- Consistency 一致性
- Availability 可用性
- Partition tolerance 分区容错性
三者取其二,如:Zookeeper满足CP、Redis满足AP
- Basically available 基本可用
- Soft-state 软状态
- Eventually consistent 最终一致
可用性A和一致性C的权衡(trade-off)
https://zhuanlan.zhihu.com/p/263555694
https://medium.com/@dongfuye/the-seven-most-classic-solutions-for-distributed-transaction-management-3f915f331e15 https://developers.redhat.com/blog/2018/10/01/patterns-for-distributed-transactions-within-a-microservices-architecture#conclusion
https://blog.bitsrc.io/distributed-transactions-in-microservices-d07aba281f90
https://juejin.cn/post/7017333689109446670
https://www.atomikos.com/Documentation/SagasVsTwoPhaseCommitVsTCC
https://george24601.github.io/2018/06/19/saga-isolation.html
- 准备阶段(Prepare phase)
- 提交阶段(Commit phase)
缺点:同步阻塞
适用于长事务,将长事务拆分成多个本地短事务,每个短事务依次直接提交,当发生错误时,为执行成功的事务执行补偿操作
缺点:存在中间状态
- Try:资源检查和预留
- Confirm or Cancel:确认执行或取消执行
业务层面的两阶段提交,如:创建订单和扣减库存
如何确保消息一定(如果业务处理成功,则消息最终也会发送成功)发送成功?
- 写本地消息表 + 轮询发送 + 失败重试
- 使用RocketMQ事务消息
如:下单成功加积分
尽可能通知下游 + 下游回查,如:支付结果通知
通常解决两类问题:
- 保证请求串行执行,每个请求都要执行或超时处理
- 保证只有一个请求可以执行,比如分布式定时任务
1)加锁与解锁
# acquire lock
SET resource_name my_random_value NX PX 30000
# release lock
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
2)RedLock算法
- 获取当前时间戳
- 依次向每个Redis实例申请锁,如果超时(远远小于锁自动释放时间),则下一个
- 如果向超过一半的Redis实例申请锁成功,且耗时小于锁自动释放时间,则视为加锁成功
- 否则视为加锁失败,依次向每个Redis实例释放锁
3)Redisson RLock
RLock lock = redisson.getLock("myLock");
// wait for lock acquisition up to 100 seconds and automatically renew lock expiration to 30 seconds every 10 seconds
boolean res = lock.tryLock(100_1000, TimeUnit.MILLISECONDS);
if (res) {
try {
System.out.println(threadName + " acquire lock succeed at " + new Date(System.currentTimeMillis()));
System.out.println(threadName + " do business begin at " + new Date(System.currentTimeMillis()));
TimeUnit.MILLISECONDS.sleep(50_000);
System.out.println(threadName + " do business end at " + new Date(System.currentTimeMillis()));
} finally {
lock.unlock();
}
} else {
System.out.println(threadName + " acquire lock fail at " + new Date(System.currentTimeMillis()));
}
临时有序节点 + 监听机制
https://zookeeper.apache.org/doc/r3.1.2/recipes.html
https://curator.apache.org/getting-started.html
- 随机
- 轮询
- 哈希
- 基于服务器负载(最小连接数、最小响应时间)
一致性哈希
哈希环(0 ~ 2^32 - 1),数据落在顺时针第一个节点上
- 优点:减少节点数量变化时,数据的迁移或缓存的失效
- 问题:数据倾斜,使用虚拟节点增加节点的数量
- 计数器算法
- 滑动窗口算法
- 令牌桶算法:匀速生成令牌,桶可以缓存令牌,可以处理突发流量
- 漏桶算法:匀速出水
- 服务提供者:服务注册、服务续约
- 服务消费者:获取服务、服务调用
- 服务注册中心:失效剔除、自我保护(保证可用性)