一文搞懂Redis中的慢查詢?nèi)罩竞捅O(jiān)視器
慢查詢
添加新日志
在每次執(zhí)行命令的之前和之后,程序都會記錄微妙格式的當前UNIX時間戳,這兩個時間戳之間的差就是服務(wù)器執(zhí)行命令所耗費的時長,服務(wù)器會將這個時長作為參數(shù)之一傳給slowlogPushEntryIfNeeded函數(shù),而slowlogPushEntryIfNeeded函數(shù)則負責檢查是否需要為這次執(zhí)行的命令創(chuàng)建慢查詢?nèi)罩尽?/p>
偽代碼過程
# 記錄執(zhí)行命令前的時間 before = unixtime_now_in_us() # 執(zhí)行命令 execute_command(argv, argc, client) # 記錄執(zhí)行命令后的時間 after = unixtime_now_in_us() # 檢查是否需要創(chuàng)建新的慢查詢?nèi)罩? slowlogPushEntryIfNeeded(argv, argc, after - before)
slowlogPushEntryIfNeeded函數(shù)的作用
- 1.檢查命令的時長是否超過slowlog-log-slower-than選項設(shè)置的時間, 如果是的話,就為命令創(chuàng)建一個新的日志,并將新日志添加到slowlog鏈表的表頭
- 2.檢查慢查詢?nèi)罩镜拈L度是否超過slowlog-max-len選項所設(shè)置的長度,如果是的話,那么將多出來的日志從slowlog鏈表中刪除掉
slowlogPushEntryIfNeeded函數(shù)的實現(xiàn)代碼:
void slowlogPushEntryIfNeeded(robj **argv, int argc, long long duration) { // 慢查詢功能未開啟,直接返回 if (server.slowlog_log_slower_than < 0) return ; // 如果執(zhí)行時間超過服務(wù)器設(shè)置的上限,那么將命令添加到慢查詢?nèi)罩? if (duration >= server.slowlog_log_slower_than) // 新日志添加到鏈表表頭 listAddNodeHead(server.slowlog, slowlogCreateEntry(argv, argc, duration)); // 如果日志數(shù)量過多,那么進行刪除 while (listLength(server.slowlog) > server.slowlog_max_len) listDelNode(server.slowlog, listLast(server.slowlog)) }
該函數(shù)根據(jù)傳入的參數(shù),創(chuàng)建一個新的慢查詢?nèi)罩荆edisServer.slowlog_entry_id的值增1
例子
舉個例子。假設(shè)服務(wù)器當前保存的慢查詢?nèi)罩救鐖D所示,如果執(zhí)行以下命令:
127.0.0.1:6379> EXPIRE msg 10086 (integer) 1
服務(wù)器在執(zhí)行完這個EXPIRE命令之后,就會調(diào)用slowlogPushEntryIfNeeded函數(shù),函數(shù)將未EXPIRE命令創(chuàng)建一條id為7的慢查詢?nèi)罩?,并將這條新日志添加到slowlog鏈表的表頭如圖所示.注意,除了slowlog鏈表發(fā)生了變化之外,slowlog_entry_id的值也從7變?yōu)?了,之后,slowlogPushEntryIfNeeded函數(shù)發(fā)現(xiàn),服務(wù)器設(shè)定的最大慢查詢?nèi)罩緮?shù)目為5條,而服務(wù)器目前保存的慢查詢?nèi)罩緮?shù)目為6條,于是服務(wù)器將id為2的慢查詢?nèi)罩緞h除,讓服務(wù)器的慢查詢?nèi)罩緮?shù)量回到設(shè)定好的5條
監(jiān)視器
概述
通過執(zhí)行MONITOR命令,客戶端可以將自己變?yōu)橐粋€監(jiān)視器,實時地接收并打印出服務(wù)器當前處理的命令請求的相關(guān)信息:
127.0.0.1:6379> MONITOR OK 1713790637.787549 [0 127.0.0.1:60753] "PING" 1713790641.908992 [0 127.0.0.1:60753] "SET" "k1" "v1" 1713790645.044945 [0 127.0.0.1:60753] "SET" "k2" "v2"
每當一個客戶端服務(wù)器發(fā)送一條命令請求時,服務(wù)器除了會處理這條命令請求之外,還會將關(guān)于這條命令請求的信息發(fā)送給所有監(jiān)視器,如圖所示
成為監(jiān)視器
發(fā)送MONITOR命令可以讓一個普通客戶端變?yōu)橐粋€監(jiān)視器,該命令的實現(xiàn)原理可以用以下偽代碼來實現(xiàn):
def MONITOR(): # 打開客戶端的監(jiān)視器狀態(tài) client.flags |= REDIS_MONITOR # 將客戶端添加到服務(wù)器狀態(tài)的monitors鏈表的末尾 server.monitor.append(client) # 向客戶端返回OK send_reply("OK")
例子
舉個例子,如果客戶端c10086向服務(wù)器發(fā)送MONITOR命令,那么這個客戶端的REDIS_MONITOR標志會被打開,并且這個客戶端本身會被添加到monitors鏈表的表尾。假設(shè)客戶端c10086發(fā)送MONITOR之前,monitors鏈表的狀態(tài)如圖所示,那么在服務(wù)器執(zhí)行客戶端c10086發(fā)送的MONITOR命令之后,monitors鏈表將被更新為如圖所示的狀態(tài)
向監(jiān)視器發(fā)送命令信息
服務(wù)器在每次處理命令請求之前,都會調(diào)用replicationFeedMonitors函數(shù),由這個函數(shù)將被處理的命令請求的相關(guān)信息發(fā)送給各個監(jiān)視器。以下是replicationFeedMonitors函數(shù)的偽代碼定義,函數(shù)首先根據(jù)傳入的參數(shù)創(chuàng)建信息,然后將信息發(fā)送給所有監(jiān)視器:
def replicationFeedMOnitors(client, monitors, dbid,argv, argc): # 根據(jù)執(zhí)行命令的客戶端、當前數(shù)據(jù)庫的號碼、命令參數(shù)、命令參數(shù)個數(shù)等參數(shù) # 創(chuàng)建要發(fā)送給各個監(jiān)視器的信息 msg = create_message(client, dbid, argv, argc) # 遍歷所有監(jiān)視器 for monitor in monitors: # 將信息發(fā)送給監(jiān)視器 send_message(monitor, msg)
例子
舉個例子,假設(shè)服務(wù)器在時間1713791641.329412,根據(jù)IP為127.0.0.1、端口號為56604的客戶端發(fā)送的命令請求,對0號數(shù)據(jù)庫執(zhí)行命令KEYS*,那么服務(wù)器將創(chuàng)建以下信息:
1713791641.329412 [0 127.0.0.1:56604] "KEYS" "*"
如果服務(wù)器monitors鏈表的當前狀態(tài)如圖上如c10086執(zhí)行命令之后所示,那么服務(wù)器會分別將信息發(fā)送給c128、c256、c512和c10086四個監(jiān)視器,如圖所示
以上就是一文搞懂Redis中的慢查詢?nèi)罩竞捅O(jiān)視器的詳細內(nèi)容,更多關(guān)于Redis慢查詢?nèi)罩竞捅O(jiān)視器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Linux服務(wù)器快速安裝Redis6.0步驟示例詳解
這篇文章主要為大家介紹了Linux服務(wù)器快速安裝Redis6.0步驟示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12Linux系統(tǒng)下安裝Redis數(shù)據(jù)庫過程
大家好,本篇文章主要講的是Linux系統(tǒng)下安裝Redis數(shù)據(jù)庫過程,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12Redis實現(xiàn)分布式鎖(setnx、getset、incr)以及如何處理超時情況
本文主要介紹了Redis實現(xiàn)分布式鎖(setnx、getset、incr)以及如何處理超時情況,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11