马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
CAP定理
CAP指的是Consistency(同等性)、 Availability(可用性)、Partition tolerance(分区容错性)
选项描述Consistency(同等性)指数据在多个副本时可以或许保持同等的特性(严格的同等性)Availability(可用性)指系统提供的服务必须一直处于可用的状态,每次哀求都能获取到正常相应(不保证获取的数据为最新数据)Partition tolerance(分区容错性)分布式系统在碰到任何网络分区故障的时候,仍旧可以或许对外提供满足同等性和可用性的服务,除非整个网络环境都发生了故障 C、A、P这三个需求中,网络分区的发生是不可避免的,因此分区容错性是分布式系统必须满足的需求。因此,CAP定理现实上是在告诉我们,当发生网络分区时,我们需要在同等性和可用性之间做出衡量,只能选择其中的一个。这是因为,在网络分区的环境下,要么保持同等性,但会牺牲可用性,即哀求大概会得到错误的相应或者超时;要么保持可用性,但会牺牲同等性,即不同节点上的数据大概是不同等的。因此,CAP定理提示我们在筹划分布式系统时要根据具体的需求和场景做出适当的取舍。
CA模型的常见应用:
- 集群数据库
- xFS文件系统
- CP without A
放弃A(可用),相称于每个哀求都需要在Server之间强同等,而P(分区)会导致同步时间无限延长,如此CP也是可以保证的。许多传统的数据库分布式变乱都属于这种模式。
CP模型的常见应用:
要高可用并允许分区,则需放弃同等性。一旦分区发生,节点之间大概会失去联系,为了高可用,每个节点只能用本地数据提供服务,而如许会导致全局数据的不同等性。现在浩繁的NoSQL都属于此类。
AP模型常见应用:
- Web缓存
- DNS
举个各人更认识的例子,像我们认识的注册中央ZooKeeper、Eureka、Nacos中:
- ZooKeeper 保证的是 CP
- Eureka 保证的则是 AP
- Nacos 不仅支持 CP 也支持 AP
分布式锁
基于redis单实例分布式锁
Redis的分布式锁是非常的经典的,它的利用遍布在各个业务系统中。
redis单实例中实现分布式锁的正确方式(原子性非常紧张):
- 设置锁时,利用set命令,因为其包含了setnx,expire的功能,起到了原子操纵的效果,给key设置随机值,并且只有在key不存在时才设置乐成返回True,并且设置key的过期时间(最好用毫秒)
SET key_name my_random_value NX PX 30000 # NX 表示if not exist 就设置并返回True,否则不设置并返回False PX 表示过期时间用毫秒级, 30000 表示这些毫秒时间后此key过期
- 在获取锁后,并完成相关业务后,需要删除自己设置的锁(必须是只能删除自己设置的锁,不能删除他人设置的锁);
删除原因:保证服务器资源的高利用效率,不消比及锁自动过期才删除;
删除方法:最好利用Lua脚本删除(redis保证执行此脚本时不执行其他操纵,保证操纵的原子性),代码如下;逻辑是 先获取key,如果存在并且值是自己设置的就删除此key;否则就跳过;
if redis.call(“get”,KEYS[1]) == ARGV[1] then return redis.call(“del”,KEYS[1]) else return 0 end
基于etcd的分布式锁
Etcd是一个高可用、分布式、同等性的键值存储系统,因其高效、可靠的特点,被广泛应用于分布式系统中。Etcd中的分布式锁实现,可以实现多个进程之间的互斥访问,避免出现并发访问的题目。基于Etcd的分布式锁实现过程中,重要涉及到以下几个步骤:
- 创建Etcd客户端毗连:在分布式系统中,各个进程都需要毗连到Etcd服务,获取分布式锁的信息。
- 创建租约:在Etcd中,租约是指某个键值对的生存时间,在租约时间内,Etcd会保证该键值对一直存在。如果租约时间到期,那么Etcd会自动将该键值对删除。
- 创建分布式锁:在Etcd中,分布式锁的实现需要利用到租约。分布式锁的创建过程重要分为两个步骤:
- 创建一个带有租约的临时节点;
- 通过比力Etcd中当前节点的序列号和前一个节点的序列号,来判断当前节点是否获取到了分布式锁。
- 释放锁:在获取到锁之后,进程需要利用相同的Etcd客户端毗连释放锁。释放锁的过程重要分为两个步骤:
- 删除当前节点;
- 关闭租约。
基于Etcd的分布式锁实现,可以或许保证分布式系统中各个进程的互斥访问。但是,它也存在一些题目:
网络通信开销:在分布式系统中,各个进程需要频仍地毗连Etcd服务,获取分布式锁的信息。这会增加网络通信的开销,影响系统的性能。
锁竞争:在高并发的环境下,分布式锁的竞争会变得非常猛烈,容易造成锁竞争的题目,影响系统的稳固性。
因此,在现实应用中,需要根据现实环境选择符合的分布式锁实现方案,保证系统的可用性和稳固性。
分布式变乱
分布式变乱是指在分布式系统中的多个变乱并发执行时,为了保证数据的同等性和完备性,需要采取一些和谐机制,确保这些变乱的执行结果和单机变乱一样具有原子性、同等性、隔离性和长期性。
以下是常见的分布式变乱实现方案:
- 两阶段提交(Two-Phase Commit,2PC):是一种同步协议,通过和谐器来实现变乱的同等性。该协议由两个阶段组成,第一阶段是投票阶段,和谐器向所有参与者发起哀求,询问它们是否可以提交变乱;第二阶段是执行阶段,如果所有参与者都同意提交,和谐器会向它们发送提交哀求,否则会发送回滚哀求。
- 三阶段提交(Three-Phase Commit,3PC):是对两阶段提交的改进,通过引入超机遇制和优化提交流程来办理2PC中存在的题目。3PC重要包含三个阶段:CanCommit,PreCommit和DoCommit。
- TCC(Try-Confirm-Cancel):是一种基于补偿的分布式变乱处置惩罚方案。将分布式变乱拆分成三个操纵:Try、Confirm和Cancel。当分布式变乱发生时,先辈行Try操纵,检查分布式变乱操纵是否可以乐成,如果Try操纵乐成,则执行Confirm操纵提交分布式变乱操纵;如果Try操纵失败,则执行Cancel操纵回滚分布式变乱。
- 本地消息表(Local Message Table,LMT):是一种轻量级的分布式变乱办理方案,它通过将分布式变乱操纵转化为本地操纵和消息发送,然后通过本地消息表来实现变乱的最终同等性。
- Saga:是一种基于流程的变乱处置惩罚机制,将分布式变乱拆分成一系列相互协作的子变乱(Step),并通过Saga和谐器来确保每个子变乱的执行次序和同等性。
- 最大努力通知: 最大努力通知相比实现会简单一些,适用于一些对最终同等性及时性要求没那么高的业务,比如支付通知,短信通知。对通知失败的操纵不停的进行重试,直到达到最大通知次数。
- Seata(Simple Extensible Autonomous Transaction Architecture)是一个开源的分布式变乱办理方案,提供了高性能和易用性的分布式变乱服务。它可以或许保证变乱的ACID属性,同时提供了简单易用的编程模型,使得开发人员可以方便地开发分布式变乱应用。
Seata是非经常见的分布式事物的利用方案,Seata支持两种变乱模型:AT(自动变乱)和TCC(尝试、确认、取消变乱)。AT模型是一种自动的变乱模型,适用于大多数的业务场景,它不需要应用开发人员显式地编写变乱提交和回滚的代码。TCC模型则需要应用开发人员表现地编写变乱提交和回滚的代码,适用于一些特定的场景,如金融领域、电商领域等。
Seata的焦点组件包罗:
Transaction Coordinator(TC):变乱和谐器,负责和谐全局变乱的提交和回滚。
Transaction Manager(TM):变乱管理器,负责管理分支变乱的状态,以及向TC报告全局变乱的状态。
Resource Manager(RM):资源管理器,负责管理本地变乱的提交和回滚,以及向TM报告分支变乱的状态。
Seata的工作流程如下:
- 客户端向TC发起全局变乱哀求。
- TC创建全局变乱,并向TM发起分支变乱哀求。
- TM在本地创建分支变乱,并向RM注册分支变乱。
- 客户端在分支变乱中执行业务逻辑。
- 客户端向TM发送分支变乱的提交哀求。
- TM向TC报告分支变乱的状态。
- TC根据分支变乱的状态决定全局变乱的提交或回滚。
- 如果全局变乱提交,TC向所有RM发送分支变乱的提交哀求。
- RM接收到分支变乱的提交哀求后,提交本地变乱。
- 如果全局变乱回滚,TC向所有RM发送分支变乱的回滚哀求。
- RM接收到分支变乱的回滚哀求后,回滚本地变乱。
- 基于Seata的分布式变乱实现方案可以保证变乱的ACID属性,同时提供了简单易用的编程模型,使得开发人员可以方便地开发分布式变乱应用。
分布式同等性算法
Paxos算法
在Paxos中有这么几个角色:
- Proposer(发起者) : 发起者提出提案,用于投票表决。
2 .Accecptor(接受者) : 对提案进行投票,并接受告竣共识的提案。
- Learner(学习者) : 被告知投票的结果,接受告竣共识的提案。
在现实中,一个节点可以同时充当不同角色。
Paxos算法包含两个阶段,第一阶段Prepare(准备)、第二阶段Accept(接受)。
Prepare(准备)阶段
发起者发起一个新的提案 P[Mn,?],然后向接受者的某个凌驾半数的子集成员发送编号为Mn的准备哀求
如果一个接受者收到一个编号为Mn的准备哀求,并且编号Mn大于它已经相应的所有准备哀求的编号,那么它就会将它已经批准过的最大编号的提案作为相应反馈给发起者,同时该接受者会答应不会再批准任何编号小于Mn的提案。
总结一下,接受者在收到提案后,会给与发起者两个答应与一个应答:
两个答应:
答应不会再接受提案号小于或等于 Mn 的 Prepare 哀求
答应不会再接受提案号小于Mn 的 Accept 哀求
一个应答:
不违背从前作出的答应的条件下,回复已经通过的提案中提案号最大的谁人提案所设定的值和提案号Mmax,如果这个值从来没有被任何提案设定过,则返回空值。如果不满足已经做出的答应,即收到的提案号并不是决议节点收到过的最大的,那允许直接对此 Prepare 哀求不予理会。
Accept(接受)阶段
如果发起者收到来自半数以上的接受者对于它发出的编号为Mn的准备哀求的相应,那么它就会发送一个针对[Mn,Vn]的接受哀求给接受者,留意Vn的值就是收到的相应中编号最大的提案的值,如果相应中不包含任何提案,那么它可以随意选定一个值。
如果接受者收到这个针对[Mn,Vn]提案的接受哀求,只要该接受者尚未对编号大于Mn的准备哀求做出相应,它就可以通过这个提案。
当发起者收到了多数接受者的接受应答后,协商结束,共识决议形成,将形成的决议发送给所有学习节点进行学习。
Raft算法
Raft算法是一种用于分布式同等性的算法,其目的是让多个节点在分布式环境下告竣同等的状态。Raft算法的筹划者以为,相比其他分布式同等性算法(如Paxos),Raft算法更容易理解、实现和调试。
Raft算法的焦点是Leader推举、日记复制和安全性。在Raft算法中,节点可以处于三种状态:Leader、Follower和Candidate。Leader负责处置惩罚客户端的哀求,并将结果复制到Follower节点。Follower和Candidate节点等候Leader的指令。如果Leader宕机,Follower和Candidate节点会通过推举产生新的Leader。
Raft算法通过日记复制来保证多个节点之间的同等性。当客户端发出哀求时,Leader会将哀求转化为一条日记记载,并将其复制到Follower节点。一旦大多数节点复制了该日记记载,Leader将会将该哀求应用于状态机,然后将结果返回给客户端。
为了保证安全性,Raft算法还引入了一些额外的束缚条件,例如限制Follower节点只能接收来自Leader的指令、确保每个日记记载都有唯一的索引、以及限制只有新的Leader才华进行新的日记复制等。
总的来说,Raft算法通过Leader推举、日记复制和安全性保证了分布式同等性。与Paxos相比,Raft算法更加容易理解、实现和调试,因此在现实应用中得到了广泛的应用。
分布式筹划
在保存数据的接口中,在insert前,先根据requestId等字段先select一下数据。如果该数据已存在,则直接返回,如果不存在,才执行 insert操纵。
加唯一索引是个非常简单但很有效的办法,如果重复插入数据的话,就会抛出非常,为了保证幂等性,一般需要捕捉这个非常。
如果是java程序需要捕捉:DuplicateKeyException非常,如果利用了spring框架还需要捕捉:MySQLIntegrityConstraintViolationException非常。
更新逻辑,比如更新用户账户余额,可以加悲观锁,把对应用户的哪一行数据锁住。同一时刻只允许一个哀求得到锁,其他哀求则等候。
select * from user id=123 for update;
这种方式有一个缺点,获取不到锁的哀求一般只能报失败,比力难保证接口返回相同值。
更新逻辑,也可以用乐观锁,性能更好。可以在表中增加一个timestamp或者version字段,例如version:
在更新前,先查询一下数据,将version也作为更新的条件,同时也更新version:
update user set amount=amount+100,version=version+1 where id=123 and version=1;
更新乐成后,version增加,重复更新哀求进来就无法更新了。
有时候表中并非所有的场景都不允许产生重复的数据,只有某些特定场景才不允许。这时候,就可以利用防重表的方式。
例如消息消费中,创建防重表,存储消息的唯一ID,消费时先去查询是否已经消费,已经消费直接返回乐成。
有些业务表是有状态的,比如订单表中有:1-下单、2-已支付、3-完成、4-撤销等状态,可以通过限制状态的活动来完成幂等。
直接在数据库上加锁的做法性能不够友好,可以利用分布式锁的方式,现在最流行的分布式锁实现是通过Redis,具体实现一般都是利用Redission框架。
哀求接口之前,需要先获取一个唯一的token,再带着这个token去完成业务操纵,服务端根据这个token是否存在,来判断是否是重复的哀求。
分布式限流
- 计数器
计数器比力简单粗暴,比如我们要限制1s可以或许通过的哀求数,实现的思绪就是从第一个哀求进来开始计时,在接下来的1s内,每个哀求进来哀求数就+1,凌驾最大哀求数的哀求会被拒绝,比及1s结束后计数清零,重新开始计数。
这种方式有个很大的弊端:比如前10ms已经通过了最大的哀求数,那么后面的990ms的哀求只能拒绝,这种现象叫做“突刺现象”。
- 漏桶算法
就是桶底出水的速率恒定,进水的速率大概快慢不一,但是当进水量大于出水量的时候,水会被装在桶里,不会直接被丢弃;但是桶也是有容量限制的,当桶装满水后溢出的部门还是会被丢弃的。
- 算法实现:可以准备一个队列来保存暂时处置惩罚不了的哀求,然后通过一个线程池定期从队列中获取哀求来执行。
- 令牌桶算法
令牌桶就是生产访问令牌的一个地方,生产的速率恒定,用户访问的时候当桶中有令牌时就可以访问,否则将触发限流。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |