分布式八股

分布式系统是当代常见的一种系统设计模式,可以大大的增加系统的处理效率。例如生成订单接口是用户在某一时间段内访问量超大的一个接口,那么这个接口的进程我们就可以复制多份部署在服务器上,他们可以同时生成多个线程处理这个接口

服务注册

可以通过zookeeper实现,zookeeper可以单独作为一个微服务部署在服务器上。其他的服务启动时可以作为provider和consumer去zk上注册自己的服务,和订阅别人的服务。注册服务实际上是在zk上创建一个路径/service,并注册自己的IP,端口权重信息。然后consumer订阅服务后缓存在本地,并监听这些路径看看是否发生变化,如果provider发生上下线就更新consumer的缓存。

分布式锁

这个时候会引入一个问题,在同一个进程上时,我们可以使用ReentrantLock或synchronize关键字来确保一个进程上的多个线程有序的读写资源。但是部署在不同进程上的线程之间要如何确保呢。我们可以使用redis来实现一个分布式锁:

简单来说Redis可以通过 SETNX KEY = VALUE 操作来实现一个简单的互斥锁,NX代表只有没有值时才能设置成功。也就是说如果之前被别的线程SET过了,此次操作会失败,可以理解会竞争锁失败。需要等待别的线程释放(删除KEY)之后才能获取锁。

锁最好还能定时释放,避免释放锁的线程挂掉了死锁问题:使用命令SETNX KEY = VALUE  EX 3,使锁3秒后自动释放。

锁最好不要提前释放,因为我们无法准确预估每个线程占有锁的最大时间,所以在定时到期时,我们可以使用redisson的看门狗机制为我们的锁续费。redisson同样也可以帮我们实现可重入锁。

可靠性:redis的主从复制是异步的,所以有可能出现复制完成之前节点宕机导致锁信息没有同步完成。redis设计了redLock模式,加锁的同时会向所有的redis节点加锁。获取锁的时候也会访问所有的节点,只有超过半数的节点一致时才会被认为是正确的结果(超过半数的节点加了锁或者没有加锁)。但是可以预见的这个性能会很差。我们也可以使用 Redis 主从复制+哨兵模式实现分布式锁。即在2n+1个从节点中部署哨兵,监测主节点是否宕机,如果超过一般的哨兵认为主节点发生宕机,则根据算法选举出新的主节点。(参考脑裂的解决方案)

分布式事务

首先要明确分布式事务尽量不要用,因为其特殊性所以是无法同时保证 高可用,强一致的。所以尽量将事务维持在每个服务内部完成统一。例如订单的创建,支付,与资源的出库。

如果必须要用分布式事务,推荐两种方案:

1. 两阶段提交,这是一种比较简单的方案,即在数据库维护一个事务管理器,分别维护不同服务间的事务,然后将所有事务分为两部分。第一部分为预执行,每个服务执行完后将执行结果入库(事务管理器)。只有所有服务都执行成功后,所有的服务才会执行第二阶段的commit操作,如果发生一个服务没有执行成功,则所有服务执行rollback操作。

2.使用消息队列。服务A执行一个命令,然后发送消息给mq,发送成功后执行事务。然后服务B再消费mq的消息,执行事务后返回ACK响应给MQ。如果是服务B业务失败,则A回滚。

3. TCC(try-confirm-cancel)即将所有分布式服务上的事务分为两个步骤,第一个步骤先尝试执行业务,第二个步骤即如果所有服务均执行成功则执行confirm步骤commit提交所有事务,如果有一个服务失败则执行cancel回滚所有服务。

分布式通信

分布式微服务之间的通信分为两种,同步通信和异步通信:

        - 同步通信:

                - HTTP: SpringMVC,WebFlux,OpenFeign还有SpringCloud都是通过HTTP的方式在服务间通信的,可以跨语言跨平台,但是通信内容较大,性能略低。一般在跨系统跨团队时使用该种方案。

                - RPC: 通过二进制协议通信,性能高于HTTP,可以使用Dubbo框架实现。一般在同一个系统内优先考虑该方案

                        - Dubbo的相关原理:注册中心默认使用的zookeeper。Provider启动时向注册中心注册自己的服务,Consumer订阅所有服务列表并缓存到本地后建立长链接监听该服务。通过动态代理的方式Consumer会将接口调用转换为网络请求,Provider会将网络请求转换为接口调用。Dubbo还能通过参数配置来实现服务降级,和熔断机制。可以通过group来区分同一个接口的不同实现,通过version来标识同一个接口的不同版本。

        - 异步通信:

                - 消息队列:通过kafka,rocketMq等消息队列实现,可能不会很及时。一般在非关键服务间通信使用改方案。

负载均衡

负载均衡算法主要分为六种:

        - 简单轮询:按顺序依次分发给后端服务器,不做任何处理

        - 权重轮询:在简单轮询的基础上可以给不同的服务器设置不同的优先级,性能高的服务器优先。

        - 简单随机:随机发给后端服务器,请求越多越均衡。

        - 权重随机:在简单随机的基础上可以给不同的服务器设置不同的优先级,性能高的服务器优先。

        - 一致性哈希:可以根据请求的参数,客户端IP哈希后得到一个值,根据这个值匹配不同的服务器,保证每次同一个用户都能被分配到同一个服务器。对于一些状态性的服务可以使用该算法。

        - 最小活跃数:实时统计所有服务的连接数,优先分配给最小链接数的后端服务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值