redis 是不是单线程 ?
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/651eaffb470b72af3cf8bd50131d5a05.png)
redis
单线程指的是命令处理在一个单线程中。
- 主线程:
redis-server
→ 命令处理、网络事件的监听。
- 辅助线程:
bio_close_file
:异步关闭大文件。
bio_aof_fsync
:异步 aof
刷盘。
bio_lazy_free
:异步清理大块内存。
jemalloc_bg_thd
:后台线程,进行内存分配,内存释放。
io_thd_*
:IO
多线程,负责 read / write
、decode / encode
。
- 辅助线程负责处理阻塞的操作,这样可以不阻塞主线程,让主线程最大限度地处理命令,优化性能。
命令处理为什么是单线程 ?
- 为什么不采用多线程:
redis
有多个对象类型,每个对象类型又有多种数据结构的实现,导致加锁复杂、锁粒度不好控制(操作临界资源所需要的时间)。
- 频繁的
CPU
上下文切换,抵消多线程的优势。
- 单线程的局限:不能有耗时的操作,比如
CPU
运算、阻塞的 IO
,会影响 redis
的响应性能。
redis
处理 IO
密集型:
- 磁盘
IO
:
fork
进程,在子进程做持久化。
- 使用
bio_aof_fsync
,另起线程做持久化(异步 aof
刷盘)。
- 网络
IO
:
- 服务多个客户端,造成
IO
密集;数据请求或返回数据量比较大。
- 开启
IO
多线程。
redis
处理 CPU
密集型:
- 数据结构切换:
redis
会根据当前数据量的大小,选择一个数据结构去存储。
- 渐进式数据迁移:当数据量小的时候,会分配一个小的内存,当数据量大的时候,会分配一个大的内存(翻倍扩容),那么就需要将原来内存中的数据迁移到新的内存中,
redis
不会将原数据一次性都挪过去,而是采用一定的策略逐渐挪过去。
redis 单线程为什么快 ?
- 采用哪些机制:
redis
是内存数据库,大部分情况下:操作完内存后会立刻返回给客户端,不需要关注写磁盘的问题。特殊情况:使用 aof
持久化方式 + always
策略:每一次操作完内存后,都必须持久化到磁盘中,然后再返回给客户端。
- 数据结构高效:在执行效率与空间占用间保持平衡,可以进行数据结构切换。
- 采用高效的
reactor
网络模型:IO
多路复用 + 非阻塞 IO
。
- 做了哪些优化:
- 耗时阻塞的操作,另起线程处理。
- 异步关闭大文件。
- 异步释放大内存块。
- 异步
aof
刷盘。
IO
多线程。
- 将大的操作拆分成小的操作:
redis 数据组织方式:
typedef struct redisDb {
dict *dict;
dict *expires;
dict *blocking_keys;
dict *ready_keys;
dict *watched_keys;
}
struct dict {
dictType *type;
dictEntry **ht_table[2];
unsigned long ht_used