1. 什么是分布式?
- 将服务部署在多台机器上,就叫分布式。分布式有两种形式,一种是水平扩展,即将同样的系统部署在多台机器上,让流量分发到这多台机器上;另一种是垂直拆分,就是把一个系统拆分成若干个子系统,不同的子系统负责不同的服务。
2. 什么是集群?
- 不同的机器部署相同的服务,对外表现为一个整体。集群要具有高可用性,一台机器挂了其他机器还能正常提供服务;也得具备可扩展性,可以动态地增加机器,提高集群的处理能力;还得具备负载均衡能力。
3. 什么是 CAP 定理?
- C 表示一致性,A 表示可用性,P 表示分区容错性。分布式系统是通过网络联通的,但是由于一些故障可能导致各节点之间联不通了,数据分布在不同的节点上,这就叫出现了网络分区。当某份数据只保存在某一个节点且那个节点又挂掉了的时候,那个整个系统就不可用了,这时就没有容错性,这种情况是要避免的,因此只能把相同的数据部署在多个节点上,而这又会带来一致性的问题。要保证各节点的数据完全一致,那么写数据时就得让所有节点都成功了才算成功,这又会带来可用性的问题。所以并不是 CAP 只能 CP 或 AP,只是当网络发生分区时,分区容错性是一定要满足的,不能出现分区了整个服务就不可用了,所以就得在一致性和可用性之间做取舍。
4. 什么是 base 理论?
- base 理论是基本可用、软状态和最终一致性三个单词的缩写,也就是分布式系统出现故障的时候,允许损失部分的可用性,多个节点的数据同步允许存在一定的延时,即允许软状态存在,通过一定时间的同步后,最终能够达到一致性,这是对一致性和可用性权衡的结果。
5. 对 dubbo 了解吗?
- dubbo 是阿里开源的 RPC 框架,所谓 RPC,就是远程调用,即调用别的服务的方法可以像调用本地方法一样。dubbo 的架构是由 注册中心 register、监控中心 monitor、服务提供者 provider 和服务消费者 consumer 组成。dubbo 工作流程就是 provider 向 register 注册自己的服务,consumer 在 register 订阅自己需要的服务,同时 provider 和 consumer 都会记录自己的调用次数和时间等,发送到 monitor 中进行统计。dubbo 底层采用 netty 进行通信。
6. 分布式锁有哪些实现方案? 分布式锁应该要做到在同一时刻同一方法只能被一台机器的一个线程执行,同事具备可重入性,具备锁失效机制,具备非阻塞锁的特性,具备高可用性以及高性能。
- 用数据库实现:执行逻辑前先往数据库插入一条记录,如果成功,就表示占锁成功,执行完逻辑后删除记录;如果插入失败,就以当前线程 ID ,机器 IP 以及方法名为条件去查询是否存在记录,如果存在,则表示获取锁成功。
- 用 Redis 实现:利用 Redis 的 set k v nx ex 命令就可以达到分布式锁效果,不过这种方式只适用单机版的 Redis,如果 Redis 是集群,那就可能存在 master 上设置了 key,还没来得及同步到 slave 上的时候,master 挂了,slave 成了新的 master,新的 master 上没有该 key,因此又可以获取锁成功。解决办法是用 red lock,即红锁算法,要在超过一半的 Redis 节点上都获取锁成功了且获取锁的总时间小于锁过期时间时,才会认为获取锁成功。还有一点要注意,Redis 释放锁的时候应该用 lua 脚本,因为释放锁时首先要根据 key 获取到值,然后判断值跟自己的值是否相同,相同再删除 key,这并不是一个原子操作,因此要用 lua 脚本实现。
- 用 zookeeper 实现:可以用 zookeeper 的临时顺序节点来实现。先新建一个 lock 持久节点,然后线程申请锁时,就在 lock 下新建一个临时顺序节点比如 lock1,然后查找 lock 下所有节点,判断 lock1 是不是第一个,如果是,获取锁成功,如果不是,获取锁失败,同时监控自己前面的那个节点,当自己前面那个节点被干掉时,再去检查自己是不是第一个。
7. 分布式 ID 有哪些实现方案? 分布式 ID 应该全局唯一,趋势递增,单调递增,保证信息安全,不能根据已知 ID 猜出下一个 ID,含时间戳,便于追踪问题。
- UUID:本地生成,没有网络消耗,但是无序,不能趋势递增,入库性能较差;
- 数据库自增:搞个专门的表,用 replace into 语句来插入数据生成 ID,简单易用,不需要额外的成本,但是并发性不好;
- 用 Redis 实现:利用 Redis 的 incr 或者 incrby,性能好,但需要维护 Redis 集群,成本较高;
- 雪花算法:是一个 64bit 的整数,首位是符号位,固定是 0,第 2 到 42 位是时间戳,全部是 1 的话,换算后大概是 69 年,从 1970 年开始算,可以用到 2039 年;第 43 到 52 位,5 位表示机房号,5 位 表示机器编号,最后 12 位是序列号,用来记录同一毫秒内生成的不同 ID。性能好,同意机器同一毫秒内最多生成 4095 个 ID,但是可能会出现时钟回拨问题。所谓时钟回拨,就是如果服务器的时间快了,通过 ntp 校验后,回到了以前的时间,这样就可能生成重复的 ID。可以用百度开源的 UidGenerator、hutool 工具里的雪花算法来解决这个问题。