订单号的生成,这是每个交易系统都碰到的问题。方案有很多种,比如uuid、时间戳+随机数、数据库自增长等等。这些方案或多或少都存在一些问题。比如uuid索引性能低下,时间戳+随机数存在可能重复的问题,数据库自增长如果是分布式多表的情况显然是不合适的。更蛋疼的是笔者所在公司业务方提出蛋疼的要求:订单号的格式为yyyymmdd+7位有序数字,比如当天第一笔为yyyymmdd0000001,第二笔就是yyyymmdd0000002,以此类推。公司不怕从订单号看到订单的业务信息,就是这么牛逼,不服?Ok,我们来聊聊当时的解决方案。
1.转变思路
上文的订单生产方案可以看到有一个共同的特点:在使用时生产!!!我们知道,计算机的任何行为都会有一定资源开销。来分析一下订单号的格式为yyyymmdd+7位有序数字的性能问题:如果是传统的做法,就是查询订单号当日的最大值+1作为当前的订单号,因为查询最大值牵涉到数据库记录排序的问题,这就是一个很大的性能开销,况且如果是多库多表的情况就更糟糕了。
改变思路,对,改变思路,因为上面所例举的方法都是在创建订单时即时生成的有序订单号,但可以在生成订单之前提前生成订单号,那么就可以减少这部分的开销了。
2.引入redis
1)创建定时任务,每天凌晨4点生成次日订单号,由于凌晨4点交易量一般不会高,为了减少对主业务的影响故选此时间段。
2)所有生成的订单号放入一个双向队列里Deque,队列Deque保存在redis的<key,value>结构中,其中key为yyyymmdd+7位有序数字,value为双向队列Deque。

通过预生成订单号并利用Redis队列存储,解决传统订单号生成中的性能瓶颈,避免订单号冲突,减少数据库负担。
最低0.47元/天 解锁文章
1530





