神一样的CAP理论被应用在何方?( 三 )


 

神一样的CAP理论被应用在何方?

文章插图
 
 
不过这种方式对于单主却无法自动切换主从的 MySQL 来说 , 基本就无法实现 P 分区容错性(MySQL 自动主从切换在目前并没有十分完美的解决方案) 。
可以说这种方式强依赖于数据库的可用性 , 数据库写操作是一个单点 , 一旦数据库挂掉 , 就导致锁的不可用 。这种方式基本不在 CAP 的一个讨论范围 。
基于 Redis 实现分布式锁
Redis 单线程串行处理天然就是解决串行化问题 , 用来解决分布式锁是再适合不过 。
实现方式:
setnx key value Expire_time 获取到锁 返回 1  ,  获取失败 返回 0 为了解决数据库锁的无主从切换的问题 , 可以选择 Redis 集群 , 或者是 Sentinel 哨兵模式 , 实现主从故障转移 , 当 Master 节点出现故障 , 哨兵会从 Slave 中选取节点 , 重新变成新的 Master 节点 。
 
神一样的CAP理论被应用在何方?

文章插图
 
 
哨兵模式故障转移是由 Sentinel 集群进行监控判断 , 当 Maser 出现异常即复制中止 , 重新推选新 Slave 成为 Master , Sentinel 在重新进行选举并不在意主从数据是否复制完毕具备一致性 。
所以 Redis 的复制模式是属于 AP 的模式 。保证可用性 , 在主从复制中“主”有数据 , 但是可能“从”还没有数据 。
这个时候 , 一旦主挂掉或者网络抖动等各种原因 , 可能会切换到“从”节点 , 这个时候可能会导致两个业务线程同时获取得两把锁 。
 
神一样的CAP理论被应用在何方?

文章插图
 
 
这个过程如下:
  • 业务线程 -1 向主节点请求锁
  • 业务线程 -1 获取锁
  • 业务线程 -1 获取到锁并开始执行业务
  • 这个时候 Redis 刚生成的锁在主从之间还未进行同步
  • Redis 这时候主节点挂掉了
  • Redis 的从节点升级为主节点
  • 业务线程 -2 想新的主节点请求锁
  • 业务线程 -2 获取到新的主节点返回的锁
  • 业务线程 -2 获取到锁开始执行业务
  • 这个时候业务线程 -1 和业务线程 -2 同时在执行任务
上述的问题其实并不是 Redis 的缺陷 , 只是 Redis 采用了 AP 模型 , 它本身无法确保我们对一致性的要求 。
Redis 官方推荐 Redlock 算法来保证 , 问题是 Redlock 至少需要三个 Redis 主从实例来实现 , 维护成本比较高 。
相当于 Redlock 使用三个 Redis 集群实现了自己的另一套一致性算法 , 比较繁琐 , 在业界也使用得比较少 。
能不能使用 Redis 作为分布式锁?这个本身就不是 Redis 的问题 , 还是取决于业务场景 。
我们先要自己确认我们的场景是适合 AP 还是 CP  ,  如果在社交发帖等场景下 , 我们并没有非常强的事务一致性问题 , Redis 提供给我们高性能的 AP 模型是非常适合的 。
但如果是交易类型 , 对数据一致性非常敏感的场景 , 我们可能要寻找一种更加适合的 CP 模型 。
基于 Zookeeper 实现分布式锁
刚刚也分析过 , Redis 其实无法确保数据的一致性 , 先来看 Zookeeper 是否适合作为我们需要的分布式锁 。
首先 ZK 的模式是 CP 模型 , 也就是说 , 当 ZK 锁提供给我们进行访问的时候 , 在 ZK 集群中能确保这把锁在 ZK 的每一个节点都存在 。
 
神一样的CAP理论被应用在何方?

文章插图
 
 
这个实际上是 ZK 的 Leader 通过二阶段提交写请求来保证的 , 这个也是 ZK 的集群规模大了的一个瓶颈点 。
①ZK 锁实现的原理
说 ZK 的锁问题之前先看看 Zookeeper 中几个特性 , 这几个特性构建了 ZK 的一把分布式锁 。
ZK 的特性如下: