参考:https://github.com/CyC2018/Interview-Notebook/blob/master/notes/
业务中的分布式:
分布式存储:将数据分片到多个节点上,不仅可以提高性能(可扩展性),同时也可以使用多个节点对同一份数据进行备份(高可用性)
分布式计算:将一个大的计算任务分解成小任务分配到多个节点上去执行,再汇总每个小任务的执行结果得到最终结果。MapReduce 是分布式计算最好的例子。
分布式事务:
指事务的操作位于不同的节点上,需要保证事务的 AICD 特性。
产生的原因:
- 数据库分库分表;
- SOA 架构,比如一个电商网站将订单业务和库存业务分离出来放到不同的节点上。
解决办法:
1. 两阶段提交协议(很好地解决分布式事务问题)
2. 消息中间件(本质上是一个暂存转发消息的一个中间件)
处理模型:(1)点对点;(2)发布/订阅
负载均衡的算法与实现:
算法有轮询(Round Robin)、加权轮询、最少连接(将请求发送给当前最少连接数的服务器)、加权最小连接、随机算法
上面的没有加权的适合服务器性能差不多场景
Zookeeper 分布式锁
Zookeeper 是一个为分布式应用提供一致性服务的软件,例如配置管理、分布式协同以及命名的中心化等,这些都是分布式系统中非常底层而且是必不可少的基本功能,但是如果自己实现这些功能而且要达到高吞吐、低延迟同时还要保持一致性和可用性,实际上非常困难。
抽象模型:Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示它的父节点为 /app1。
监听器:为一个节点注册监听器,在节点状态发生改变时,会给客户端发送消息。
节点类型
- 永久节点:不会因为会话结束或者超时而消失;
- 临时节点:如果会话结束或者超时就会消失;
- 有序节点:会在节点名的后面加一个数字后缀,并且是有序的,例如生成的有序节点为 /lock/node-0000000000,它的下一个有序节点则为 /lock/node-0000000001,依次类推。
分布式锁实现:
- 创建一个锁目录 /lock。
- 在 /lock 下创建临时的且有序的子节点,第一个客户端对应的子节点为 /lock/lock-0000000000,第二个为 /lock/lock-0000000001,以此类推。
- 客户端获取 /lock 下的子节点列表,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点,如果是则认为获得锁,否则监听自己的前一个子节点,获得子节点的变更通知后重复此步骤直至获得锁;
- 执行业务代码,完成后,删除对应的子节点。
会话超时
如果一个已经获得锁的会话超时了,因为创建的是临时节点,因此该会话对应的临时节点会被删除,其它会话就可以获得锁了。可以看到,Zookeeper 分布式锁不会出现数据库分布式锁的死锁问题。
羊群效应(在这里不存在羊群效应)
在步骤二,一个节点未获得锁,需要监听监听自己的前一个子节点,这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知(羊群效应),而我们只希望它的后一个子节点收到通知。
--------------------------------------------------------
分布式 Session
在分布式场景下,一个用户的 Session 如果只存储在一个服务器上,那么当负载均衡器把用户的下一个请求转发到另一个服务器上,该服务器没有用户的 Session,就可能导致用户需要重新进行登录等操作。
Sticky Sessions
需要配置负载均衡器,使得一个用户的所有请求都路由到一个服务器节点上,这样就可以把用户的 Session 存放在该服务器节点中。
缺点:当服务器节点宕机时,将丢失该服务器节点上的所有 Session。
Session Replication
在服务器节点之间进行 Session 同步操作,这样的话用户可以访问任何一个服务器节点。
缺点:需要更好的服务器硬件条件;需要对服务器进行配置。
Persistent DataStore
将 Session 信息持久化到一个数据库中。
缺点:有可能需要去实现存取 Session 的代码。
In-Memory DataStore
可以使用 Redis 和 Memcached 这种内存型数据库对 Session 进行存储,可以大大提高 Session 的读写效率。内存型数据库同样可以持久化数据到磁盘中来保证数据的安全性。