Redis实时性数据与DB数据同步一致性问题研究
目录
实时性的数据,一般业务管理数据都是基本上不发生变化的,而发生随时不停发生变化的数据我们将之称之为实时性高的数据叫实时数据。实时数据很难保证在不同数据源下的一致性,除非查看的是某一时刻的数据快照(历史快照),否则很难保持不同数据源数据之间没有差异。所以,从实践中得出的结论是:异构多数据源保证实时数据一致性是一个伪命题,缓存的使用具有不可逆的特性,大多数情况下缓存不能当作真实数据源。
预设场景
欲实现移动App人员位置管理,要求:
1、展示用户总数和在线数量,数据交互到REDIS。
2、通过用户在线情况,同步到数据库DB保留在线、离线和位置信息。
3、验证两边的在线数量是否能保持一致。
问题分析
1、使用REDIS管理用户在线状态数据,网络状态未知的情况下,用户频繁上线、离线。
- a.用户REDIS高效缓存位置数据
- b.存在网络抖动(不确定性因素)
2、从Redis同步数据到DB本身是一个传统使用方式的反向操作,一般地都是将DB数据加载到REDIS。
- a.传统使用方式REDIS是DB数据的缓存
- b.使用redis主从同步(但是数据库级别的查询分页是个问题,不满足需求)
- c.DB更新实时性高的数据批量处理和中间环节存在时间差问题
3、推测结论:缓存不可以作为主要的数据源使用,而应该以DB为主缓存为辅,使用缓存主要是为了提高数据加载效率。
流程设计
下面是一幅App心跳上传的位置分发到RabbitMQ进行位置管理的服务,位置保存在REDIS中,DB是PG(Postgresql)。
- MQ分发逻辑:在OnlineMQ、KeepLiveMQ和OfflineMQ进行消费的时候加了二级队列进行处理,RabbitMQ是异步执行消费。
- 在二级队列:Java程序并发队列批量处理用户状态位置数据,线程批量处理,是为了提升MQ本身消费的效率问题。
- 数据维护:Quality Service 和网格聚合都是为了维护用户在线时间过期的辅助服务。
- 用户30分钟内无位置和心跳上来即离线。
- 在线有心跳但没有位置的系统进行保活。
- 用户有心跳有位置的为在线。
- 真实批量处理线程消费必须要有休眠时间,防止空转调度CPU,这里设置的是50ms(无论设多小都是一个时间差)。
- 在正常情况下,离线、上线、保活队列数据应该是互斥的。
实践验证
回头贴上效果图。
问题结论
- 异步的操作实时性不可控。
- 多个数据源非主从和集群模式要同步实时数据结果是不可信的。
- 缓存的主要功能是辅助数据库数据服务而非反过来使用。
- 异构数据库数据同步实时性没法保证。