Sequence :: 为什么需要使用独立的序列号生成服务,而不是用自增长列?

几年以前,我们决定将所有Oracle中的序列号对象(Sequence)都集中起来,很多业务(包括交易、支付、充值)的主键都是依据序列号来依次生成的。后来又开发了自己的序列号生成服务来接入所有的应用,自研的序列生成机制完全没有单点,具备足够的处理参力,并且允许多机房布署又不需要进行数据保护,因为这样更加有利于应用问题的排查。

oneproxy_business_sequence

在第一次将系统从Oracle迁到MySQL时,曾经使用自增列来生成业务主键,然而在经历了几次测试环境MySQL主从切换后,发现双活的MySQL主备很容易出现双写现象,即主备同时进行数据写入,从而造成主键冲突,出现了业务编号重复的现象,不管是基于DNS的切换还是基于应用的动态IP推送,面对上百个应用程序节点,都不能清爽地避免脑裂现象。虽然是极少量的几条记录级别的主键冲突,但为了纠正这些冲突的主键,代价却非常之高,需要牵涉很多人,需要排查很多系统,还好是在测试环境上遇到了这个问题。

从业务层面看,支持一个业务需要很多个系统的协作,这里面可能包含多个内部系统,也可能包含与很多外部系统的交互,交互的主要内容就是业务编号(主键)以及业务的状态,所以业务主键会被多个内外部的系统所交叉引用。即使当你只搞乱了几个业务主键,但需要订下的系统数量却很多,是一件极耗时间和人力的事情,说句不好听的话,处理起来要比丢点数据还累很多。因此我们才开发了自己的分布式序列号服务,即使是用来保存序列号的数据库损坏丢失,也不会有什么影响,不需要备份才能彻底解决数据保护的问题。

我们认为很难做到IDC级别故障的数据零丢失,可以尽力减少可能的数据丢失,但不要去追求绝对的零数据丢失。重要的是以灾难发生后,能够在数据有点点损失的情况下起动应用,对外提供服务,只要业务编号没有错乱,可从不同的系统中进行交叉数据验证,控制数据丢失的影响范围,或者进行交叉数据恢复,就象磁盘RAID 5机制一样,一块盘损坏可以从其他几块盘上来进行恢复。在认真分析后,我们认为数据丢失会带来可控的损失,而业务主键的错乱会给系统带来来更大的麻烦。

如果需要这样的分布式序列号生成服务,现在可以在数分钟内使用OneProxy来布署一个了。