前言
也不知道是谁这么有才,居然发明了1024这个程序员的节日,其他的节日都是买买买,唯独这个节日促销活动少的可怜,连早上买菜都是占了第二天重阳节的便宜,除了程序员们自嗨,也没人来给码农们庆祝了。
今天也嗨了一把,程序员的节日必须在工位上,飞速的敲着代码才是对1024最大的尊重,在这一天的结尾之际还是聊聊最近开发中的一些问题,其中数据一致性的问题确实需要梳理一下。
什么是一致性
关于一致性常常在两个地方听到,一个是数据库,另一个是分布式,两者都叫一致性,但是含义却不同。
数据库一致性
数据库中的一致性其实代表不破坏完整性,所有的数据从一个状态转化到另一个状态时不发生逻辑问题,比如说A通过手机银行给B转了100万,这件事情发生后A账户少了100万,B账户多了100万,这样就保证了数据的一致,如果转账结束A账户的钱少了100万,B账户却只多了100块,那完蛋了,A和B肯定一起去找银行打架去了。
分布式一致性
很多资料对于分布式一致性理解的都是数据冗余副本,当所有副本的数据一样时,那么此时的状态就是一致的。按照我自己的理解,这里的冗余副本不一定指的是数据形式完全一样,比如玩家在游戏服拥有金币资产200万,然后全服排行榜上的展示面板上显示资产也是200万,可能具体数据的形式不同,但这应该也是一种数据一致性的表现。
两个概念容易混淆,因为经常在分布式的架构下更新数据库,两种一致性也常常在同一个操作中有所体现。其实我也经常混着用,反正知道这个意思就好了,最近遇到的问题也是两个概念的集合,不过还是先来理解一下分布式的一致性吧
分布式一致性分类
- 强一致性: 要求无论更新操作是在哪一个节点副本上执行,之后获取的数据都是最新的。
- 弱一致性: 能容忍部分或全部节点都看不到最新数据,数据改变时尽量通知可能多的节点。
- 最终一致性: 是弱一致性的一种特例表现,需要保证用户最终能够读取到最新的数据。
我们当然希望能实现强一致性,但这样需要付出相当大的代价,往往要通过牺牲可用性才能达到。
一致性的保证
如果要想达到强一致性,那么就得保证任何数据在改变之后必须通知所有节点,等待所有节点更新完毕后才能给用户提供服,这就要在开始更新时加一把大锁,先锁住数据,等待所有节点完成更新时释放锁,这样才能提供数据的强一致性保证。
如果节点太多的话,这个锁的机制将会消耗大量的时间来等待,可能导致应用长时间不能提供正常服务,在一些应用上显然是不合适的,所以是否要保证强一致性需要根据具体的业务逻辑来选择。
还有一个经常听到的观点就是在分布式系统中一致性和可用性我们只能选择一个,这一般是从CAP理论中得到的结论,但是这样说是不准确的,关于CAP理论最初版的大意为:“对于一个分布式计算系统,不可能同时满足一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance )三个设计约束”。
通过CAP理论告诉我们分布式系统只能选择CP或者AP,但其实这里的前提是分布式系统发生了“分区”现象。如果当前系统没有发生分区现象,我们没有必要放弃C或者A,应该C和A都可以保证。
还有一点个人的理解,由于数据传输是需要时间的,那么当一个节点修改了数据同步到另一个节点时不可能瞬间完成,所以数据不一致总是时刻存在,而我们前面提到的数据一致总是指对用户而言的,虽然数据在传输过程中是不一致的,但是我们可以规定在数据完成同步前,用户看到的都是旧数据,这样就对用户而言数据就是一致的。
而数据同步过程中的不一致,如果在不一致期间还发生了中断、崩溃等问题,就必须通过日志来恢复了,个人觉得,总是有那么一种极限情况,连日志都救不了你,毕竟记录日志的也是一种程序,但是这类事情发生的概率也比较小了。
总结
- 程序世界的一致性常常指数据库中的一致性和分布式中的一致性
- CAP理论告诉我们分布式系统在发生了分区现象时,才需要选择CP或者AP,否则应该可以保证CA
欲穷千里目,更上一层楼。最近越来越发现古诗的精妙之处了,随着阅历的增加,之前背诵的古诗有些突然就明白了,不知道应该开心还是难过~
2020-10-26 00:27:02