本文主要的内容是,在构建支付系统时,涉及到的各种ID、NO、凭证号的生成规范,对应的关键思考点,以及实现方案。
需要将ID分类
ID的生成分为3类:凭证号、普通ID、自增ID。
凭证号
支付系统中,一部分ID需要作为凭证号存在,支付整体来看,具有一定的业务意义。需要区分开来。
自增ID
完全不需要对外,无业务意义,为了性能和有序性而存在。
设计目标:
- 局部唯一
- 局部有序
- 性能好
- 不作为分库分表的依据
- 具体ID生成策略:
- 数据库物理主键。
+1自增长,建议每个表都增加。
普通ID
系统内部ID,没有整体支付的业务意义。
设计目标
- 全局唯一
- 趋势递增
- 分段可配
- 可读性
- 可作为分库分表依据
- 性能有保证
- 具体ID生成策略
凭证号25位字符串,组成规则如下:
时间戳(8位)+递增序列(12位)+分库分表标识位(5位)
redis自增的实现
redis自增:借助redis单线程通过incr、incrby实现唯一自增id。
redis自增1方式
redis> SET rank >> 0 OK
redis> INCR rank >> (integer) 1
redis> GET rank >> "1"
说明:内部自增,每次+1即可。
递增序列到了最大值(不一定非要到物理最大值,可以预留一个缓冲段)后,执行SET rank,进行重置(0)。
凭证号
系统内部ID,从支付全区来看,是连接业务的锁链。(逻辑上,有点像外健)
普通ID、自增ID,直接通过ID生成器获取,而凭证号需要在凭证服务(Voucher)落地处理。
设计目标
- 全局唯一
- 趋势递增
- 分段可配
- 可读性
- 可作为分库分表依据
- 性能有保证
- 具有整体业务意义
凭证号有哪些?
目前的需求来看,以下3类数据,需要通过Voucher获取凭证号作为ID的有如下几个:
- 交易凭证号
- 支付凭证号
- 入账凭证号
原始凭证(外壳)
除此之外,每次请求的通用信息(如调用的接口、合作方ID、字符集、签名、签名类型、买家IP、操作员、回调地址等),这也将作为每次资金变动的原始凭证的一部分而存在。
ID生成策略
redis自增:借助redis单线程通过incr、incrby实现唯一自增id
分段配置
凭证号29位字符串,组成规则如下:
业务代码(3位)+时间戳(8位)+递增序列(12位)+有效性校验码(1位)+分库分表标识位(5位)
业务代码
301-支付,302-退款;
401-提现,402-退票
501-转账
601-充值,602-充退
701-资金冻结,702-资金解冻
时间戳
YYYYMMDD
递增序列
12位,+1递增,全局有序。
有效性校验码
1位
校验规则(不能太耗CPU,但也不能太容易猜出):
通过Luhn算法生成校验码 http://www.jianshu.com/p/193d8b84a6a1
服务间关系
其他
UUID:UUID无法保证趋势递增、不可读,不可以接受。
网友评论