个人技术分享

1、分布式系统

简单说就是:一个活儿可以被多个人处理(一个请求过来,有多个节点都有能力处理它并响应),因此,需要考虑数据的一致性

在这里插入图片描述

分布式系统中的多个节点,可以是多台物理机、多台虚拟机、多个容器。分布式系统的引入,提高了系统的:

  • 可伸缩性(业务高峰期多起几个实例放节点上)
  • 可靠性(多个节点可以干活儿,挂掉一台服务器也问题不大)
  • 性能(并发能力变为n倍,n为节点数)

在这里插入图片描述
最后,加节点,是多了个干活儿的人,提到的是并发上限,单个接口,响应该几秒还是几秒,因为处理某个接口的这个活儿,你交给哪个人去干,都是那个耗时。

2、CAP定理

  • Consistency:一致性
  • Availability:可用性
  • Partition tolerance:分区容错性

CAP定理即:布式系统无法同时满足这三个指标

在这里插入图片描述

一致性,即用户访问分布式系统的任意节点,得到的数据必须一致。一个活儿,多个人都可以处理,但你问甲的结果和问乙的结果必须一样

在这里插入图片描述

可用性,即用户访问集群中的任意健康节点,必须得到响应,不能超时或者拒绝。

在这里插入图片描述

分区容错,即集群出现分区时,整个系统也要持续对外提供服务。

分区容错性,背景是:因网络故障或其他原因,导致分布式系统的部分节点和其他节点失去了联系,形成了独立分区

在这里插入图片描述
此时,客户端往节点node02写入数据v1,而node02只能同步给node01,node03数据还是旧的,违背了一致性。反之,如果想要数据一致,那就让分区2的节点node03别干活儿了,penging到网络恢复,但这违背了可用性。

结论:

  • 分布式系统节点之间肯定是需要网络连接的,分区(P)是必然存在的,因此,而分区一旦出现,如上分析,一致性和可用性就不可能同时满足。因此,CA是不可能的
  • 如果保证访问的高可用性A,可以持续对外提供服务,但不能保证数据的强一致性 ⇒ AP
  • 如果保证访问的数据强一致性C,就要放弃高可用性 ⇒ CP

3、Base理论

