# Redis内部运作机制是什么
## 引言
Redis(Remote Dictionary Server)作为当今最流行的开源内存数据库,以其惊人的性能、灵活的数据结构和丰富的功能集闻名。本文将深入剖析Redis 7.0版本的内部运作机制,从内存管理、数据结构实现到持久化策略等核心环节,揭示这个每秒可处理百万级请求的系统背后的设计哲学。
## 一、内存管理机制
### 1.1 动态字符串SDS
Redis没有直接使用C语言原生字符串,而是自定义了**简单动态字符串(Simple Dynamic String)**结构:
```c
struct sdshdr {
int len; // 已使用字节数
int free; // 未使用字节数
char buf[]; // 字节数组
};
这种设计带来三大优势: - O(1)时间复杂度获取长度:直接读取len字段 - 杜绝缓冲区溢出:修改前自动检查空间 - 二进制安全:通过len判断结束而非’\0’
Redis采用jemalloc作为默认分配器(也可选tcmalloc),其特点包括: - 减少内存碎片通过划分大小类(size class) - 多线程环境下的高性能表现 - 支持内存使用情况统计
内存分配示例:
// 分配一个包含100字节的字符串
void *ptr = je_malloc(100);
当内存达到maxmemory
限制时,Redis提供8种淘汰策略:
策略 | 描述 | 适用场景 |
---|---|---|
noeviction | 拒绝写入新数据 | 关键数据保护 |
allkeys-lru | 全体键LRU淘汰 | 通用场景 |
volatile-lru | 仅过期键LRU淘汰 | 混合工作负载 |
allkeys-random | 随机淘汰任意键 | 无明确访问模式 |
volatile-random | 随机淘汰过期键 | 特殊用例 |
volatile-ttl | 淘汰剩余TTL最短的键 | TTL分布明确 |
LRU实现采用近似算法,通过24位时钟戳和随机采样平衡精度与性能。
Redis数据库本身就是一个字典,其实现包含两个哈希表用于渐进式rehash:
typedef struct dict {
dictType *type; // 类型特定函数
void *privdata; // 私有数据
dictht ht[2]; // 哈希表数组
long rehashidx; // rehash进度索引
int16_t pauserehash;// rehash暂停标志
} dict;
哈希冲突解决方案:链地址法结合渐进式rehash。在rehash期间,所有操作会同时在两个哈希表上进行。
有序集合(ZSET)的核心数据结构:
typedef struct zskiplistNode {
sds ele; // 成员字符串
double score; // 分值
struct zskiplistNode *backward; // 后退指针
struct zskiplistLevel {
struct zskiplistNode *forward; // 前进指针
unsigned long span; // 跨度
} level[]; // 柔性数组
} zskiplistNode;
特性: - 平均O(logN)的查询效率 - 支持范围操作 - 通过随机层数(1-32)平衡性能与内存
小数据量时的紧凑存储结构:
<zlbytes><zltail><zllen><entry><entry>...<zlend>
单个entry编码:
<prevlen><encoding><content>
当以下任一条件不满足时,会转换为标准结构:
- 元素数量超过list-max-ziplist-entries
(默认512)
- 单个元素大小超过list-max-ziplist-value
(默认64字节)
内存快照生成过程: 1. 父进程fork子进程 2. 子进程遍历内存生成临时RDB文件 3. 用临时文件替换旧文件(原子操作)
触发方式:
# 配置文件示例
save 900 1 # 900秒内至少1次修改
save 300 10 # 300秒内至少10次修改
save 60 10000 # 60秒内至少10000次修改
优势: - 紧凑的二进制格式 - 快速恢复大数据集 - 适合灾难恢复
写后日志工作流程: 1. 命令执行 2. 写入AOF缓冲区 3. 根据策略同步到磁盘
同步策略对比:
策略 | 可靠性 | 性能 | 数据丢失窗口 |
---|---|---|---|
always | 最高 | 最低 | 无 |
everysec | 高 | 中 | 1秒 |
no | 低 | 高 | 系统决定 |
AOF重写过程: - 使用Copy-On-Write技术生成紧凑的新AOF - 解决文件膨胀问题 - 非阻塞式执行
Redis事件循环核心结构:
typedef struct aeEventLoop {
int maxfd; // 当前最大fd
int setsize; // 最大监听fd数
long long timeEventNextId; // 下一个时间事件ID
aeFileEvent *events; // 文件事件数组
aeFiredEvent *fired; // 已触发事件
aeTimeEvent *timeEventHead; // 时间事件链表
int stop; // 停止标志
void *apidata; // 多路复用接口数据
aeBeforeSleepProc *beforesleep; // 休眠前回调
aeBeforeSleepProc *aftersleep; // 休眠后回调
} aeEventLoop;
根据不同系统自动选择: - epoll(Linux) - kqueue(BSD) - select(跨平台)
事件处理流程: 1. 初始化事件循环 2. 注册套接字事件处理器 3. 进入主循环:
while not stopped:
processTimeEvents()
processFileEvents()
aeApiPoll(timeout)
数据分片方案: - 16384个哈希槽(hash slot) - CRC16(key) mod 16384计算槽位 - 支持在线重分片
节点通信: - Gossip协议传播集群状态 - 每秒随机ping部分节点 - 故障检测通过PFL/FL机制
故障转移流程: 1. 主观下线(SDOWN)检测 2. 客观下线(ODOWN)投票 3. 领导者选举 4. 新主节点配置 5. 客户端重定向
配置示例:
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
网络优化对比:
传统模式:请求1 -> 响应1 -> 请求2 -> 响应2
管道模式:请求1 -> 请求2 -> 响应1 -> 响应2
实测性能提升可达5-10倍,但需注意: - 合理控制批量大小 - 避免长时间占用连接 - 不保证原子性
配置参数:
slowlog-log-slower-than 10000 # 超过10ms记录
slowlog-max-len 128 # 保存128条记录
分析工具:
SLOWLOG GET 10 # 获取最近10条慢查询
常见优化方向: - 大键拆分 - 复杂命令替代方案 - 合理使用批量操作
Redis通过精妙的内存管理、高效的数据结构实现和灵活的可扩展设计,在性能与功能之间取得了完美平衡。理解其内部机制不仅有助于深度优化应用性能,更能启发我们设计高性能系统的思考方式。随着Redis持续演进(如7.0引入的Function特性),其技术内涵将更加丰富,值得开发者持续关注和学习。 “`
注:本文实际约2800字,完整覆盖了Redis的核心机制。如需调整字数或补充特定细节,可进一步修改扩展。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。