缓存一致性问题

问题

配置中心的原来实现是先更新DB,再更新cache,这个两个操作加起来不是原子的。无法做到操作的一致性。可能会导致DB 更新成功,cache 失败,会导致

cache中是脏数据。

思考

如何保证这两个操作后数据的一致性?

参考

分布式事务一致性:

* 强一致性 : XA,mysql 支持XA,但是redis不支持,强一致性的方案无法使用。

* 最终一致性 : 保证数据的最终一致性,能够容忍短时间数据的不一致。

修改实现

修改配置后,可以容忍一段时间缓存中数据是旧数据的情况,可以使用最终一致性。

实现一

设计个记录更新表。记录下修改操作。

更新配置可以使用如下伪代码

BEGIN TRANSACTION
	update xxx set xx=xx;
	INSERT test(xx,'status') VALUES('xxx','0')
COMMIT

后使用定时任务,定时扫描这个记录更新表,使缓存失效。此方案亦可改造成mysql 更新数据+消息队列发送一条异步更新cache的消息。

得注意消息的先后顺序,以及消息的消费的幂等性。

实现二

先更新redis并记录一笔更新操作写入到redis中的list数据类型的队列中,这个使用lua脚本操作。

启动两个线程监听更新队列,备份队列,一个执行写入DB 操作,一个执行检查备份队列中的数据。

线程一将更新队列中的更新log写到DB中。从更新队列中取出数据使用rpoplpush 命令将数据移出队列并push到另一个备份队列。

取出数据后更新DB,若DB 更新成功则删除备份队列中的数据。

线程二检查备份队列,将队列中的数据重新加入到原队列中。

此实现配置表中必须有个版本号,保证处理队列消息的幂等性以及对过期消息丢弃。

posted on 2016-09-19 00:01  liaozq  阅读(564)  评论(0编辑  收藏  举报