已通过os信号请求关闭服务器,redis(一)内部机制的介绍和启动过程
redis(一)內部機制的介紹和啟動過程
redis的基本介紹
redis服務端
redis客戶端
redis的持久化
redis中的文件事件和時間時間
redis的啟動過程
redis的基本介紹
redis是一種非關系型數(shù)據(jù)庫,采用=key,value的形式來存儲數(shù)據(jù)。key是二進制數(shù)據(jù),對于value的數(shù)據(jù)類型,redis支持string、hash、list、set、sorted set五種類型。
對于單個redis實例,內部使用多線程通信,但是對外采用RESP單線程通信協(xié)議,在TCP層通過二進制方式進行傳輸數(shù)據(jù),單線程采用同步的請求方式。
redis服務端
redis服務端內部結構為struct redisServer和struct redisDb。redis中默認16個數(shù)據(jù)庫,可以通過配置來修改數(shù)據(jù)庫數(shù)量,每一個數(shù)據(jù)庫對應一個redisDb。數(shù)據(jù)庫之間的數(shù)據(jù)是相互獨立的。查詢數(shù)據(jù)的時候,可以通過select指定具體某個數(shù)據(jù)庫。
1 struct redisServer {2 int dbnum;//服務器的數(shù)據(jù)庫數(shù)量,值由服務器配置的“databases”選項決定,默認為16
3 redisDb *db;//數(shù)組,保存著服務器中的所有數(shù)據(jù)庫
4
5 list *clients;//一個鏈表,保存了所有客戶端狀態(tài),每個鏈表元素都是“redisClient”結構
6
7 time_t unixtime;//保存秒級精度的系統(tǒng)當前UNIX時間戳,減少獲取系統(tǒng)當前時間的系統(tǒng)調用次數(shù),100毫秒更新一次
8 long long mstime;//保存毫秒級精度的系統(tǒng)當前UNIX時間戳
9 unsigned lruclock;//默認每10秒更新一次,用于計算數(shù)據(jù)庫鍵的空轉時長,數(shù)據(jù)庫鍵的空轉時長 = 服務器的“l(fā)ruclock”屬性值 - 數(shù)據(jù)庫鍵值對象的“l(fā)ru”屬性值
10
11 long long ops_sec_last_sample_time;//上一次進行服務器每秒執(zhí)行命令數(shù)量抽樣的時間
12 long long ops_sec_last_sample_ops;//上一次進行服務器每秒執(zhí)行命令數(shù)量抽樣時,服務器已執(zhí)行命令的數(shù)量
13 long long ops_sec_samples[REDIS_OPS_SEC_SAMPLE];//環(huán)形數(shù)組,每個元素記錄一次服務器每秒執(zhí)行命令數(shù)量抽樣結果,估算服務器在最近一秒鐘處理的命令請求數(shù)量(數(shù)組長度默認為16,100毫秒更新一次)
14 int ops_sec_idx;//ops_sec_samples數(shù)組的索引值,每次抽樣后值增1,等于16時重置為0
15
16 size_t stat_peak_memory;//已使用內存峰值
17
18 int shutdown_asap;//關閉服務器的標識,1表示關閉,0不關閉
19
20 pid_t rdb_child_pid;//記錄執(zhí)行BGSAVE命令的子進程的ID,-1表示服務器沒有正在執(zhí)行BGSAVE
21 pid_t aof_child_pid;//記錄執(zhí)行BGREWRITEAOF命令的子進程的ID,-1表示服務器沒有正在執(zhí)行BGREWRITEAOF
22 int aof_rewrite_scheduled;//1表示有BGREWRITEAOF命令被延遲了(服務器執(zhí)行BGSAVE期間收到的BGREWRITEAOF會被延遲到BGSAVE執(zhí)行完成之后執(zhí)行)
23 struct saveparam *saveparams;//記錄了自動保存條件的數(shù)組(執(zhí)行BGSAVE的條件)
24 long long dirty;//修改計數(shù)器(上一次執(zhí)行BGSAVE之后已經(jīng)產生了多少修改)
25 time_t lastsave;//上一次執(zhí)行自動保存操作(BGSAVE)的時間
26 sds aof_buf;//AOF緩沖區(qū)
27
28 int cronloops;//serverCron函數(shù)的運行次數(shù)計數(shù)器
29
30 lua;//用于執(zhí)行Lua腳本的Lua環(huán)境
31 redisClient *lua_client;//Lua腳本的偽客戶端,在服務器運行的整個生命周期一直存在,直至服務器關閉才會關閉
32 dict *lua_scripts;//字典,記錄所有載入的Lua腳本,鍵為某個Lua腳本的SHA1校驗和,值為對應的Lua腳本
33 dict *repl_scriptcache_dict;//字典,記錄已經(jīng)傳播給所有從服務器的所有Lua腳本,鍵為腳本的SHA1校驗和,值為NULL,用于EVALSHA1命令的復制
34
35 long long slowlog_entry_id;//下一條慢查詢日志的ID
36 list *slowlog;//保存了所有慢查詢日志的鏈表
37 long long slowlog_log_slower_than;//服務器配置“slowlog-log-slower-than”選項的值,表示查詢慢于多少微秒便記錄慢查詢日志
38 unsigned long slowlog_max_len;//服務器配置“slowlog-max-len”選項的值,表示服務器最多保存多少條慢查詢日志記錄,若超出,最久的記錄會被覆蓋
39
40 monitors;//鏈表,監(jiān)視器客戶端列表
41
42 dict *pubsub_channels;//字典,保存所有頻道的訂閱關系,鍵為某個被訂閱的頻道,值為鏈表,記錄了所有訂閱這個頻道的客戶端
43 list *pubsub_patterns;//鏈表,保存所有模式的訂閱關系,每個鏈表節(jié)點都包含了訂閱的客戶端和被訂閱的模式
44 };
struct redisDb {
dict*dict;//數(shù)據(jù)庫鍵空間字典,保存數(shù)據(jù)庫中所有的鍵值對
dict *expires;//過期字典,保存數(shù)據(jù)庫中所有鍵的過期時間
dict *watched_keys;//字典,正在被WATCH命令監(jiān)視的鍵
};
redisDb中三個字典中的key共享對象,value值不一樣。對于過期的鍵,redis采用惰性刪除和定時刪除相結合的方式,惰性刪除,指執(zhí)行之前會查看這個key是否過期,定時刪除值一段時間之后分多次遍歷數(shù)據(jù)庫,每次只刪除部分過期的數(shù)據(jù)。
redis客戶端
redis-server通過tcp端口或socket來創(chuàng)建和redis-cli的連接,可以修改redis.conf中的maxclients來指定最大連接數(shù),在建立連接之后,socket會被設置為非阻塞模式,同時創(chuàng)造一個struct redisClient來保存客戶端的連接信息。
1 struct redisClient {2 redisDb *db;//記錄客戶端當前正在使用的數(shù)據(jù)庫,上文提到之前有16個們默認的數(shù)據(jù)庫,可以通過select進行切換數(shù)據(jù)庫
3 int fd;//客戶端正在使用的套接字描述符,-1表示偽客戶端(AOF文件或者Lua腳本),大于-1表示普通客戶端
4 robj *name;//客戶端名字
5 int flags;//客戶端標志,記錄了客戶端的角色,以及客戶端目前所處的狀態(tài)
6 sds querybuf;//輸入緩沖區(qū),根據(jù)輸入內容動態(tài)地縮小或擴大,但不能超過1GB,否則服務器將關閉這個客戶端
7 robj **argv;//命令與命令參數(shù),數(shù)組,每個元素都是一個字符串對象,argv[0]為命令,其余元素為參數(shù)
8 int argc;//argv數(shù)組的長度
9 struct redisCommand *cmd;//當前執(zhí)行的命令的實現(xiàn)函數(shù),指向命令表中的命令結構
10 char buf[REDIS_REPLY_CHUNK_BYTES];//固定大小輸出緩沖區(qū),數(shù)組,默認大小為16KB
11 int bufpos;//buf數(shù)組目前已使用的字節(jié)數(shù)量
12 list *reply;//可變大小輸出緩沖區(qū),鏈表
13 obuf_soft_limit_reached_time:記錄了“reply”輸出緩沖區(qū)第一次到達軟性限制的時間,用于計算持續(xù)超出軟性限制的時長,以此決定是否關閉客戶端14 int authenticated;//0表示未通過身份驗證,1表示已通過身份驗證
15 time_t ctime:創(chuàng)建客戶端的時間,可用于計算客戶端與服務器連接的時間長度16 time_t lastinteraction:客戶端與服務器最后一次進行互動的時間,可用于客戶端的空轉時長17 multiState mstate;//事務狀態(tài),包含一個事務隊列,以及一個已入列命令計數(shù)器
18 };
db:是一個指針,指向Redis服務器狀態(tài)結構中的“db”數(shù)組其中一個元素,表示當前客戶端正在使用的數(shù)據(jù)庫。默認情況下,Redis客戶端的目標數(shù)據(jù)庫為0號數(shù)據(jù)庫,可以通過select命令切換,所以select命令的實現(xiàn)原理為:修改redisClient.db指針,讓它指向服務器中指定的數(shù)據(jù)庫。
fd:連接當前客戶端與Redis服務器的套接字描述符。值為-1表示偽客戶端(AOF文件或者Lua腳本),值大于-1則表示普通客戶端。Redis客戶端分為普通客戶端與偽客戶端兩種類型,其中通過網(wǎng)絡連接與Redis服務器進行連接的就是普通客戶端,反之則是偽客戶端了。偽客戶端也有兩種類型,分別是Lua腳本的偽客戶端和AOF文件的偽客戶端。Redis服務器狀態(tài)結構的“l(fā)ua_client”屬性就保存了Lua腳本的偽客戶端,它會在Redis服務器初始化時就被創(chuàng)建,負責執(zhí)行Lua腳本中包含的Redis命令,在服務器運行的整個生命周期一直存在,直至服務器關閉才會關閉。而AOF偽客戶端則是在載入AOF文件時被創(chuàng)建,用于執(zhí)行AOF文件中的Redis命令,在AOF文件載入完成之后被關閉。client list:列出目前所有連接到服務器的普通客戶端。
redis的持久化
AOF、RDB指的是redis持久化策略,可以通過redis.conf中的參數(shù)來配置。
appendfsync (always/everysec/no)
save [time(s)] [times]
AOF指的是保存操作命令,他會將每一次redis的數(shù)據(jù)操作命令追加到文件中,當鍵過期的時候會加入del命令,并且每過一段時間,會對已經(jīng)生成的文件優(yōu)化一次,主要指的是操作命令的合并。
RDB指的是執(zhí)行save或bgsave命令創(chuàng)建一個新的RDB文件,新建一個子進程,把所有的數(shù)據(jù)寫入文件。
redis中的文件事件和時間時間
redis中的事件分為文件事件和時間事件
文件事件:指的是通過epoll實現(xiàn)io多路復用程序來監(jiān)聽多個套接字,對讀、寫、關閉、連接都支持事務,支持原子操作。
時間事件:指的是redis中在默寫特定時間執(zhí)行操作,主要有定時事件和周期性事件。所有的時間事件會被放在一個無須列表中,新加入的事件會在事件的頭部插入。每次執(zhí)行事件的時候都會去遍歷列表。正常情況下只有一個serverCron時間時間,在benchmark模式下,也只有兩個時間事件。
redis的啟動過程
(1)初始化服務器狀態(tài)結構
新創(chuàng)建一個struct redisServer類型的實例變量作為服務器的狀態(tài),記錄著整個服務器的狀態(tài),并為結構中的各個屬性設置默認值,例如:服務器的運行ID、默認配置文件路徑、默認端口等等,同時創(chuàng)建Redis命令表。
(2)載入配置選項
載入用戶指定的配置參數(shù)和配置文件,并根據(jù)用戶設定的配置,對服務器狀態(tài)變量的相關屬性進行修改。
(3)初始化服務器數(shù)據(jù)結構
這一步主要是為服務器狀態(tài)中的一些數(shù)據(jù)結構分配內存,例如:
“clients“:鏈表,保存所有與服務器連接的客戶端的狀態(tài)結構。
”db“:字典保存服務器的所有數(shù)據(jù)庫。
”lua“:用于執(zhí)行Lua腳本的Lua環(huán)境。
”slowlog“:用于保存慢查詢日志。
除此之外,還會進行一些非常重要的設置操作,例如:
為服務器設置進程信號處理器。
創(chuàng)建共享對象,例如經(jīng)常經(jīng)常用到的“OK”回復字符串對象,1到10000的字符串對象等等。
為serverCron函數(shù)創(chuàng)建時間事件。
如果AOF持久化功能已經(jīng)打開,則打開現(xiàn)有的AOF文件,若AOF文件不存在,則創(chuàng)建并打開一個新的AOF文件,為AOF寫入做好準備。
初始化服務器的后臺I/O模塊,為將來的I/O操作做好準備。
(4)還原數(shù)據(jù)庫狀態(tài)
若服務器啟用了AOF持久化功能,則載入AOF文件,否則載入RDB文件,根據(jù)AOF文件或RDB文件記錄的內容還原數(shù)據(jù)庫狀態(tài),同時在日志文件中打印出載入文件并還原數(shù)據(jù)庫狀態(tài)所耗費的時長。
(5)執(zhí)行事件循環(huán)
一切準備就緒,開始執(zhí)行服務器的事件循環(huán),開始接受客戶端的連接請求,處理客戶端發(fā)送的命令請求。
來源:oschina
鏈接:https://my.oschina.net/u/4332949/blog/3449911
總結
以上是生活随笔為你收集整理的已通过os信号请求关闭服务器,redis(一)内部机制的介绍和启动过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图像风格迁移cvpr2020_CVPR
- 下一篇: java matcher replace