接上篇,时间长了,思路都断了。本来这章要写流水号的使用场景,一看内容第三章已经写得差不多了,直接跳过。
4、流水号的技术实现
-
流水号的生成
根据上面的分析,全局流水号是代表一个服务场景的,是用户向应用系统发起的一次服务请求,如果把全企业所有的应用系统看做一个整体的话,那么第一次向这个有机整体发起访问请求的系统就是生成全局流水号的时间。一般情况下,业务发起方都是渠道,也就是我们所说的人机交互界面,再通俗点是有前端页面的系统。特别的,也存在直接对外提供的服务接口,比如银企直连、支付接口以及其他的金融开放服务,此时,负责生成全局流水号的就是提供服务开放接口的系统;另外还存在系统后台自动执行的定时或批量任务,其全局流水应是批量触发系统,如果是全行作业统一管理,则统一作业管理系统生成,如果各自独立,则业务触发系统生成。
请求流水号是上游向下游系统发起请求的时机由上游系统生成的,代表的是一次请求的实例。
-
有意义还是无意义?
现在的技术倾向是流水号无意义化,一是从性能角度考虑可以更快的生成流水号,二是将流水号和业务解耦,流水号只充当纯粹的技术主键,业务属性由具体的业务字段去承载。但是很多企业和系统并没有这种勇气直接抛弃流水号的中的业务属性,这也有他们的理由,一是习惯使然,通过流水号的解析可以直接获取很多信息,在很多只有流水号的场景可以简化数据库的访问;二是如果这个流水号是对外开放的,比如业务员,他们会更希望看到有规律的一组数字;三是使用有意义的流水号对于问题定位,在没有统一的日志分析运维平台的情况下,的确可以节约时间。说了这么多,流水号中到底应不应该用有意义的属性?你自己去判断。
-
流水号的编码规则
既然说是编码规则,前提就是说选择了有意义的流水号的情况。一般情况下编码要跟使用目的相结合,比如对于全局流水号,你希望知道是哪个系统发起的、什么时间发起的、什么机构发起的等等,那么流水号中就可以把这些要素编进去。有些银行希望知道柜面的业务是哪个柜员发起的,那么也可以把柜员编进去。分布式环境下,为了快速定位实例,也可以把实例编进去,一句话,需要什么就把什么编进去。以下是一些可供参考的维度:
系统编码
日期
机构
用户
实例码
业务类型
校验码
顺序码
-
高并发下的流水号生成
流水号的记录有很多种方式,常见的还是数据库表记录和sequence的方式,使用可持久化缓存也是一种方式。高并发下的处理方案无非是将于数据库的IO操作转化为对内存的操作,具体实现上是从数据库中一次性取出多个seq,例如一次性取出1000个放到缓存中,如果是数据库记录,则数据库序列号一次性+1000,如果是sequence,则sequence步长调整为1000,使用的时候再从缓存中获取。
如果是分布式,有两种方式避免分布式流水号重复,一是在流水号中增加实例号来区分;二是使用数据库的排它锁,避免多个应用同时从数据库中获取流水号。
-
流水号的记录与检索
流水的记录常见也是两种方式,文件和数据库,对于关键的交易流水,一般都会登记的数据库中,对于一般性的服务访问流水很多系统只记录到日志文件中。交易流水由于存在后续交易的可能性,如上篇中所说的基于原交易的查询、冲正、补录等操作,对流水的查询能力要求比较高,需要应用系统能根据全局流水号、请求流水号、后台系统流水号等多种维度查询,这种实时查询服务关系型数据库系统最有优势,所以存数据库还是不二选择。
而对于一般服务访问流水,可能没有业务含义,只是单纯的代表一次服务请求,大多数查询服务都是这种类型,这种流水只记录服务流水日志即可,也可以将这种流水通过大字段结构化文本的方式记录到数据库中;这种类型的数据如果没有专用的分析工具在使用和检索的时候比较费时费力,通过人肉运维的方式显然比较原始,现在的大数据分析平台对于这种类型的数据处理起来得心应手,联创智融也开发了一个专门的日志分析平台,iLog专门用于处理这种大文本交易流水,并且具有还原跨系统交易链路的能力,是系统运维的好帮手哦。
结语
结束的有点仓促,都怪这个咖啡馆空调给的太低了,太想逃离了,快点打完了事。
The End.