缓存和数据库数据一致性探讨
数据库和缓存的更新方式
1.先更新数据库,再更新缓存
2.先更新缓存,再更新数据库
3.先更新数据库,再删除缓存
4.先删除缓存,再更新数据库
5.使用canal更新缓存
一、先更新数据库,再更新缓存
1 | db.update(key,val) |
- 1.如果数据库更新成功,缓存设置失败,结果数据库是新数据,缓存是旧数据,导致数据不一致
- 2.高并发场景下,A线程更新数据库
status=1
成功后卡住,B线程更新数据库status=2
,并更新缓存成功,然后A线程恢复,把缓存刷成status=1
,此时数据库status=2
和缓存status=1
数据不一致
结论:不推荐
二、先更新缓存,再更新数据库
1 | cache.setex(key,ttl,val) |
- 1.如果缓存更新成功,数据库设置失败,结果数据库是旧数据,缓存是新数据,导致数据不一致
- 2.高并发场景下,A线程更新缓存
status=1
成功后卡住,B线程更新缓存status=2
,并更新数据库成功,然后A线程恢复,把数据库刷成status=1
,此时数据库status=1
和缓存status=2
数据不一致
结论:不推荐
三、先更新数据库,再删除缓存
1 | db.update(key,val) |
- 1.如果数据库更新成功,缓存删除失败,结果数据库是新数据,缓存是旧数据,导致数据不一致
- 2.高并发场景下,A线程更新数据库
status=1
成功后卡住,B线程更新数据库status=2
,并删除缓存成功,然后A线程恢复,删除缓存,此时不影响数据一致性
结论:不推荐
四、先删除缓存,再更新数据库
1 | cache.del(key) |
1.如果缓存删除成功,数据库更新失败,此时不影响数据一致性
2.高并发场景下,A线程删除缓存后卡住,B线程删除缓存,并更新数据库
status=2
,然后A线程恢复,更新数据库status=1
,此时不影响数据一致性
结论:可以接受五、使用canal更新缓存
canal 主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费
工作原理
canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
canal 解析 binary log 对象(原始为 byte 流)
- 1.异步执行,数据最终一致
- 2.高并发场景下,会产生短暂的不一致,但是数据会最终一致
结论:若对实时一致性要求不高推荐
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 boystar的博客!