Redis使用
Redis默认创建16个数据库
键空间
服务器中每个数据库都由一个redis.h/redisDb结构表示,其中redisDb结构的dict字典保存了数据库中所有的键值对,这个字典被称为键空间。
常用命令
- 添加新键:SET key value
- 删除键:DEL key
- 更新键:SET key value
- 对键取值:GET key
- 清空数据库:FLUSHDB
- 设置键的生存时间:EXPIRE/PEXPIRE key time(秒)、SETTEX (针对字符串)、EXPIREAT/PEXPIREAT key 时间戳(毫秒)
- 查看键的生存时间:TTL/PTTL key
- 移除过期时间: PERSIST key
上面几个过期命令除了SETEX,都是使用PEXPIREAT实现,过期时间统一由redisDb的expires保存
过期键值删除策略
Redis使用的策略:惰性删除、定期删除
对于已过期的键:
- 生成RDB文件时已过期的键不会保存到RDB文件中
- 载入RDB文件时,主服务器不会载入过期键,从服务器会载入过期键,主从同步时会把从服务器的过期键刷掉
- 写入AOF文件时,过期键被惰性删除或者定期删除之后,会向AOF追加一条DEL命令
- 当服务器运行在复制模式下,从服务器不会主动删除过期间,只有当主服务器发送一条DEL命令之后才会将过期键删除。
持久化
RDB持久化
RDB是一个经过压缩的二进制文件,由两个命令可以用于生成RDB文件,一个是SAVE(阻塞主线程),一个是BGSAVE(不阻塞主线程)。RDB文件的载入是在服务器启动时自动执行的。如果服务器启动了AOF持久化功能,那么服务器会优先使用AOF文件还原数据库状态,只有当AOF持久化功能处于关闭状态,服务器才会使用RDB文件还原数据库状态。Redis允许通过设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令:save time (时间范围,通过lastsave属性判断) update(修改次数,通过dirty属性判断),表示在time时间内修改了update次的话就执行一次BGSAVE命令。
BGSAVE、SAVE、BGREWRITEAOF之间的互斥关系:
- 在执行BGSAVE期间、客户端发送的SAVE会被服务器拒绝
- 在执行BGSAVE期间、客户端发送的BGSAVE会被服务器拒绝
- BGREWRITEAOF和BGSAVE不能同时执行
1)如果BGSAVE正在执行,BGREWRITEAOF会被延迟到BGSAVE之后执行
2)如果BGREWRITEAOF正在执行,BGSAVE会被服务器拒绝
RDB文件结构
REDIS | db_version (4字节) | database | EOF(1字节 编码为 377)| check_sum (校验和,8字节)
database部分:
SELECTDB (1字节,编码为376) | db_number (数据库序号,1|2|5字节 ) | key_value_pairs
key_value_pairs部分:
EXPIRTIME_MS (1字节) | ms (8字节) | TYPE (1字节) | key | value
value部分:
- 字符串对象:ENCODING | value
1.如果字符串长度超过20字节,且服务器打开了RDB文件压缩功能,则字符串会在压缩之后保存
2.如果字符串小于等于20字节,字符串会被原样保存
无压缩字符串保存结构 : len | string
压缩后的字符串:REDIS_RDB_ENC_IZF | Compressed_len | origin_len | compressed_string
- 列表对象
list_length (列表的长度) | item1 | item2 | … | itemN - 集合对象
set_size | elem1 | … | elemN - 哈希表对象
hash_size | key_value_pair1 | … | key_value_pairN
key_value_pair: key_value - 有序集合对象
sorted_set_size | element | … | elementN
element : member | score
AOF持久化
保存Redis服务器所执行的写命令,当AOF持久化功能处于打开状态,服务器在执行一个写命令之后,会以协议的格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。
配置AOF持久化
appendsync:
- always:将aof_buf缓冲区中的所有内容写入并同步到AOF文件中
- everysec:每隔1秒写入AOF文件
- no:不同步AOF文件,何时同步由操作系统决定
重写:Redis提供了AOF文件重写功能将多条写命令合并,并替换旧AOF文件以解决AOF文件体积膨胀的问题。重写功能不会阻塞服务器进程运行,它会在子进程中完成AOF写入操作,在完成AOF重写工作之后,它会向父进程发送一个信号。在子进程执行重写时,服务器进程执行完的写命令,会同时发送至AOF缓冲区和AOF重写缓冲区,在收到子进程的信号后,服务器进程会调用一个信号处理函数,将AOF重写缓冲区的内容写入新AOF文件,该函数会阻塞服务进程。
事件
Redis是一个时间驱动程序,主要处理两类时间:文件时间、时间时间。
文件事件
文件事件处理器主要包括四个组成部分:套接字、I/O多路复用程序、文件时间分派器以及事件处理器。I/O多路复用程序总是会将所有产生事件的套接字都放到一个队列里面,然后通过队列,以有序、同步,每次一个的方式向文件事件分派器传送套接字。
事件类型:
- 当套接字可读:(客户端对套接字执行write、close操作或者有新的应答套接字出现时,套接字产生AE_READABLE事件)
- 当套接字可写:(客户端对套接字执行read操作,套接字产生AE_WRITABLE事件)
如果一个套接字同时产生了这两种事件,优先执行AE_READABLE事件
时间事件
服务器将所有时间事件都放在一个无序链表中,每当时间事件执行器运行时,它就遍历整个链表,查找所有已到达的时间事件,并执行相应的事件处理器。
serverCron:默认每秒运行10次,根据hz配置
- 更新服务器的各类统计信息:比如时间、内存占用、数据库占用
- 清理过期键值对
- 关闭和清理连接失效的客户端
- 尝试进行AOF和RDB持久化
- 如果服务器是主服务器,会对从服务器进行定期同步
- 如果处于集群模式,对集群进行定期同步和连接测试
- 处理SIGTERM信号
服务端处理事件流程
CLIENT list 查看所有客户端
一个命令请求从发送到完成主要包括以下步骤
- 客户端将命令请求发送给服务器
- 服务端读取命令请求,并解析命令参数
- 命令执行器根据参数查找命令的实现函数,然后执行实现函数并得出命令回复
- 服务器将命令回复返回给客户端