缓存一致性的实现
缓存一致性是指缓存中的数据与数据库之间的数据保持一致,确保用户读取到的是最新、最准确的数据。
在分布式系统中,由于多个节点可能同时访问和修改数据,因此保证缓存一致性非常重要
解决方案
当数据更新时,我们最好删除缓存,下一次查询缓存时会出现未命中,这时需要重新读取一次数据库并加载到缓存中,这时缓存中的数据就是最新的数据。
如果直接更新缓存可能会涉及复杂的逻辑和额外的开销,影响缓存服务器的性能
如果先删缓存,再更新数据库,可能会出现一些问题:
线程A删除缓存后,线程B读取到旧数据并更新到缓存中,而线程A随后更新数据库,导致缓存中存储了旧数据。
如果先更新数据库再删除缓存,也有可能出现一些问题:
在线程A更新数据库和删除缓存之间,可能有线程B读取到了缓存中的旧数据。但最终缓存与数据库的数据是一致的,并且都是最新的。
经过对比可以发现,
如果先删除缓存,再更新数据库,如果没有及时更新,可能会导致缓存长时间地储存旧数据。对业务影响较大
而先更新数据库,再删除缓存,只存在一个很小周期的缓存与数据库不一致的情况,因此,对于一致性要求不是很高的业务可以选择先更新数据库,再删除缓存,保证缓存一致性。
列车余票如何保障缓存数据库一致性
但是先更新数据库,再删除缓存,如果出现删除缓存失败的情况,缓存中储存的还是旧数据,就会出现缓存数据库不一致的情况,并不能保证系统的高可用。
因此像列车余票扣减这种对一致性敏感的业务,最好还是通过 Binlog 异步更新列车缓存,实现缓存一致性。
一、利用Binlog异步更新缓存
- Binlog记录数据变更:
- 当列车余票数据在数据库中发生变化时(如用户购票导致余票减少),MySQL会将这一变更记录到Binlog日志中。
- Canal监听Binlog:
- Canal是一个基于MySQL增量日志解析的中间件,通过监听Binlog的变化,可以实时地解析出Binlog中的数据变更信息。
- 异步更新缓存:
- 然后Canal将解析出的数据变更信息发送到消息队列中。
- 购票模块中的缓存同步服务 订阅消息队列中的消息,并根据消息中的数据变更信息,异步地更新缓存中的数据。例如,如果数据库中某趟列车的余票减少了,缓存同步服务就会相应地减少缓存中该趟列车的余票数量。
二、优势分析
- 高可靠性:
- 通过消息队列的持久化机制和重试机制,可以确保数据变更信息能够可靠地传递到缓存系统,并成功地更新缓存中的数据。即使缓存更新失败,系统也能够在后续的重试中成功更新。
- 实时性高:
- 由于Binlog的写入和监听都是异步进行的,并且这些过程通常具有较高的处理速度,因此可以确保缓存中的数据与数据库中的数据之间的延迟非常小。
- 自动化与减少人为错误:
- 因为Binlog更新缓存的过程是自动化的,不需要人工干预或额外的触发机制。这大大减少了由于人为错误或系统延迟导致的缓存更新不及的问题。
总结
所以在对一致性要求不是很高的业务,可以选择先更新数据库,再删除缓存。
像列车余票扣减这种对一致性敏感的业务,最好还是通过 Binlog 异步更新列车余票缓存,实现缓存一致性。
缓存一致性的实现
https://xichicheng.github.io/2024/11/20/缓存一致性的实现/