Java面试题-分布式

分布式

1. 谈谈业务中使用分布式的场景

为什么需要使用分布式:单体项目的性能瓶颈问题,需要分布式提升性能。

  • 场景1:服务拆分。

​ 单体项目将不同服务进行拆分,拆分后的服务可以支持横向扩容,避免因为单台服务器问题影响整体项目。

  • 场景2:数据库拆分。

​ 数据库读写分离,分库分表等提升性能。

2. Session分布式方案

项目场景:

  • 传统项目:

    服务器的session保存在本地,每次请求都会在同一个地方, 只要session没有过期则一定能够获取到session对象。

  • 分布式项目:

    有多个服务器,不同的请求发送到不同的服务器,不同服务器Session如何确保能够获取到?

解决方案:

  1. session复制

    Tomcat原生支持seesion同步,通过广播的方式进行异步同步,通过网络进行数据传输。在服务器集群较多时,session同步会占用大量带宽,同时session的增多导致单台服务器的内存会被大量占用。

    session复制适用于集群数量不多的情况下。

  2. 客户端存储

    直接将session数据存储到cookie中,每次请求解析cookie中的session数据。

    cookie是不安全的,且每次请求携带会增加网络传输开销。

  3. Hash一致性

    通过nginx的负载均衡配置,设置ip-hash策略,将客户端与服务器绑定,使同一ip的请求都转发到同一台服务器。

    一旦某台服务器宕机,session丢失,用户需要重新登录。

  4. 基于Redis的分布式session

    通过中间件Redis存储session信息,需要session数据只需通过查询Redis即可。

    确保Redis的可用性,还需要主从集群架构,确保Redis高可用。

3. 分布式锁的场景

  1. 系统是一个分布式系统,集群集群,java的锁已经锁不住了。
  2. 操作共享资源,比如库里唯一的用户数据。
  3. 同步访问,即多个进程同时操作共享资源。

4. 分布式锁的实现方案

  • Redis分布式锁
  • 数据库分布式锁
  • Zookeeper分布式锁

4.1 Redis分布式锁

setnx(key,value):如果当前key不存在,设值成功,返回1;如果当前key存在,设值失败,返回0。

expire(key):设置过期时间。

锁流程:

1、 setnx(key,value)加锁。

2、 expire(key)对key设置超时时间,避免死锁问题。

3、 执行流程。

4、del释放锁。

4.2 数据库分布式锁

基于数据库分布式锁有2种实现方案:数据库表的增删、数据库的排他锁

  • 数据库表的增删

    在数据库中维护一张表,每一个方法为唯一标识,进行增删操作,增加成功则为获取锁,执行完成后删除锁;其他线程继续。

  • 数据库的排他锁

    通过for update,对数据加上排他锁,其他线程无法获取锁并被阻塞。

4.3 Zookeeper分布式锁

基于zookeeper临时有序节点实现分布式锁。

https://blog.csdn.net/qq_41432730/article/details/123389670

5. 分布式事务

5.1 概念

相对于本地事务而言,本地事务通过数据库的事务机制就可以保证ACID(原子性、一致性、隔离性、持久性)特性,分布式环境下,涉及多个数据库,分布式事务就是为了保证多个数据库的数据一致性。

分布式事务处理的关键是:1、记录事务在任何节点所做的所有动作 2、事务所有操作要么全部提交、要么全部回滚

5.2 常见实现方案

5.2.1 2PC(两阶段提交)

先说说分布式事务中的XA协议:

XA协议中有三个角色:

  • AP(Applicatoin):应用程序
  • TM(Transaction Manager):事务管理器
  • RM(Resource Manager):资源管理器

XA接口提供资源管理器和事务管理器之间通信的标准接口。

两阶段提交

  • 阶段一:协调者向所有参与者发送预请求,等待参与者在本地执行操作并返回是否可以提交
  • 阶段二:协调者根据参与者的结果,判断是统一提交还是统一回滚。

优点:

​ 实现成本较低,尽量保证了数据强一致性。

缺点:

​ 协调者的地位很重要,需要考虑宕机的风险。

​ 资源管理器不是直接提交,而是同步阻塞。

​ 协调者发送了提交的通知,所有参与者受网络问题可能有数据不一致性的存在。

5.2.2 3PC(三阶段提交)

三阶段提交

  • 阶段一:canCommit;协调者确认所有参与者是否可以执行
  • 阶段二:preCommit;协调者确认参与者可以执行后,发送预请求,参与者在本地执行操作并返回是否可以提交
  • 阶段三:doCommit;协调者根据参与者的结果,判断是统一提交还是统一回滚。

优点:

​ 解决两阶段提交的单体故障和同步阻塞问题。

缺点:

​ 无法保证数据不一致问题。

5.2.3 TCC

TCC:Try Confirm Cancel;是两阶段提交的变种。是业务层面的分布式事务,保证最终一致性

  • Try阶段:尝试执行业务,根据执行结果,决定进入Confirm阶段或是Cancel阶段。
  • Confirm阶段:执行成功,将数据的状态进行更新为成功。
  • Cancel阶段:执行失败,将数据的状态进行更新为失败。

优点:

​ 数据库层的二阶段提交交给应用层实现,规避了数据库二阶段提交的阻塞问题。

缺点:

​ 需要开发成本,对代码的侵入性较大。

5.2.4 本地消息表

核心思想:分布式事务拆分为本地事务进行处理。

添加一张消息表,将新增数据和新增消息放到一个事务内;另外一个线程不断轮训消息表,将消息推送到MQ,另一个服务去消费消息。

实现了数据的最终一致性,需要在业务系统增加一张消息表,多一次消息表的操作,有一定损耗。

5.2.5 MQ消息事务

消息事务的原理是将两个事务通过MQ进行异步解耦。

消息事务依赖于消息中间件的事务消息,只有接收到确认才会正常投递消息。

对比本地消息表减少了消息表的存在,降低数据库操作。

5.2.6 最大努力通知

最大努力通知相比实现会简单一些,适用于一些对最终一致性实时性要求没那么高的业务,比如支付通知,短信通知。

6. 集群与负载均衡的算法与实现

6.1 轮询

将客户端发送到负载均衡器的请求,依次轮流的转发给服务器集群的节点。不需要考虑每个节点的连接数、负载、性能等情况。

优点:

​ 简单,公平

缺点:

​ 无法根据服务器性能分配;无法合理利用服务器资源

6.2 随机

随机把请求分发到可用的服务器上,由概率论的知识可知,随着请求量的变大,随机算法会逐渐演变为轮询算法,即集群各个节点会处理差不多数量的请求。所以优缺点也是与轮询算法类似。

6.3 加权轮询

每个服务器分配好权重,轮询根据分配的权重进行请求的分配。

6.4 加权随机

每个服务器分配好权重,随机根据分配的权重进行请求的分配。

6.5 IP-Hash

通过散列算法将请求分配到不同的服务器上。

猜你喜欢

转载自blog.csdn.net/qq_36986510/article/details/129306653
今日推荐