2021-06-30 06:53:39
数据库与Redis数据一致性问题主要指在以MySQL作为存储、Redis作为缓存的架构中,如何保证两者数据最终一致,常见解决方案有四种,各有优缺点,适用不同场景。具体如下:
方案一:通过key的过期时间,MySQL更新时Redis不更新
优点:开发成本低,易于实现;管理成本低,出问题概率小。
不足:完全依赖过期时间,时间太短易使缓存频繁失效,太长则易有长时间更新延迟(不一致)。若读请求频繁且过期时间长,会产生很多长期脏数据。
方案二:在方案一基础上扩展,通过key的过期时间兜底,更新MySQL时同时更新Redis
优点:相对方案一,更新延迟更小。
不足:若更新MySQL成功但更新Redis失败,会退化到方案一;在高并发场景,业务server需同时连接MySQL和Redis,损耗双倍连接资源,易造成连接数过多问题。
方案三:针对方案二的同步写Redis进行优化,增加消息队列,将Redis更新操作交给Kafka,由消息队列保证可靠性,再搭建消费服务异步更新Redis
优点:消息队列可用一个句柄,很多消息队列客户端支持本地缓存发送,有效解决方案二连接数过多问题;实现逻辑上解耦;消息队列本身具有可靠性,通过手动提交等手段可至少一次消费到Redis。
不足:依旧解决不了时序性问题,如多台业务服务器分别处理同一行数据的两条请求,若MySQL中第一条先执行,而进入Kafka的顺序是第二条先执行,数据会产生不一致;引入消息队列需增加服务消费消息,成本较高,还有重复消费风险。
方案四:通过订阅binlog来更新Redis,把搭建的消费服务作为MySQL的一个slave,订阅binlog,解析出更新内容再更新到Redis
优点:在MySQL压力不大的情况下,延迟较低;和业务完全解耦;解决了时序性问题。
不足:要单独搭建一个同步服务,并且引入binlog同步机制,成本较大。
首先确认产品对延迟性的要求,若要求极高且数据可能变化,不建议用缓存。
通常场景下,方案一足够,因其没有开发成本,在读多写少且业务对延迟有一定包容性的场景中比较实用。
若想增加更新时的即时性,可选择方案二,但没必要做重试保证等。
方案三和方案四适用于对延时要求比较高的业务,方案三是推模式,方案四是拉模式,方案四可靠性更强,若愿意花功夫处理消息逻辑,可一步到位选择方案四。