要么追求CP,要么追求AP,但也不是非0即1。追求了CP,仍然有数据的一致性,不过不再是强一致性,而是最终一致罢了。⇒ Base理论:

  • Basically Available(基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用
  • Soft state(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态
  • Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致

在这里插入图片描述

以上面的下单业务为例,下单后,需要做订单数据生成、账户扣款、库存余量维护。数据分布在不同的节点上,需要跨越多个节点或服务进行数据操作和事务处理(分布式事务)。此时就有两种选择:

  • 最终一致:各个分支事务(订单服务、账户服务、库存服务各自对应一个分支事务)分别执行并提交,如果哪一个分支事务执行失败,则需要恢复其他已提交的分支事务的数据(之前insert的就delete)。如此,数据最终一致,但会出现一个临时状态,也就是Base理论里所说的软状态,即数据不一致,订单服务库里有订单数据,但库存服务的库里数据未减少。 ⇒ AP
  • 强一致:各个分支事务执行完后不要提交,等待彼此的结果,统一提交或回滚,如此,数据强一致,但分支事务等待其他分支时,处于弱可用状态 ⇒ CP

4、分布式事务的解决方案:Seata

微服务架构下,多个微服务之间,只是做查询,那没啥好提事务的,但只要一个业务发生了多个微服务的写操作,如上面说的下单,就要进行分布式事务控制。解决方案:

  • Seata
  • MQ

Seata架构:
在这里插入图片描述

包括三个角色:

  • TC(Transaction Coordinator):事务协调者,维护全局和分支事务的状态,协调全局事务提交或回滚
  • TM (Transaction Manager): 事务管理器,定义全局事务的范围、开始全局事务、提交或回滚全局事务
  • RM(Resource Manager):资源管理器,可以认为是每一个微服务的节点,他们分别对应一个分支事务

4.1 Seata的XA模式

分支事务各自执行业务SQL后,不提交分支事务,等待TC检查各个分支事务,如果各个分支事务的SQL执行都没报错,则通知分支事务一起提交事务,反之,通知各个分支事务一起回滚事务。体现的是CP,即保证的是数据强一致性

在这里插入图片描述

XA模式缺陷是:各个分支事务之间要等待,等待期间,有资源锁定(业务SQL执行对应的数据被锁定,其他线程无法访问)

4.2 Seata的AT模式

和XA不同,AT模式下,各个分支事务会执行SQL并提交事务,但同时每个分支事务也都记录了undo-log日志。提交事务后,各个分支事务向TC报告自己的事务状态到TC,即告诉TC,自己的SQL执行成功没有,都成功,则删除undo-log日志,有一个失败,则根据undo-log把其余分支事务的数据退回去。

在这里插入图片描述
AT模式,体现的是AP,只要最终一致性,不要强一致

4.3 Seata的TCC模式

TCC模式即,Try、Confirm、cancel。比如还是下单,买本书100元,订单服务对应的分支事务A,进行Try资源预留,即检查下你的余额有没有 > 100,有则冻结100块。库存服务对应的分支事务B,进行Try资源预留,即检查库存剩余数量是否 > 1。Try后,各个分支事务向TC报告事务状态,如果都成功,则进行Confirm,提交全局事务。反之,执行Cancel,释放预留资源。

在这里插入图片描述
缺点是Try的部分得自己代码实现。

5、分布式事务的解决方案:MQ

比如向借呗申请借钱,借呗系统资质审核通过后,支付宝系统余额才能增加。但借呗和支付宝在两个不同的系统,还不是一个系统的两个微服务。此时,可用MQ实现:

在这里插入图片描述

用户申请借钱,资质审核通过后,借呗系统落库借款单并给MQ发消息(这两步,借呗在自己的库里加事务去控制同成功、同失败)。支付宝系统监听MQ,消费,给对应的用户增加余额。这样,数据的强一致性最弱,也即"5分钟内到账"。

最后,分布式事务各个方案的使用场景:

在这里插入图片描述

6、分布式系统下,接口的幂等性

幂等性:即多次调用一个接口,和单次调用一个接口,结果都一致,不会改变业务状态。 需要考虑幂等的场景如:用户重复点击(网络波动)。Restful API下的接口:

在这里插入图片描述
PUT不一定幂等:

//幂等
update t item set money= 500 where id = 1;

//不幂等
update t item set money = money + 500 where id = 1;

关于接口幂等性的实现方式:

在这里插入图片描述

6.1 数据库唯一索引

确保列或列组合的数值唯一性的索引,如此,插入数据时,多次调用就会报错:

在这里插入图片描述
这样只能处理新增的幂等性,修改的幂等性无法保证

6.2 token + redis

  • 第一次请求,生成一个唯一 token 存入redis ,返回给前端
  • 第二次请求,业务处理,携带之前的token,到redis 进行验证,如果存在,可以执行业务,删除token。如果不存在,则直接返回,不处理业务
    在这里插入图片描述

6.3 分布式锁

如下,防止重复支付,用支付ID作为分布式锁的key,防止某一笔订单被重复支付

在这里插入图片描述

7、分布式任务调度xxl-job

xxl-job的优势:

  • 解决集群任务的重复执行问题
  • cron 表达式定义灵活,不再硬编码到代码中
  • 定时任务失败了,重试和统计
  • 任务量大,分片执行

7.1 路由策略

每个任务交给哪个节点(或者job服务的哪个pod)去干:

在这里插入图片描述

  • First:固定选择第一个实例
  • Last:固定选择最后一个实例
  • Round:轮询
  • Random:随机
  • Least_Frequently_Used:最不经常使用的,使用频率最低的
  • Least_Recently_Used:最近最久未使用,最久没被使用的
  • FailOver:故障转移,按心跳检测,第一个心跳检测成功的
  • BusyOver:忙碌转移,按空闲检测,第一个空闲检测成功的
  • Sharding_Broadcast:分片广播

7.2 任务执行失败的处理

设置路由策略为故障转移 + 设置失败重试次数

在这里插入图片描述

重试后也可能失败,此时可查看日志,

在这里插入图片描述

以及设置邮件告警:页面上配置的是运维的邮箱

在这里插入图片描述

最后,部署xxl-job时,要配置下邮件发送者的信息,比如公司邮箱

在这里插入图片描述

7.3 大数据量任务同时执行–分片广播

分片广播的路由策略下,将一个任务分片执行并发到多个执行器上
在这里插入图片描述

在任务执行的代码中可以获取分片总数和当前分片,按照取模的方式分摊到各个实例执行:

在这里插入图片描述

8、面试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述