天天看點

redis的單線程

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的單線程

前台顯示redis的pid是18741。

除了

out.18741

是redis本身的線程之外,其餘三個都與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來實作的。是以它可以處理并發。

當我們開一個用戶端:

redis的單線程

也追蹤到了用戶端資料的到達:

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:

redis的單線程

該程序是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。

繼續閱讀