一致性详解

在后台开发中,当我们需要支持大规模的并发读写,同时具备横向扩展能力。这这时我们一般会对数据进行hash分区,从而分布到不同的服务器中,以解决写的瓶颈。同时每个写服务器会通过主从同步分布到多台服务器上面,从而实现读写分离,提高读的并发性能。
那么问题来了,一次性写多条数据,怎么保证多台服务器的一致性呢?如果数据同步存在延迟,怎么保证写后一定能读到呢?本文我们就探讨一下一致性的问题。

一致性的分类

我们通常把一致性分为最终一致性与强一致性,那么什么是最终一致性,什么是强一致性呢?
最终一致性(Eventually):写入数据 A 成功后,在其他副本有可能读不到 A 的最新值,但在某个时间窗口之后保证最终能读到。注意这里有限定某个时间窗口。
强一致性(Strong):数据 A 一旦写入成功,在任意副本任意时刻都能读到 A 的最新值。
从定义中我们可以看出,这种分类方法太过于笼统,不利于实际应用。故我们一般从数据的维度或者用户的维度进行分类。

数据维度的一致性

数据维度的一致性常用的有如下几种:
1、线性一致性,是建立在事件的先后顺序之上。在线性一致性下,所有操作都被记录到一条时间线上,事件之间可以比较先后顺序。所有的副本都按相同的顺序同步数据。在分布式下,要实现线性一致性一般需要将写操作hash到同一个主节点,或者引入全局时钟。
2、因果一致性是一种弱化的顺序一致性,所有进程必须以相同的顺序看到具有潜在因果关系的写操作,不同进程可以以不同的顺序看到并发的写操作。MySQL5.7开始的数据库的主从同步,其实就是满足因果一致性。在比如一个客户先购买了某只股票,后面又卖了。那么不管在哪里看到的都是先买了某只股票,再卖了某只股票,那么就是满足因果一致性的。

用户维度的一致性

用户维度的一致性,常用的有:
1、单调读一致性是指,如果一个进程读取数据项 a 的值,那么该进程对 a 执行的任何后续读操作,总是得到第一次读取的那个值或更新的值。说白了,就是不能读到新数据后,再读到比这个数据还旧的数据。比如在微博的场景中,某个明星发布了一条微博,如果某个粉丝读到了这条微博,再读到这条微博过后,重新打开APP,发现那条微博不见了(明星没有删除微博),那么就不满足单调一致性。单调读一致性在实现上比较简单,一般把同一个用户通过hash映射到同一个节点即可。
2、写后读一致性是指,一个进程对数据项 a 执行一次写操作的结果,总是会被该进程对 a 执行的后续读操作看见。这个比较常见,比如数据库采用 Master-Slave 结构部署时,写完 Master 数据库,如果从 Slave 读取,有可能读不到,就不满足写后读一致性了。再具体一点的例子就是,某个明星发布了一条微博,但是这个明星再次打开APP时,如果看不到自己发布的微博,那么就不满足写后读一致性。在实现上,用户写完数据后,可以在一定的时间内hash到写入数据的节点即可。

一致性性问题如何解决

上文提到高并发写的时候,我们通过多机器hash处理,从而实现每个机器的写并发都不会太大,但是业务一般都有都多写少的特点,故我们又通过复制多个副本,然后读操作都在副本上面实现,那么我们要如何做到读后写一致性呢?
比如 MySQL,就可以采用一个 Master,多个 Slave 的方式,所有的写都在 Master 上更新,所有的读都在 Slave 上进行,但这里存在一个问题,就是怎么保证写后读一致性?我们可以监控读写的延迟,然后设置一个最大的读写延迟的阈值,如果写后读再阈值以内,那么就去master读,如果超过了阈值,就去slave读。

前面的方法是只再主节点里面写数据,那么我们是否可以一次写多个节点呢?这时Quorum 机制(NWR 模型)就派上用场了。
Quorum 机制就是要满足公式 W+R > N。其中,W 表示必须至少写入成功的节点数,R 表示至少读取成功的节点数,N 表示总节点数。这个公式把选择权交给了业务用户,让用户来做出最终决策。那么业务端怎么知道读取出来的就是最新的数据呢?就是利用版本号,每次写数据的同时,都记录这条数据对应的版本号,读数据的时候判断版本号,版本最新的就是最终数据。这里还存在另外一个问题,那就是,如果写的时候只写入的节点<=N/2,当存在并发写操作时,版本会存在冲突,这就要求我们写数据的时候最好是遵循 W>N/2。

思考题:

1、前面介绍的只再主节点写数据,但是如果主节点挂了,就要选一个从节点作为新的主节点。那么我们如何才能保证选出来的主节点的数据不丢失呢?这时就涉及到分布式共识问题了,我后面会在分布式共识里面介绍。
2、前面介绍的通过hash到不同的服务器,那么常用的hash方法都有哪些呢?怎么做到一个工业级的hash呢?

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值