豪门足球风云vivo账号登录版
972.64MB · 2025-12-03
Paxos 有点类似 2PC,3PC,但比这两种算法更加完善。在很多多大厂都得到了工程实践,比如阿里的 OceanBase 的 分布式数据库, Google 的 chubby 分布式锁 。
Paxos算法是什么? Paxos 算法是 基于消息传递 且具有 高效容错特性 的一致性算法,目前公认的解决 分布式一致性问题 最有效的算法之一。
Paxos算法的工作流程?
在Paxos中有这么几个角色:
详细可以看这篇文章:Paxos 算法详解
详情请看ZAB协议
ZAB协议(Zookeeper Atomic Broadcast)是Zookeeper中用于实现分布式一致性的协议。该协议旨在确保分布式系统中的数据一致性和可靠性,并具有以下特点:
ZAB协议的执行过程包括三个阶段:
如果在确认阶段(或提议阶段),Follower节点没有收到Leader节点的任何消息(包括提案和可能的超时通知),并且无法与Leader节点建立通信,那么这些Follower节点可能会认为Leader已经失效,并可能触发崩溃恢复模式。
然而,崩溃恢复模式通常不是由单个Follower节点单独触发的。实际上,ZooKeeper集群中的节点会通过一种称为“选举算法”的机制来共同决定何时进入崩溃恢复模式,并选举出一个新的Leader节点。
ZAB(ZooKeeper Atomic Broadcast)算法和Paxos算法都是分布式系统中用于实现数据一致性的算法。
两者的主要联系在于它们都采用了类似领导者的选举机制,通过多数派的投票来保证系统的稳定性。在ZAB中,这体现在它使用了一种类似于Paxos的领导者选举过程,其中有一个领导者(leader)来协调多个跟随者(follower)的操作。而在Paxos中,一个提案需要被大多数的进程接受并返回结果,才能被确定。
两者的区别在于它们的目标和实现方式不同:
综上所述,ZAB和Paxos的联系在于采用了领导者的选举机制和多数派的投票原则,而区别在于它们的目标和实现方式不同。
CAP原则是由Eric Brewer提出的分布式系统设计的基本定理。它指出在一个分布式系统中,以下三个特性最多只能同时满足其中两个:
为什么CAP原则最多只能同时满足其中两个?
假设有一个分布式数据库,分布在两个数据中心A和B。如果A和B之间的网络连接断开:
BASE是对CAP中一致性和可用性权衡的结果,它的全称是:
BASE原则是对CAP中AP的一个延伸,它的主要思想是:
举一个符合BASE原则场景例子:
在一个大型社交媒体平台上,用户可以在线更新他们的个人状态(例如,发布心情、描述活动等)。该平台有多个数据中心,分布在不同的地理位置,以支持全球用户的低延迟访问。为了能够快速响应用户请求并保持高可用性,该平台选择遵循BASE原则。
符合BASE原则的特征:
BASE原则是对CAP中一致性和可用性权衡的结果,它通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。
在Java分布式系统开发中,我们经常需要根据具体业务需求来选择适合的原则。例如:
在实际应用中,我们可能会使用各种技术和框架来实现这些原则,如分布式事务、最终一致性等。理解这些原则对于设计可靠的分布式系统至关重要。
Raft 也是一个 一致性算法,和 Paxos 目标相同。但它还有另一个名字 - 易于理解的一致性算法。Paxos 和 Raft 都是为了实现 一致性 产生的。这个过程如同选举一样,参选者 需要说服 大多数选民 (Server) 投票给他,一旦选定后就跟随其操作。Paxos 和 Raft 的区别在于选举的 具体过程 不同。
Raft算法的工作流程?
Raft 协议将 Server 进程分为三种角色:
就像一个民主社会,领导者由跟随者投票选出。刚开始没有 领导者,所有集群中的 参与者 都是 跟随者。
那么首先开启一轮大选。在大选期间 所有跟随者 都能参与竞选,这时所有跟随者的角色就变成了 候选人,民主投票选出领袖后就开始了这届领袖的任期,然后选举结束,所有除 领导者 的 候选人 又变回 跟随者 服从领导者领导。
这里提到一个概念 「任期」,用术语 Term 表达。
Leader选举过程
Raft 使用心跳(heartbeat)触发Leader选举。当Server启动时,初始化为Follower。Leader向所有Followers周期性发送heartbeat。如果Follower在选举超时时间内没有收到Leader的heartbeat,就会等待一段随机的时间后发起一次Leader选举。
Follower将其当前term加一然后转换为Candidate。它首先给自己投票并且给集群中的其他服务器发送 RequestVote RPC 。结果有以下三种情况:
选出 Leader 后,Leader 通过 定期 向所有 Follower 发送 心跳信息 维持其统治。若 Follower 一段时间未收到 Leader 的 心跳,则认为 Leader 可能已经挂了,然后再次发起 选举 过程。
一个系统 各组件分别部署在不同服务器。彼此通过网络通信和协调的系统。
分布式最早出现的目地首先是解决单点问题,避免单点故障,然后解决了性能问题。
分布式事务是相对本地事务而言的,对于本地事务,利用数据库本身的事务机制,就可以保证事务的ACID特性。
而在分布式环境下,会涉及到多个数据库。
分布式事务其实就是将对同一库事务的概念扩大到了对多个库的事务。目的是为了保证分布式系统中的数据一致性。
分布式事务处理的关键是:
详情可以看分布式事务实现方案
一般需要使用分布式锁的场景如下:
一个完善的分布式锁需要满足以下特点:
分布式锁常见的实现有三种实现:
用数据库实现分布式锁比较简单,就是创建一张锁表,数据库对字段作唯一性约束。
加锁的时候,在锁表中增加一条记录即可;释放锁的时候删除记录就行。
如果有并发请求同时提交到数据库,数据库会保证只有一个请求能够得到锁。
这种属于数据库 IO 操作,效率不高,而且频繁操作会增大数据库的开销,因此这种方式在高并发、高性能的场景中用的不多。
上面列举出了分布式锁需要满足的特点,使用数据库实现分布式锁也需要满足这些特点,下面我们来一一介绍实现方法:
数据库的表名为lock,各个字段的定义如下所示:
| 字段名名称 | 字段类型 | 说明 |
|---|---|---|
| lock_key | varchar | 锁的唯一标识符号 |
| lock_time | timestample | 加锁的时间 |
| lock_duration | integer | 锁的超时时长,单位可以业务自定义,通常为秒 |
| lock_owner | varchar | 锁的持有者,可以是节点或线程的唯一标识,不同可重入粒度的锁有不同的含义 |
| locked | boolean | 当前锁是否被占有 |
获取锁的SQL语句 :获取锁的SQL语句分不同的情况,如果锁不存在,那么首先需要创建锁,并且创建锁的线程可以获取锁:
insert into lock(lock_key,lock_time,lock_duration,lock_owner,locked) values ('xxx',now(),1000,'ownerxxx',true)
如果锁已经存在,那么就尝试更新锁的信息,如果更新成功则表示获取锁成功,更新失败则表示获取锁失败。
update lock set
locked = true,
lock_owner = 'ownerxxxx',
lock_time = now(),
lock_duration = 1000
where
lock_key='xxx' and(
lock_owner = 'ownerxxxx' or
locked = false or
date_add(lock_time, interval lock_duration second) > now())
释放锁的SQL语句 当用户使用完锁需要释放的时候,可以直接更新locked标识位为false。
update lock set
locked = false,
where
lock_key='xxx' and
lock_owner = 'ownerxxxx' and
locked = true
看门狗
通过上面的步骤,可以实现获取锁和释放锁,那么看门狗又是做什么的呢?
想象一下,如果用户获取锁到释放锁之间的时间大于锁的超时时间,是不是会有问题?是不是可能会出现多个节点同时获取锁的情况?这个时候就需要看门狗了,看门狗可以通过定时任务不断刷新锁的获取事件,从而在用户获取锁到释放锁期间保持一直持有锁。
Redis的Java客户端Redisson实现了分布式锁,我们可以通过类似ReentrantLock的加锁-释放锁的逻辑来实现分布式锁。
详情可以看redis实现分布式锁
Zookeeper实现的分布式锁适用于引入Zookeeper的服务
详情可以看zk实现分布式锁
基于数据库的分布式锁:
基于Redis的分布式锁:
基于Zookeeper的分布式锁:
详情可以看请求限流算法
计数器比较简单粗暴,比如我们要限制1s能够通过的请求数,实现的思路就是从第一个请求进来开始计时,在接下来的1s内,每个请求进来请求数就+1,超过最大请求数的请求会被拒绝,等到1s结束后计数清零,重新开始计数。
这种方式有个很大的弊端:比如前10ms已经通过了最大的请求数,那么后面的990ms的请求只能拒绝,这种现象叫做“突刺现象”。
就是桶底出水的速度恒定,进水的速度可能快慢不一,但是当进水量大于出水量的时候,水会被装在桶里,不会直接被丢弃;但是桶也是有容量限制的,当桶装满水后溢出的部分还是会被丢弃的。
算法实现:可以准备一个队列来保存暂时处理不了的请求,然后通过一个线程池定期从队列中获取请求来执行。
令牌桶就是生产访问令牌的一个地方,生产的速度恒定,用户访问的时候当桶中有令牌时就可以访问,否则将触发限流。
实现方案:Guava RateLimiter是一个谷歌提供的限流,其基于令牌桶算法,比较适用于单实例的系统。
详情可以看幂等性
时间轮(Time Wheel)是一种用于管理和调度大量定时任务的数据结构。它是一种高效的定时任务调度算法,主要用于优化任务调度的效率,特别是在需要处理大量定时任务时。时间轮是一种环形的数据结构,通过将时间划分为若干个时间片(槽),每个时间片负责管理一定时间段(如秒、分钟等内 的任务。
工作原理:
应用场景
实际应用示例: