Redis 知识全景图两大维度系统维度 从系统维度上说,你需要了解 Redis 的各项关键技术的设计原理,这些能够为你判断和推理问题打下坚实的基础,而且,你还能从中掌握一些优雅的系统设计规范,例如 run-to-complete 模型、epoll 网络模型,这些可以应用到你后续的系统开发实践中。应用维度 在应用维度上,我建议你按照两种方式学习: “应用场景驱动”和“典型案例驱动”,一个是“面”的梳理,一个是“点”的掌握。
三大准线高性能主线,包括线程模型、数据结构、持久化、网络框架;高可靠主线,包括主从复制、哨兵机制;高可扩展主线,包括数据分片、负载均衡。

Redis 的问题画像图基础基本架构:一个键值数据库包含什么?Memcached 支持的 value 类型仅为 String 类型,Redis 支持的 value 类型包括了 String、哈希表、列表、集合等。Redis 能够在实际业务场景中得到广泛的应用,就是得益于支持多样化类型的 value。键值数据库的基本操作集合PUT:新写入或更新一个 key-value 对;GET:根据一个 key 读取相应的 value 值;DELETE:根据一个 key 删除整个 key-value 对;SCAN: 根据一段 key 的范围返回相应的 value 值;SimpleKV如何定位键值对的位置?索引的作用是让键值数据库根据 key 找到相应 value 的存储位置,进而执行操作。
不同键值数据库采用的索引并不相同Memcached 和 Redis 采用哈希表作为 key-value 索引RocksDB 则采用跳表作为内存中 key-value 的索引。
SimpleKV 演进到 RedisRedis 主要通过网络框架进行访问,而不再是动态库了,这也使得 Redis 可以作为一个基础性的网络服务进行访问,扩大了 Redis 的应用范围。Redis 数据模型中的 value 类型很丰富,因此也带来了更多的操作接口,例如面向列表的 LPUSH/LPOP,面向集合的 SADD/SREM 等。在下节课,我将和你聊聊这些 value 模型背后的数据结构和操作效率,以及它们对 Redis 性能的影响。
Redis 的持久化模块能支持两种方式:日志和快照,这两种持久化方式具有不同的优劣势,影响到 Redis 的访问性能和可靠性。SimpleKV 是个简单的单机键值数据库,但是,Redis 支持高可靠集群和高可扩展集群,因此,Redis 中包含了相应的集群功能支撑模块。
数据结构:快速的Redis有哪些慢操作?Redis 接收到一个键值对操作后,能以微秒级别的速度找到数据,并快速完成操作。
Redis 为啥这么快?一方面,这是因为它是内存数据库,所有操作都在内存上完成,内存的访问速度本身就很快。另一方面,这要归功于它的数据结构。这是因为,键值对是按一定的数据结构来组织的,操作键值对最终就是对数据结构进行增删改查操作,所以高效的数据结构是 Redis 快速处理数据的基础。
底层数据结构一共有 6 种,分别是简单动态字符串双向链表压缩列表哈希表跳表整数数组它们和数据类型的对应关系如下图所示:可以看到,String 类型的底层实现只有一种数据结构,也就是简单动态字符串。而 List、Hash、Set 和 Sorted Set 这四种数据类型,都有两种底层实现结构。通常情况下,我们会把这四种类型称为集合类型,它们的特点是一个键对应了一个集合的数据。为了实现从键到值的快速访问,Redis 使用了一个哈希表来保存所有键值对。
全局哈希表哈希表的最大好处很明显,就是让我们可以用 O 的时间复杂度来快速查找到键值对——我们只需要计算键的哈希值,就可以知道它所对应的哈希桶位置,然后就可以访问相应的 entry 元素。哈希表的冲突问题和 rehash 可能带来的操作阻塞。 Redis 解决哈希冲突的方式,就是链式哈希。链式哈希也很容易理解,就是指同一个哈希桶中的多个元素用一个链表来保存,它们之间依次用指针连接。
哈希冲突链上的元素只能通过指针逐一查找再操作。如果哈希表里写入的数据越来越多,哈希冲突可能也会越来越多,这就会导致某些哈希冲突链过长,进而导致这个链上的元素查找耗时长,效率降低。对于追求“快”的 Redis 来说,这是不太能接受的。 Redis 会对哈希表做 rehash 操作。
rehash 也就是增加现有的哈希桶数量,让逐渐增多的 entry 元素能在更多的桶之间分散保存,减少单个桶中的元素数量,从而减少单个桶中的冲突。Redis 采用了渐进式 rehash。避免rehash的过程中大量的数据拷贝造成的Redis现场阻塞问题。
高性能IO模型:为什么单线程Redis能那么快?Redis 是单线程,主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。单线程 Redis 为什么那么快?一方面,Redis 的大部分操作在内存上完成,再加上它采用了高效的数据结构,例如哈希表和跳表,这是它实现高性能的一个重要原因。另一方面,就是 Redis 采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率。
多路复用机制 基本 IO 模型与阻塞点非阻塞模式 在 socket 模型中,不同操作调用后会返回不同的套接字类型。socket 方法会返回主动套接字,然后调用 listen 方法,将主动套接字转化为监听套接字,此时,可以监听来自客户端的连接请求。最后,调用 accept 方法接收到达的客户端连接,并返回已连接套接字。基于多路复用的高性能 I/O 模型 Linux 中的 IO 多路复用机制是指一个线程处理多个 IO 流,就是我们经常听到的 select/epoll 机制。
简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字。内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。
下图就是基于多路复用的 Redis IO 模型。图中的多个 FD 就是刚才所说的多个套接字。Redis 网络框架调用 epoll 机制,让内核监听这些套接字。此时,Redis 线程不会阻塞在某一个特定的监听或已连接套接字上,也就是说,不会阻塞在某一个特定的客户端请求处理上。
正因为此,Redis 可以同时和多个客户端连接并处理请求,从而提升并发性。AOF日志:宕机了,Redis如何避免数据丢失?Redis 的持久化主要有两大机制AOF日志RDB 快照AOF后写日志好处好处一: 可以避免出现记录错误命令的情况。为了避免额外的检查开销,Redis 在向 AOF 里面记录日志的时候,并不会先去对这些命令进行语法检查。
所以,如果先记日志再执行命令的话,日志中就有可能记录了错误的命令,Redis 在使用日志恢复数据时,就可能会出错。好处二:它是在命令执行后才记录日志,所以不会阻塞当前的写操作。AOF三种写回策略 设置appendfsyncAlways,同步写回:。


