# 分布式架构

# 为什么要进行系统拆分?

业务发展到一定量级,达到单体系统负载极限,无法再承载业务的进一步发展。
通过分而治之的方式,将系统拆分为子系统,进而通过扩展的方式不断适应业务的发展。

具体来讲,以下因素是考虑系统拆分的原因:

  1. 获得更高的系统整体性能;
  2. 使得系统可维护性、可扩展性增强;
  3. 增加代码的可维护性,减少代码冲突;
  4. 增加子系统的边界,保持领域内问题可控。

# 如何进行系统拆分?

  1. 考虑组织架构(康威定理);
  2. 考虑领域划分;
  3. 考虑系统内聚与解耦;
  4. 考虑系统的分层;
  5. 考虑模块的代码量。

# 分布式服务接口的幂等性如何设计(比如不能重复扣款)?

  • 保证幂等性主要是三点:
  1. 对于每个请求必须有一个唯一的标识;
  2. 每次处理完请求之后,必须有一个记录标识这个请求处理过了;
  3. 每次接收请求需要进行判断,判断之前是否处理过。

需要结合业务场景解决。
比如利用 Redis,用 orderId 作为唯一键,只有成功插入这个支付流水,才可以执行实际的支付扣款。

# 分布式服务接口请求的顺序性如何保证?

一旦引入顺序性保障,比如使用分布式锁,会导致系统复杂度上升,而且会带来效率低下,热点数据压力过大等问题。
所以要尽量避免这类需求。

一般通过队列来保证。

# 分布式锁的实现方案?哪种效率比较高?

分布式锁有 3 个重要的考量点:
互斥(只能有一个客户端获取锁)
不能死锁
容错(只要大部分 Redis 节点创建了这把锁就可以)

  • Redis

    • SET key value [EX seconds] [PX milliseconds] NX 创建一个 key
    • RedLock 算法
  • Zookeeper

某个节点尝试创建临时 znode,此时创建成功了就获取了这个锁;
这个时候别的客户端来创建锁会失败,只能注册个监听器监听这个锁。
释放锁就是删除这个 znode,一旦释放掉就会通知客户端,然后有一个等待着的客户端就可以再次重新加锁。

    • 采用另一种方式,创建临时顺序节点:

如果有一把锁,被多个人给竞争,此时多个人会排队,第一个拿到锁的人会执行,然后释放锁;
后面的每个人都会去监听排在自己前面的那个人创建的 node 上,
一旦某个人释放了锁,排在自己后面的人就会被 ZooKeeper 给通知,
一旦被通知了之后,就 ok 了,自己就获取到了锁,就可以执行代码了。

比较:

redis 分布式锁,需要自己不断去尝试获取锁,比较消耗性能。 zk 分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小。

如果是 Redis 获取锁的那个客户端 出现 bug 挂了,那么只能等待超时时间之后才能释放锁;
而 zk 的话,因为创建的是临时 znode,只要客户端挂了,znode 就没了,此时就自动释放锁。

# 分布式事务了解吗?你们如何解决分布式事务问题的?

# 分布式事务的实现方案?

  • 两阶段提交方案/XA方案

  • TCC 方案
    TCC 的全称是: Try 、 Confirm 、 Cancel 。

  • 本地消息表

  • 可靠消息最终一致性方案

  • 最大努力通知方案

# TCC 如果出现网络连不通怎么办?XA 的一致性如何保证?

# 集群部署时的分布式 Session 如何实现?

  • 完全不用 Session

使用 JWT Token 储存用户身份,然后再从数据库或者 cache 中获取其他的信息。

  • Tomcat + Redis

基于 Tomcat 原生的 Session 支持即可,然后就是用一个叫做 Tomcat RedisSessionManager 的东西,
让所有我们部署的 Tomcat 都将 Session 数据存储到 Redis 即可。

  • Spring Session + Redis

给 Spring Session 配置基于 Redis 来存储 Session 数据,
然后配置了一个 Spring Session 的过滤器,这样的话,Session 相关操作都会交给 Spring Session 来管了。
接着在代码中,就用原生的 Session 操作,就是直接基于 Spring Session 从 Redis 中获取数据了。

# Zookeeper 的使用场景?

  • 分布式协调

如 A 系统发送个请求到 mq,然后 B 系统消息消费之后处理了。那 A 系统如何知道 B 系统的处理结果?

A 系统发送请求之后可以在 zookeeper 上对某个节点的值注册个监听器,
一旦 B 系统处理完了就修改 zookeeper 那个节点的值,A 系统立马就可以收到通知,完美解决。

  • 分布式锁

一个机器接收到了请求之后先获取 zookeeper 上的一把分布式锁,就是可以去创建一个 znode,接着执行操作;
然后另外一个机器也尝试去创建那个 znode,结果发现自己创建不了,
因为被别人创建了,那只能等着,等第一个机器执行完了自己再执行。

  • 元数据/配置信息管理

zookeeper 可以用作很多系统的配置信息的管理,
比如 kafka、storm 等等很多分布式系统都会选用 zookeeper 来做一些元数据、配置信息的管理。

  • HA高可用性

hadoop、hdfs、yarn 等很多大数据系统,都选择基于 zookeeper 来开发 HA 高可用机制,
就是一个重要进程一般会做主备两个,主进程挂了立马通过 zookeeper 感知到切换到备用进程。