Catalog
  1. 1. version 5.0
redis 单线程 or 多线程

忘记是什么原因了,看了一下 redis 的线程数,发现不止一个线程。从用 redis 起就认为它是单线程的,也没有研究过,趁这个机会挖掘一下。由于未发布的 6.0 在 IO 线程上有一些优化,所以这里将 5.0 及以下分析一下。

version 5.0

我测试了两个版本, 4.0 和 5.0, 启动后都是有 4 个线程。并且这两个版本在线程这块的代码差不多,我就拿5.0来说。如果再早的版本跟他们不一致的话,这里也不做讨论了。我是直接搜索源码 pthread_create 的,发现只有一处调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* Initialize the background system, spawning the thread. */
void bioInit(void) {
pthread_attr_t attr;
pthread_t thread;
size_t stacksize;
int j;

/* Initialization of state vars and objects */
for (j = 0; j < BIO_NUM_OPS; j++) {
pthread_mutex_init(&bio_mutex[j],NULL);
pthread_cond_init(&bio_newjob_cond[j],NULL);
pthread_cond_init(&bio_step_cond[j],NULL);
bio_jobs[j] = listCreate();
bio_pending[j] = 0;
}

/* Set the stack size as by default it may be small in some system */
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr,&stacksize);
if (!stacksize) stacksize = 1; /* The world is full of Solaris Fixes */
while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= 2;
pthread_attr_setstacksize(&attr, stacksize);

/* Ready to spawn our threads. We use the single argument the thread
* function accepts in order to pass the job ID the thread is
* responsible of. */
for (j = 0; j < BIO_NUM_OPS; j++) {
void *arg = (void*)(unsigned long) j;
if (pthread_create(&thread,&attr,bioProcessBackgroundJobs,arg) != 0) {
serverLog(LL_WARNING,"Fatal: Can't initialize Background Jobs.");
exit(1);
}
bio_threads[j] = thread;
}
}

BIO_NUM_OPS 宏定义为 3。 到这里就能看出4个线程分别是 1 个主线程和 3 个 bio 线程。
主线程就负责网络 I/O 以及请求的处理,也就是我们熟知的 redis 是单线程的概念,因为业务只在这一个线程中处理,所以说 redis 是单线程也没有什么很大的问题。关于 bio 线程,大致看了一下,主要工作是完成 aof 写磁盘、释放内存、关闭文件任务。

总的来说,redis 是一个线程处理所有的客户端请求,其他线程处理耗时任务。

Author: 42
Link: http://blog.ikernel.cn/2019/11/25/redis%E7%BA%BF%E7%A8%8B/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment