麒麟v10 上部署 TiDB v5.1.2 生产环境优化实践
949
2023-04-03
【原创】分布式之数据库和缓存双写一致性方案解析(二)
引言
应该没人问我,为什么没有先更新缓存,再更新数据库这种策略。
博主当时觉得,这种更新策略比较简单,没必要多做说明,结果太多人留言给博主,问我为什么不说这套方案?好吧,博主先跟大家道个歉,是我的问题。所以再开一文,把这个方案说明一下
正文
在【招财进宝】项目中有一个技术的细节值得拿出来说说,淘宝商品详情页面每天的流量在10亿以上,里面的内容都是放在缓存里的,做【招财进宝】的时候,我们要给卖家显示他的商品被浏览的次数,这个数字必须实时更新,而用缓存的话一般都是异步更新的。于是商品表里面增加了这样一个字段,每增加一个PV这个字段就要更新一次。发布上去一个小时数据库就挂掉了,撑不住这么高的update。数据库撑不住怎么办?一般的缓存策略是不支持实时更新的,这时候多隆大神想了个办法,在apache上面写了一个模块,这个数字根本不经过下层的web容器(只经过apache)就写入一个集中式的缓存区了,这个缓存区的数据再异步更新到数据库。好像什么问题,到了多隆手里,总能迎刃而解。
好吧,如果没耐心的读者,直接看博主的总结吧。上面巴拉巴拉一堆,就是说,当时他们有一个读多写多的场景,然后多隆大神用了先更缓存,再异步更新数据库的策略。难道淘宝的大神没发现线程安全问题?不是的,上面提到的场景具有一个特殊性。我们先摘取关键一句话
于是商品表里面增加了这样一个字段,每增加一个PV这个字段就要更新一次
update product_tb set number = number+1 where product_id =xxx
大家注意到了么,并发执行这句SQL并不需要关心执行顺序。哪个更新线程先执行加一的SQL语句 ,与操作顺序有什么关系呢?再说的通俗一点,假设我们同时有请求A和请求B进行更新操作,那么会出现(1)线程A更新了缓存(2)线程B更新了缓存(3)线程B更新了数据库(4)线程A更新了数据库因为他们这个时候执行的sql是无序的,所以上面的步骤(3)和步骤(4)哪一个步骤先执行,并没有关系。最终结果一定是一致的。容博主啰嗦,来个实例,假设表product_tb如下
product_id | number |
---|---|
1 | 3 |
这时请求A和请求B同时对product_id为1的数据进行更新操作,无论是按出现并发问题时的顺序 | |
(1)线程B更新了数据库,进行加一 | |
(2)线程A更新了数据库,进行加一 | |
还是正常的顺序 | |
(1)线程A更新了数据库,进行加一 | |
(2)线程B更新了数据库,进行加一 | |
最终结果都是 |
product_id | number |
---|---|
1 | 5 |
ok。说到这里,大家应该是懂了。换句话说,如果此时,操作的sql是有序的,就会出现最上面说的线程安全问题。所以,希望大家针对问题多思考总结。 | |
给大家留一个思考问题? | |
如果此时是一个读多写多的场景,又要求更新数据库的操作必须严格保证顺序,那这个时候怎么保证缓存和数据库的一致性?大家可以来我的博客留言。 |
总结
本文是对上次文章的一次文章的一次补充。只怪博主思考问题太过简单,给大家留了个坑。因此再开一篇文章进行补充说明。希望大家能够有所收获。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。