redis深入学习随记(1)
为什么要在项目中使用缓存?
- 高性能
- 高并发
用了缓存之后会有什么不良的后果?
- 缓存与数据库双写不一致
- 缓存雪崩
- 缓存穿透
- 缓存并发竞争
redis和memcached有啥区别?
- redis支持服务器端的数据操作:redis相比memcached来说,拥有更多数据结构和支持更多丰富的数据操作,通常在memcahed里,你需要将数据拿到客户端来进行修改再set回去,大大增加了网络IO的次数和数据体积。在redis中,这些复杂的操作通常和一般的set/get一样高效。所以如果需要缓存能够支持更复杂的结构和操作,那么redis是一个不错的选择。
- 集群模式:memcached没有原生的集群模式,需要依赖客户端来实现往集群中分片写入数据,但是redis目前是原生支持cluster模式的,redis官方就是支持cluster集群模式的。
redis的线程模型
文件事件处理器
redis基于reactor模式开发了网络事件处理器,这个处理器叫做文件事件处理器,这个文件事件处理器,是单线程的,redis才叫做单线程模型,采用IO多路复用机制同时监听多个socket,根据socket上的事件来选择对应的事件处理器来处理这个事件。
文件事件处理器的结构包括4个部分,多个socket,IO多路复用程序,文件事件分派器,事件处理器(命令请求处理器,命令回复处理器,链接应答处理器,等等)
多个socket可能并发产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用程序会监听多个socket,但是会将socket放入一个队列中排队,每次从队列去一个socket给事件分派器,时间分派器把socket给对应事件处理器。
文件事件
当socket变得可读时,或者有新的可以应答的socket出现,socket就产生一个AE_READABLE事件。
当socket变得可写的时候,socket会产生一个AE_WRITABLE事件。
IO多路复用程序可以同时监听AE_REABLE和AE_WRITABLE两种事件,如果一个socket同时产生了AE_READABLE和AE_WRITABLE两种事件,那么文件事件分派器优先处理AE_REABLE事件。
文件事件处理器
如果是客户端要连接redis,那么会为socket关联连接应答处理器。
如果是客户端要写数据到redis,那么会为socket关联命令请求处理器。
如果是客户端要从redis读取数据,那么会为socket关联命令回复处理器。
为什么redis单线程模型也能效率这么高?
- 纯内存操作
- 核心是基于非阻塞IO多路复用机制
-
单线程反而避免了多线程频繁切换上下问的问题。
01_redis单线程模型.png
一次完整的客户端与服务器连接事件实例:
追踪一次redis客户端与服务器进行连接并发送命令的过程。
假设一个redis服务器正在运行,那么这个服务器的监听套接字的AE_READABLE事件应该正处于监听状态下,而该事件对应的处理器为连接应答处理器。
如果这时有一个redis客户端向服务器发起连接,那么监听套接字产生AE_READABLE事件应该正处于监听状态下,而该事件对应的处理器为连接应答处理器。
如果这时有一个 Redis 客户端向服务器发起连接, 那么监听套接字将产生 AE_READABLE 事件, 触发连接应答处理器执行: 处理器会对客户端的连接请求进行应答, 然后创建客户端套接字, 以及客户端状态, 并将客户端套接字的 AE_READABLE 事件与命令请求处理器进行关联, 使得客户端可以向主服务器发送命令请求。
之后, 假设客户端向主服务器发送一个命令请求, 那么客户端套接字将产生 AE_READABLE 事件, 引发命令请求处理器执行, 处理器读取客户端的命令内容, 然后传给相关程序去执行。
执行命令将产生相应的命令回复, 为了将这些命令回复传送回客户端, 服务器会将客户端套接字的 AE_WRITABLE 事件与命令回复处理器进行关联: 当客户端尝试读取命令回复的时候, 客户端套接字将产生 AE_WRITABLE 事件, 触发命令回复处理器执行, 当命令回复处理器将命令回复全部写入到套接字之后, 服务器就会解除客户端套接字的 AE_WRITABLE 事件与命令回复处理器之间的关联。