“现在如果说不出几句如何保证数据一致性方案的话,觉得出去面试都丢人,尤其是缓存和数据库的数据一致性
“全程无图,请谨慎阅读
缓存对于程序性能而言,无疑是个杀手锏,但不是完美的解决方案。关键在于缓存的物理位置和数据真实保存的位置是分离的,当然这里指的是分布式缓存方案。位于不同物理位置的两份数据要想保证强一致性,理论上来说是不可能的
。
但是,程序员总是爱创造奇迹。
单说数据库,程序员们创造了事务特性,就是平时面试经常问的ACID特性的一个爱称。至于ACID的概念是什么,简单的抄袭一下:
“ACID,是指数据库管理系统(DBMS)在写入或更新资料的过程中,为保证事务(transaction)是正确可靠的,所必须具备的四个特性:原子性(atomicity,或称不可分割性)、一致性(consistency)、隔离性(isolation,又称独立性)、持久性(durability)。
Atomicity(原子性):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
回归正题,存放缓存数据的设备能否也提供事务特性呢?如果可以,是否也能够提供完整的ACID特性呢?
如果你看过几篇缓存和DB一致性的文章就会发现,无论你先更新DB后更新缓存,还是先更新缓存后更新DB,或是先更新DB后删除缓存.....无论怎么折腾,都不能保证数据的强一致性
。
悲哀吗?看了这么多文章居然不能解决这个问题。
“多个不同的外部设备数据要想保证强一致性,除非都能提供事务的接口,还需要引入
事务协调器
拿缓存和数据库的一致性保证来说,没有协调器根本不可能保证强一致性。所以业务让步了:保证最终一致性
即可
最终一致性容易保证吗?其实也不容易
看有些人已经给你出解决方案了:引入MQ。因为MQ一是能保证消息的可靠性到达和可靠性消费,二是MQ是解耦利器。很多数据一致性的方案都会借助MQ的特性来做最终一致性。
分布式的铁律CAP原则,大家都应该知道,但是我觉得最应该熟记的是BASE理论。
利用MQ来做数据库和缓存一致性,本质上也属于BASE理论的实践。在业务上做出让步,遗漏短暂的中间状态来达到最终目的。
分布式锁可行吗
客户端可以读到错误数据的原因源自数据的中间状态,如果在数据变动的整个过程不允许其他请求读取也可以达到数据上的强一致性。
什么意思呢?在一个数据的变动过程中,不允许其他请求进来,等到缓存和数据库全部修改完成再允许其他请求进来,这就是业务上的分布式锁控制一致性方案。
无奈,一般的分布式锁性能都比较低,这个低是对比无锁的情况下来对比的,相对于肉眼时间,还是很快的。最主要的是,如果引入分布式锁的技术,那又将面临分布式锁的一系列问题。
“最后强调一点:缓存一定要设置过期时间,这是保证最终一致性的兜底方案
往期回顾
#
愚蠢的领导才会用程序员祭天!!
#
【另类见解】秒杀并非高不可攀
#
我把负载均衡讲出了花,领导却不给我涨工资
#
一个搜索需求搞垮微服务