Skip to content

Latest commit

 

History

History
37 lines (32 loc) · 2.4 KB

订单分库分表问题.md

File metadata and controls

37 lines (32 loc) · 2.4 KB

电商系统中订单数据量会持续增加,对容量和访问性能产生压力,对于一般的关系型数据库来说,需要考虑拆分数据,也就是分库分表。
数据拆分之后对数据访问和聚合产生影响,需要权衡数据访问策略,采取相应的拆分策略,这里主要考虑水平拆分。

对订单数据的访问模式有以下几种:

  1. 根据user_id查找订单列表 : 用户查询自己的订单列表。
  2. 根据order_id查找订单 : 客服查询订单信息。
  3. 根据时间段查找订单列表 : 数据统计。

数据拆分策略往往是采用hash算法对某些数据组合而成的key进行运算,获得对应存放的数据库节点,即db_id = hash(key) 。
结合上面的访问模式来看,很难有一种hash算法同时满足多个维度的访问模式。
因此经常需要额外建立索引关系,这意味着额外的时间和空间成本,以及保证数据一致性的机制。

针对上面的3种访问模式,数据统计一般用于离线分析,可以单独建立额外的数据仓库。第2种访问模式是否可以避免额外建立索引关系呢?
订单是用户产生的,按照user_id拆分订单,即db_id=hash(user_id),如果产生的order_id带有db_id信息,那么就可以直接从order_id获取db_id,不需要根据order_id建立额外索引关系了。

db_id = hash_user(user_id)
order_id = create_order(db_id)
db_id = hash_order(order_id)

如果再考虑未来可能的数据迁移,order_id中不直接带有db_id信息,而是带有和hash_user相同的拆分数据,即order_id = create_order(user_id),这样就实现了两种hash算法的统一。

以某项目为例,user_id和order_id都是整数,用于拆分的key为 user_id最后一位,即(user_id mod 256) ,首次拆分成8个数据库,未来可能继续拆成16 ,32 ,64 ,128,256个数据库。

db_id : 0 1 2 3 4 5 6 7    
db_id = ( user_id mod 256 ) mod 8
order_id = time × 256 + ( user_id mod 256 )
db_id = (order_id mod 256 ) mod 8

再拆成16个,每个节点裂变成2个节点。

db_id : 0->(0 8),1->(1 9),2 ->(2 10),3->(3 11),4->(4 12),5->(5 13),6->(6 14),7->(7,15)   
db_id = ( user_id mod 256 ) mod 16
order_id = time × 256 + ( user_id mod 256 )
db_id = (order_id mod 256 ) mod 16

最终,通过把拆分信息合并到order_id中,最终实现了user_id和order_id映射db_id的统一。