# 分布式架构
# 为什么要进行系统拆分?
业务发展到一定量级,达到单体系统负载极限,无法再承载业务的进一步发展。
通过分而治之的方式,将系统拆分为子系统,进而通过扩展的方式不断适应业务的发展。
具体来讲,以下因素是考虑系统拆分的原因:
- 获得更高的系统整体性能;
- 使得系统可维护性、可扩展性增强;
- 增加代码的可维护性,减少代码冲突;
- 增加子系统的边界,保持领域内问题可控。
# 如何进行系统拆分?
- 考虑组织架构(康威定理);
- 考虑领域划分;
- 考虑系统内聚与解耦;
- 考虑系统的分层;
- 考虑模块的代码量。
# 分布式服务接口的幂等性如何设计(比如不能重复扣款)?
- 保证幂等性主要是三点:
- 对于每个请求必须有一个唯一的标识;
- 每次处理完请求之后,必须有一个记录标识这个请求处理过了;
- 每次接收请求需要进行判断,判断之前是否处理过。
需要结合业务场景解决。
比如利用 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 感知到切换到备用进程。