分布式面试题
有使用过缓存吗?Redis和Memcached有什么区别?
redis相比memcached有哪些优势:
- memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
- redis的速度比memcached快很多
- redis可以持久化其数据
Redis的线程模型?单线程的Redis如何实现高性能的?
-
线程模型:
-
Redis 基于 Reactor 模式开发了自己的网络事件处理器: 这个处理器被称为文件事件处理器(file event handler):
-
- 文件事件处理器使用 **I/O 多路复用(multiplexing)**程序来同时监听多个套接字, 并根据套接字目前执行的任务来为套接字关联不同的事件处理器。
-
- 当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作时, 与操作相对应的文件事件就会产生, 这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。
-
虽然文件事件处理器以单线程方式运行, 但通过使用 I/O 多路复用程序来监听多个套接字, 文件事件处理器既实现了高性能的网络通信模型, 又可以很好地与 redis 服务器中其他同样以单线程方式运行的模块进行对接, 这保持了 Redis 内部单线程设计的简单性。
详细介绍:Redis线程模型
什么是分布式锁?使用Redis实现过分布式锁
分布式锁的四个条件:
- 互斥性:任意时刻,只能有一个客户端获取锁,不能同时有两个客户端获取到锁。
- 安全性:锁只能被持有该锁的客户端删除,不能由其它客户端删除。
- 死锁:获取锁的客户端因为某些原因(如down机等)而未能释放锁,其它客户端再也无法获取到该锁。
- 容错:当部分节点(redis节点等)down机时,客户端仍然能够获取锁和释放锁。
分布式锁三种实现方式:
- 数据库乐观锁
- 基于Redis的分布式锁
- 基于ZooKeeper的分布式锁
Redis实现分布式锁:
- Jedis开源组件的jedis.set(String key, String value, String nxxx, String expx, int time)方法获取锁
- 释放锁;使用jedis.eval()方法调用Luau脚本代码,eval()方法是将Lua代码交给Redis服务端执行;例如Lua脚本文本:
if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end
详细介绍:Redis分布式锁的正确实现方式
Zookeeper实现的分布式锁和Redis有何区别?
- Zookeeper使用会话有效期方式解决死锁现象。
- Redis 是对key设置有效期解决死锁现象
-
可靠性:
- 从可靠性角度分析,Zookeeper可靠性比Redis更好。
- 因为Redis有效期不是很好控制,可能会产生有效期延迟,Zookeeper就不一样,因为Zookeeper临时节点先天性可控的有效期,所以相对来说Zookeeper比Redis更好
Zookeeper和Redis分布式锁详细介绍:为什么分布式要有分布式锁!
-
Redis的key过期处理策略
-
- 定时删除:在设置键的过期时间的时候创建一个定时器,当过期时间到的时候立马执行删除操作。不过这种处理方式是即时的,不管这个时间内有多少过期键,不管服务器现在的运行状况,都会立马执行,所以对CPU不是很友好。
-
- 惰性删除:惰性删除策略不会在键过期的时候立马删除,而是当外部指令获取这个键的时候才会主动删除。处理过程为:接收get执行、判断是否过期(这里按过期判断)、执行删除操作、返回nil(空)。
-
- 定期删除:定期删除是设置一个时间间隔,每个时间段都会检测是否有过期键,如果有执行删除操作。这个概念应该很好理解。
分布式事务有了解吗?如何实现分布式事务?
分布式事务用于在分布式系统中保证不同节点之间的数据一致性。
分布式事务的实现有很多种,最具有代表性的是由Oracle Tuxedo系统提出的XA分布式事务协议。XA协议包含两阶段提交(2PC)和三阶段提交(3PC)两种实现
在XA协议中包含着两个角色:事务协调者和事务参与者。
- 2PC成功处理
-
第一阶段
- 作为事务协调者的节点会首先向所有的参与者节点发送Prepare请求。
- 在接到Prepare请求之后,每一个参与者节点会各自执行与事务有关的数据更新,写入Undo Log和Redo Log。如果参与者执行成功,暂时不提交事务,而是向事务协调节点返回“完成”消息。
-
当事务协调者接到了所有参与者的返回消息,整个分布式事务将会进入第二阶段。
第二阶段
- 如果事务协调节点在之前所收到都是正向返回,那么它将会向所有事务参与者发出Commit请求。
- 接到Commit请求之后,事务参与者节点会各自进行本地的事务提交,并释放锁资源。当本地事务完成提交后,将会向事务协调者返回“完成”消息。
-
当事务协调者接收到所有事务参与者的“完成”反馈,整个分布式事务完成。
- 2PC失败处理
在XA的第一阶段,如果某个事务参与者反馈失败消息,说明该节点的本地事务执行不成功,必须回滚。
于是在第二阶段,事务协调节点向所有的事务参与者发送Abort请求。接收到Abort请求之后,各个事务参与者节点需要在本地进行事务的回滚操作,回滚操作依照Undo Log来进行。
-
第一阶段
-
-
- 性能问题;XA协议遵循强一致性。在事务执行过程中,各个节点占用着数据库资源,只有当所有节点准备完毕,事务协调者才会通知提交,参与者提交后释放资源。这样的过程有着非常明显的性能问题。
- 协调者单点故障问题;事务协调者是整个XA模型的核心,一旦事务协调者节点挂掉,参与者收不到提交或是回滚通知,参与者会一直处于中间状态无法完成事务。
- 丢失消息导致的不一致问题;在XA协议的第二个阶段,如果发生局部网络问题,一部分事务参与者收到了提交消息,另一部分事务参与者没收到提交消息,那么就导致了节点之间数据的不一致。
参考链接:漫画:什么是分布式事务?
-
XA三阶段提交(3PC)
- 三阶段提交在两提交的基础上增加了CanCommit阶段,并且引入了超时机制。一旦事务参与者迟迟没有接收到协调者的commit请求,会自动进行本地commit。这样有效解决了协调者单点故障的问题。但是性能问题和不一致的问题仍然没有根本解决。