数据分片(Sharding)设计问题一例

Question:假设一家 C2C 网站,数据库中某表存储买卖双方交易的数据信息,对于一条交易来说,买卖双方数据具有一定程度的耦合性,比如卖家的状态更新对应买家的状态也会更新,对于一个中大规模的电子商务网站,架构师在设计中如何考虑数据分片的问题(假定该表随着数据的膨胀必须拆分)?

Answer:对于一个中大规模的电子商务网站,随着网站的不断发展,其相应的数据规模会不断膨胀。数据分片技术是使网站得于实现可扩展性的一种常用解决方案。对于 C2C 类型的网站,由于交易记录不容易进行水平的数据分割,因此对于这样的应用处理要再进行细分:

  • 买卖双方交易的信息,具备较高的时效性,即交易全部完成后就不会再有更新,因此这部分数据可以与正在交易中的数据区分开来,并可以单独分表,定时归纳。具体的做法可以采用水平分割的数据分片技术,比如可以根据用户号码段范围进行切片,把不同的群体划分到不同的 DB 上,这样可以很好的进行横向水平扩展(Scale Out)。它可以很好的突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。
  • 对于正在交易中的数据,主要根据时间进行分表。如果分的更细,则可以分三个表,但是这样在事务保证方面则要复杂很多,不建议这样做。

这个问答是《程序员》杂志架构师接龙栏目的第一期的内容。提问者是我,回答者是腾讯研发总监王速瑜先生。其实我抛出问题后当时还真不知道接龙的是哪位,只是知道会是百度或是腾讯的朋友来回答,当然我也对这两家的数据处理方式都是比较感兴趣的。最后刊登的内容或许让很多人觉得不过瘾 — 如果能更详细一点就好了(毕竟还有其他问题呢)。不过能够引发思考就好,这也是这个栏目的初衷吧。

对这个问题或许可以补充的是,切分或许还算是容易的事情,但是切分后用户对数据的查询多少是有点麻烦。一旦要查询历史交易信息,则必须考虑跨多个数据分片获取数据并排序的问题。交易中的数据与交易完成的数据是否做切分,是有必要根据自己的实际情况仔细衡量。要注意如对交易中的活动数据单独存放的一个表中,则还是不可避免的要产生 I/O 热点问题,而且,这个表实际上变成了一个数据队列(新的瓶颈)–新生成的交易进来,完成的交易删除或归档。这样产生的双重 I/O 压力不容忽视。

当然,这个问题的前提限制了回答的发挥,其实在设计初期也可以考虑买家信息与卖家信息分别放入不同的表中,然后对这两种属性的表再进行切分,这也是可选的途径,这样的开销是每笔交易会重复存储一条记录,而记录的变化也要在两个表中更新。对数据的一致性维护有一定的挑战。这似乎是个只带来额外开销的办法?其实也有益处–索引的设计起码会更简单一些,而用户对交易记录的定制查询也会更加方便。

数据分片(或 Sharding) 现在几乎是每个网站架构师都必须要考虑的基础问题。多数情况下,分片的粒度和方式取决于业务,慢慢地快变成可意会不可言说的话题了,你有什么建议或意见不妨留言说说。

EOF

为了避免误导,对于数据量不大的站点,首选如何利用好 Cache 吧,分片只是手段,不是目的。


5 thoughts on “数据分片(Sharding)设计问题一例

  1. Ray

    Both the question and solution need further elaboration.
    RDB sharding model depends on real world business needs.
    *If it has large merchants with of large amount of orders (for example, top 50 sellers count for 50% of orders) it makes sense to shard order/transaction data by buyer ids, meaning orders always exist in the same shards as buyer. Otherwise, putting all orders of a large merchant in one shard can cause inbalanced distribution of data and requests on certain shards with large merchants.
    *If its sellers are mostly small/medium business with limited number of order volume, it really doesn’t matter whether order data lives in buyer or seller shards.

    Reply
  2. victor666666

    以下为我的看法:
    buyer seller
    | |
    | |
    transaction
    >
    his_transaction
    对交易表和交易历史表均按时间分片,交易成功置结束标志同时进历史表,交易表和历史交易表均保存规定时间长度的数据
    至于:
    (1) 活动交易表的IO热点,这个我不太明白,插入和更新都是不同的记录,应该也不存在两个owner同时改同一条交易记录的情况吧,怎么会有热点,除非buffer block级,分片后已经避免很少了
    (2) 查询历史数据部分,这个查历史数据如限定时间范围,这个速度应该可以接受吧,如超出历史范围,则另外申请(做预计算再提供)
    看看谁有别的看法??

    Reply
  3. wuweixin

    三张表, 购买索引, 出售索引, 交易表
    针对购买索引按用户ID进行分片
    针对出售索引按用户ID进行分片
    针对交易表按时间进行分片
    每张表都分片了, 应该可以解决业务扩展了吧……

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *