经常我们需要将两份相同
的数据保存成不同的数据结构
。比如一边是代理商政策录入系统,但代理商维护的数据不能直接拿来使用。并且为了方便代理商修改,我们不能让代理商信息保存成我们可以直接使用的数据结构,而且可能两者保存。则我们需要又一个中间系统进行数据的转换。
case
这里我们定义A系统为代理商政策录入系统,B系统为业务查询系统。到这里是不是有点像读写分离的做法,录入和读取分成了2个系统。但要注意的是这里读写库的数据类型是不一样的。A系统作为录入系统直接落库,B系统存储业务直接可以使用的数据,需要支持大量查询,可以将数据存到redis或内存中。
实现这个系统需要保证4点
-
顺序性
-
时效性
-
一致性
-
可靠性
顺序性是指在我连续修改2条记录的时候,要保证我修改的顺序。否则的话,比如我先修改为1在修改为2,顺序错了记录的信息就可能是1了。
顺序性
首先我们来看一下顺序性是怎么实现的。
从A系统中取出数据
对数据进行处理,并记录
我们需要在C系统中做到这两件事情,而且需要在这两步中都保证顺序性。
其中从A系统中取数据,有两种方案:
-
监听数据库binlog
-
主动发送MQ消息
如果使用binlog的方式则在取数据的时候就不需要保证顺序性了,因为binlog是有顺序的。而如果使用MQ的方式则需要我们自己来保证顺序性,因为系统先收到那个消息有时候是可能逆序的。
所以需要将修改同一条记录的消息放到一个MQ队列中,来保证其有序性。上图中每一条黄线代表一个消息队列。
对数据处理
这里我们可以使用通用的处理方法进行处理,对应操作的顺序可以继续用队列来保证。
同一条记录的任务可以放到同一个队列中进行处理。上图中每一个第一阶段的队列在第二阶段都有相对的队列来处理数据。
一致性
数据一致性的兜底方案采用一个定时任务进行增量diff。如下图在正常数据同步之外,对A/B的数据进行定时diff。
时效性
所需时间主要有
-
A数据库读取数据的时间
-
数据通过MQ发送到C系统的时间
-
C系统处理的时间
之后B系统读取的时间不做考虑。数据库读取数据正常通过索引来优化,MQ使用kafka发送消息的时间也比较固定,C系统处理为保障顺序性时的每一个队列分配一个线程并发处理。
可靠性
这里使用ZK做了任务管理,超时或机器挂掉会进行重试。