redis的worker是單線程的,是以redis是一把天然的鎖。
但是,怎麼才能知道worker是單線程的呢?
我們用這個指令來啟動一個前台的redis:
strace -ff -o ../../test_redis/out ./redis-server
我們将追蹤所有
fork
系指令,并且把結果放在
../../test_redis_process
這個檔案夾裡,以
out
作為字首。
運作之後,在
test_redis
目錄下,我們看到:
-rw-r--r-- 1 root root 35690 May 22 18:55 out.18741
-rw-r--r-- 1 root root 134 May 22 18:55 out.18742
-rw-r--r-- 1 root root 134 May 22 18:55 out.18743
-rw-r--r-- 1 root root 134 May 22 18:55 out.18744
有4個檔案。

前台顯示redis的pid是18741。
除了
out.18741
是redis本身的線程之外,其餘三個都與redis的實際工作無關。
我們檢視linux18741程序的任務,有4個線程。和我們用strace追蹤到的是一樣的。
現在的問題是,這個
out.18741
的檔案裡有什麼?以及,單線程的redis如何處理并發?
我們很自然的
vi out.18741
。
熟悉的東西找到了:
epoll_create(1024) = 5
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 7
bind(7, {sa_family=AF_INET, sin_port=htons(6379),
sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(7, 511) = 0
epoll_ctl(5, EPOLL_CTL_ADD, 6, {EPOLLIN, {u32=6, u64=6}}) = 0
epoll_wait(5, [], 10128, 0) = 0
我們證明了,redis底層使用epoll來實作的。是以它可以處理并發。
當我們開一個用戶端:
也追蹤到了用戶端資料的到達:
read(8, "*3\r\n$3\r\nset\r\n$6\r\nuser:1\r\n$9\r\noce"..., 16384) = 40
我們知道,bgsave會觸發rdb的持久化,這時會fork一個子程序來完成。
前台的log:
該程序是19154。
我們在
out.18741
中查一下:
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7ff811c3c250) = 19154
write(1, "18741:M 22 May 2020 19:20:12.468"..., 74) = 74
read(3, 0x7ffefeed83cf, 1) = -1 EAGAIN (Resource temporarily unavailable)
write(8, "+Background saving started\r\n", 28) = 28
它用了
clone
,當然這也是一種fork。