文章插图
结合这几个特点 , 来看下 ZK 是怎么组合分布式锁:
- 业务线程 -1 , 业务线程 -2 分别向 ZK 的 /lock 目录下 , 申请创建有序的临时节点 。
- 业务线程 -1 抢到 /lock0001 的文件 , 也就是在整个目录下最小序的节点 , 也就是线程 -1 获取到了锁 。
- 业务线程 -2 只能抢到 /lock0002 的文件 , 并不是最小序的节点 , 线程 2 未能获取锁 。
- 业务线程 -1 与 lock0001 建立了连接 , 并维持了心跳 , 维持的心跳也就是这把锁的租期 。
- 当业务线程 -1 完成了业务 , 将释放掉与 ZK 的连接 , 也就是释放了这把锁 。
ZK 官方提供的客户端并不支持分布式锁的直接实现 , 我们需要自己写代码去利用 ZK 的这几个特性去进行实现 。
文章插图
究竟该用 CP 还是 AP 的分布式锁
首先得了解清楚我们使用分布式锁的场景 , 为何使用分布式锁 , 用它来帮我们解决什么问题 , 先聊场景后聊分布式锁的技术选型 。
无论是 Redis , ZK , 例如 Redis 的 AP 模型会限制很多使用场景 , 但它却拥有了几者中最高的性能 。
Zookeeper 的分布式锁要比 Redis 可靠很多 , 但他繁琐的实现机制导致了它的性能不如 Redis , 而且 ZK 会随着集群的扩大而性能更加下降 。
简单来说 , 先了解业务场景 , 后进行技术选型 。
分布式事务 , 是怎么从 ACID 解脱 , 投身 CAP/BASE
如果说到事务 , ACID 是传统数据库常用的设计理念 , 追求强一致性模型 , 关系数据库的 ACID 模型拥有高一致性+可用性 , 所以很难进行分区 。
在微服务中 ACID 已经是无法支持 , 我们还是回到 CAP 去寻求解决方案 , 不过根据上面的讨论 , CAP 定理中 , 要么只能 CP , 要么只能 AP 。
如果我们追求数据的一致性而忽略可用性这个在微服务中肯定是行不通的 , 如果我们追求可用性而忽略一致性 , 那么在一些重要的数据(例如支付 , 金额)肯定出现漏洞百出 , 这个也是无法接受 。所以我们既要一致性 , 也要可用性 。
文章插图
都要是无法实现的 , 但我们能不能在一致性上作出一些妥协 , 不追求强一致性 , 转而追求最终一致性 , 所以引入 BASE 理论 。
在分布式事务中 , BASE 最重要是为 CAP 提出了最终一致性的解决方案 , BASE 强调牺牲高一致性 , 从而获取可用性 , 数据允许在一段时间内不一致 , 只要保证最终一致性就可以了 。
实现最终一致性
弱一致性:系统不能保证后续访问返回更新的值 。需要在一些条件满足之后 , 更新的值才能返回 。
从更新操作开始 , 到系统保证任何观察者总是看到更新的值的这期间被称为不一致窗口 。
最终一致性:这是弱一致性的特殊形式;存储系统保证如果没有对某个对象的新更新操作 , 最终所有的访问将返回这个对象的最后更新的值 。
BASE 模型
BASE 模型是传统 ACID 模型的反面 , 不同于 ACID , BASE 强调牺牲高一致性 , 从而获得可用性 , 数据允许在一段时间内的不一致 , 只要保证最终一致就可以了 。
BASE 模型反 ACID 模型 , 完全不同 ACID 模型 , 牺牲高一致性 , 获得可用性或可靠性:Basically Available 基本可用 。
支持分区失败(e.g. sharding碎片划分数据库)Soft state 软状态 , 状态可以有一段时间不同步 , 异步 。
Eventually consistent 最终一致 , 最终数据是一致的就可以了 , 而不是时时一致 。
推荐阅读
- 泡茶不好喝 你的茶汤出尽了吗
- 爱喝茶的人常有的四条怪癖
- 每种茶都有自己的特性茶文化博大精深
- 茶叶香气的九大类型
- 这篇java的NIO编程,保证你能看懂
- 到底什么才是好茶
- 一篇全面的 MySQL 高性能优化实战总结
- 普洱散茶的冲泡技巧
- 武夷水仙和凤凰水仙有啥区别
- Python数据类型详解——元组