Contents

库存中心分库分表设计

Inventory Core Sharding Design

一、背景

  • 1、库存与串码再领域模型上分离。库存属于逻辑概念,串码与实物一一对应,属于实体概念。
  • 2、串码数据量较大,需要做分库/分表,优化串码查询性能
  • 3、在线串码表需要定期备份,将历史数据迁移至历史库,优化串码查询性能。
  • 注: 所有非在线交易类的串码问题参考:串码详情ES大宽表方案

二、数据分片方案

  • 串码中心数据分片方案的出发点:
  • 【问题1】解决大量串码信息存储问题
  • 【问题2】解决数据分片后在线交易串码精准查找问题(海外VRS出库场景,指定imei1货imei2)。
  • 【问题3】解决数据分片后在线交易串码模糊查找问题(如v-work扫码出库场景,给定任意一个数字(可能是imei1,imei2,itemCode,boxNo等任意一种属性)查找对应的串码信息).

2.1 方案一 – 只分表不分库

  • 【优点】
  • 所有数据均在一个库中,不存在跨库的分布式事务,不存在多数据源处理。
  • 代码逻辑较为简单,只需要维护分表的逻辑即可。
  • 【缺点】
  • 串码库发生抖动,所有代理的所有串码相关业务都受到影响。
  • 单库的性能瓶颈,数据量增大后无法水平扩展数据库的性能。
  • 不能解决问题2和问题3 —- imei1,imei2,meid,boxNo,itemCode通过同一个接口扫码出库实现不了,调拨场景也无法准确定位到这批串码(imei1……)所在的分库。

2.2 方案2 – 按代理分库

  • 【优点】
  • 每一个代理的数据在一个库中,串码库发生抖动不会影响其他的代理。
  • 分多个库的性能比方案一中单库的性能高很多。
  • 【缺点】
  • 代理间的调拨,涉及多个数据源的分布式事务问题。
  • 不能解决问题2和问题3 —- imei1,imei2,meid,boxNo,itemCode通过同一个接口扫码出库实现不了,调拨场景也无法准确定位到这批串码(imei1……)所在的分表。

2.3 方案3 – 按UUID分库且分表

2.3.1 【前提】
  • MES 一代串码同步到v-work库存中心时,有库存中心为每条串码生成全局唯一的UUID(和平台组沟通,可以较高的效率生成全局唯一的UUID)
  • 现有的业务数据规则:
1
2
3
1. IMEI1、IMEI2固定是15位数字(8位tac+6位流水+1位校验码)例如:“865224038614541”
1. MEID固定是14位字符(8位头+6位16进制的流水)例如:“A00000754A0AEB”
1. BOX_NO手机:18位字符;IOT :BOX_NO 长度不固定
2.3.2 【串码映射表】
  • 串码信息表 (1) –> 串码映射表(N) –> 串码详情表
  • 串码映射表,
uuidvalue备注
123456780123456865224038614541imei1
123456780123456145416830422568imei2
123456780123456A00000754A0AEBmeid
123456780123456210616830422562boxNo
123456780123456264224038614542itemCode
  • 库存串码表
uuidfirst_agent_codeime1ime2meidboxNoitemCodearehouse_codeaccount_idsku_code
123123123545454545463636363637373737383838332112393939393654321100010001456789

  • 【优点】
  • 分多个库的性能比方案一中单库的性能高很多,可以解决大量串码存储问题
  • 可以解决问题2和问题3
  • 【缺点】
  • 串码映射表冗余了很多数据,存储空间增加
  • 串码映射表大量的数据存储将会带来性能瓶颈。(1亿串码*5个映射维度 = 5亿的数据量)
2.3.3 【串码映射表、库存串码表分库分表】
  • 在2.3.1【前提】中,可以发现业务长度的数据是有一些规律的,可以利用业务数据的长度特性针对2.3.2【串码映射表】做分库分表处理。
  • 根据业务数据的长度,将串码映射表拆分为3个库(每个库按uuid分为512张表):
  • 1)长度为15的imei1和imei2与uuid的映射库
  • 2)长度14的meid与uuid的映射库
  • 3)长度不为14且不为15的boxNo,itemCode与uuid的映射库
2.3.4 【扫码出库场景分析】
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@startuml
交付中心 -> 库存中心: 1、调用库存中心扫码出库接口
库存中心 -> 库存中心: 2、库存中心扣减库存
库存中心 -> 串码中心: 3、库存中心\n携带串码调用串码中心
串码中心 -> 串码中心映射表: 4、根据串码长度找到对应的分库 \n 假设分别扫码 \n 1 imei1=100 2 boxNo=200
串码中心映射表 -> 串码中心映射表: 5.1根据imei1长度\n找到对应的分库serialCode_15 \n 根据100%512得到这条数据所在分表,\n 并得到100对饮的UUID
串码中心映射表 -> 库存串码映射表: 5.2根据uuid%5找到对应的分库\n 根据uud%64得到这条数据所在分表,\n 并得到100对饮的UUID
串码中心映射表 -> 串码中心映射表: 6.1根据boxNo长度找到对应的分库 \n serialCode_not_15_14 \n 根据200%512得到这条数据所在分表,\n 并得到200对饮的UUID
串码中心映射表 -> 库存串码映射表: 6.2根据uuid%5找到对应的分库\n 根据uud%64得到这条数据所在分表,\n 并得到200对饮的UUID
库存串码映射表 -> 库存串码映射表: 5.3 在iemi1=100的分表中\n 进行对串码行的出库操作
库存串码映射表 -> 库存串码映射表: 6.3 在boxNo=200的分表中\n 进行对串码行的出库操作

交付中心 -> 库存中心: 1、调用库存你中心扫码出库接口
@enduml
  • 以上步骤5和步骤6涉及跨串码中心2个库的分布式事务,spring支持跨多数据源事务
2.3.5 【串码数据规模预估】
  • 【串码映射表】
  • (1) 串码映射表容量预估:
  • 在2.3.3【串码映射表、库存串码表分库分表】中串码映射表的分库分表规则:
  • 3个DB * 512张表/DB * 500~1000万数据/表(为确保MySql性能最优) = 76.8亿~153.6亿,即串码映射表最多可容纳153.6亿条串码与UUID的映射数据
  • (2) 业务所需映射表容量预估:
  • 按现有手机业务规模(1亿销售/年),同比预估iot未来业务规模(一亿销量/年):
  • 【1亿手机+1亿iot】*5 (imei1,imei2,meid,boxNo,itemCode会对应5条映射记录) =10 亿,即未来业务规模对应的串码映射表数量为10亿
  • 【结论1】2.3.3【串码映射表、库存串码表分库分表】中将串码映射表分为3个库,每个库分512张表,完全可以满足未来业务需求
  • 因串码映射表是很少的2列(UUID和业务码值),因此每条串码映射的数据量都很小。
  • 假设UUID为64位(最大位数),业务码值也为64位,即一条串码映射的数据量为:128位的字符串,即128字节(java字符串中,英文,数字,符号各占1字节),即0.1KB
  • 为了应对未来的变化,假设串码映射表单条数据增加到0.5kb
  • 串码映射表容量最大:76.8亿~153.6亿 * 0.5KB = 38.4 ~76.8亿KB=3.8T~7.6T
  • 业务所需映射表容量:10亿*0.5KB = 500GB
  • 假设一个Redis/ES节点内存容量 = 100GB,即支撑手机1亿/年,iot1亿/年,需要10个Redis/ES组成的cluster集群(每个Redis/Es节点一主一从,单节点就要5个)
  • 【结论2】为了提升串码映射表的性能,支撑手机1亿/年,iot 1亿/年的销量,可以将串码映射表数据存储在redis中,缓存时间为1年。如果业务数据持续增大,可以缩小缓存时间范围(如缓存半年,超过半年的查DB)
  • 【库存串码表】
  • (1)容量预估
  • 在2.3.3【串码映射表、库存串码表分库分表】中串码库存串码表的分库分表规则:
  • 5个DB * 64张表/DB * 500~1000万数据/表(为确保MySql性能最优) = 16亿~32亿,即库存串码表最多可容纳32亿条串码与UUID的映射数据
  • 【结论3】库存串码表最多容纳32亿条数据,以手机1亿/年,iot1亿/年的销量欸参考值,预计库存串码表可以容纳16年内的实时交易数据(根据业务需求,历史库存串码信息数据可以清理到历史库)

三、总结

  • 1)串码映射表MySql: 最大业务容量-2亿/年(手机,IOT各1亿).最大容量 – 在MySql分为3个库,每个库512张表,预计可以容纳76.8亿~153.6亿条串码记录,预计可以容纳30年内的串码映射记录
  • 2)串码映射表缓存:优化SQL查询路径,将串码映射表做缓存,最大业务容量(手机1亿/年,iot1亿/年)需要500GB内存,约10个Redis/ES集群,含主备
  • 3)串码映射表缓存容量增长:【方案1】增加Redis/ES 集群中的节点数量。【方案2】增加新的K-V型中间件(如淘宝tiar),纯内存与磁盘顺序写并存。
  • 4)库存串码表:最大容量可以容纳32亿条串码数据库,按最大业务容纳(手机1年/年,IOT1年/年)计算,预计可以容纳16年内的实时交易数据。