redis學習筆記之常用技巧

1.慢查詢分析:

客戶端命令的生命週期:

慢查詢只統計第3步的耗時,無慢查詢不代表客戶端不存在超時問題,如網絡帶寬問題

與慢查詢相關的配置:

a.slowlog-log-slower-than:預設閥值,單位爲微秒,默認10000,執行時間超過該值的命令會被記錄到慢查詢日誌(PS:設爲0會記錄所有命令,<0則不記錄任何命令)

b.slowlog-max-len:設置慢查詢日誌最多存儲多少條,超過該值則最早的一條慢查詢日誌將會被移出列表(可定期執行slowlog get將慢查詢持久化到其他存儲中)

修改慢查詢配置的2種方法:

1.修改配置文件

2.使用config set命令動態修改(若不能使用,看版本是否太低不支持)

對慢查詢日誌的操作:

a.獲取n條日誌:slowlog get n

b.獲取慢查詢日誌當前長度:slowlog len

c.重置慢查詢日誌:slowlog reset

慢查詢日誌=id+時間戳+命令耗時+命令+參數

2.pipeline機制:

pipeline可以將一組redis命令進行封裝,通過一次RTT(往返時間)傳輸給redis,再將這組redis命令的執行結果按順序返回給客戶端,但是pipeline不保證該組命令執行時候的原子性且一次性傳輸的數據量最好不要太多

                           沒有pipeline執行n次命令                                                                                                                     pipeline執行n次命令

                                                                

測試服務器的redis-3.2.10,測試常用的redis命令執行10000次,測試數據100字節,使用pipeline與不使用pipeline的耗時(ms),測試結果如下表:

 

 
使用pipeline
不使用pipeline
set18772711
hset19962369
sadd21369048
lpush23769688
zadd21672587

原生批量命令與pipeline對比:

a.前者是原子性操作,而後者不是

b.前者是一個命令對應多個key,而後者可以支持多個命令

c.前者是redis服務端支持實現的,而後者需要redis客戶端與服務端共同支持實現

3.bitmap:

bitmaps實際上就是字符串,只是它可以對字符串的位進行操作,可以將其看作是以位爲單位的數組,數組每個單元只能存儲0和1

bitmaps相關命令:

a.設置鍵第offset位的值: setbit key offset value(0 or 1)

b.獲取鍵第offset位的值: getbit key offset(return 0 or 1),不存在的位返回0

c.獲取鍵指定範圍值爲1的個數: bitcount key [start] [end]

d.多個鍵之間的運算保存結果到destkey: bitop op destkey key[key...](op=or/end/not/xor)

e.計算鍵第一個值爲target的偏移量: bitpos key target [start] [end]

bitmaps的用處:

a.網站流量統計分析:

以日期爲key,用戶id(id爲整型數字)爲bitmap的下標,若用戶登陸則對其下標值設爲1,通過多個key之間的運算(or/and/not/xor)可實現不同的統計,對於大訪問量的網站統計可節省很多內存

測試:使用bitmap方式存儲與使用set存儲用戶id來實現登陸流量統計,100w用戶,bitmap佔用內存大約200k,而使用set存儲id則佔用約60M內存

b.做黑名單限制(如:ip、手機號碼等):將ip、手機號碼等hash或使用其他算法計算出一個下標,將其下標對應的值記爲1,之後使用getbit取得對應下標判斷是否爲1即可

4.對客戶端進行監控與管理:

A.client list命令:可以列出與redis服務端相連的所有客戶端連接信息

連接信息包含如下屬性:

輸入緩衝區:

每一個redis客戶端都有一個輸入緩衝區,用於臨時保存客戶端發送的命令,同時redis會從輸入緩衝區拉去命令並執行,大小不能超過1G且不受maxmemory參數控制,超過則關閉客戶端,輸入緩衝區過大則需要留意是否發生阻塞

造成redis輸入緩衝區過大的主要原因:

a.Redis處理速度跟不上輸入緩衝區的輸入速度且每次進入緩衝區的命令包含大量bigkey

b.redis發生阻塞,不能處理命令,命令積壓在輸入緩衝區

如何監控:

a.定期執行client list命令查看qbuf與qbuf-free並分析,找出問題客戶端

b.執行info clients找出最大輸入緩衝區

兩種方式優劣對比:

命令
優點
缺點
client list能精準分析每個客戶端來定位問題相比於info client執行速度比較慢(尤其是在連接數很多的情況下),頻繁執行存在阻塞redis的可能
info clients執行速度比client list快,但分析過程較爲簡單,只是一個統計數據不能精確定位到客戶端;不能顯示所有輸入緩衝區的總量,只能顯示最大量

輸出緩衝區:

Redis每一個客戶端配置了一個輸出緩衝區,用於保存命令執行的結果返回給客戶端,並且輸出緩衝區分爲3種:普通客戶端、發佈訂閱客戶端、slave客戶端,不受maxmemory控制,可通過client-output-buffer-limit進行配置

輸出緩衝區的配置(redis.conf文件):

client-output-buffer-limit <class> <hard-limit> <soft-limit> <soft-seconds>

參數說明:

class:客戶端類型,normal(普通客戶端)、slave(slave客戶端)、pubsub(發佈訂閱客戶端)

hard-limit:若輸出緩衝區大於該值,客戶端立即關閉

soft-limit和soft seconds:若客戶端輸出緩衝區超過soft-limit並持續soft-seconds秒,客戶端立即關閉

輸出緩衝區=固定緩衝區(16k)+動態緩衝區

固定緩衝區返回較小結果,動態緩衝區返回較大結果,且固定緩衝區使用的是字節數組,動態緩衝區使用的是列表,固定緩衝區用盡則使用動態緩衝區

監控輸出緩衝區:

a.定期執行client list命令查看obl、oll、omem並分析,找出問題客戶端

b.執行info clients命令,找出輸出緩衝區列表最大對象數(client_longest_output_list)

預防輸出緩衝區異常:

a.監控並設置閥值,超過閥值則處理

b.限制普通客戶端輸出的緩衝區

c.適當增大slave端的輸出緩衝區

d.限制容易讓輸出緩衝區增大的命令,如monitor、keys等命令

B.對客戶端進行限制:

maxclients:用於限制最大客戶端連接數,一旦超過該值,新的連接將被拒絕,默認爲10000,可通過info client的connected_clients查看當前連接數,亦可以通過config set maxclients動態設置最大連接數timeout:用於限制連接最大的空閒時間,一旦超過該時間,連接將關閉,客戶端拋出JedisConnectionException,默認爲0,不會出現連接異常,可以通過config set maxclients動態設置

tcp-keepalive:檢測TCP連接活性的週期,默認爲0,即不進行檢測,若需設置,建議爲60,可防止大量死連接佔用系統資源

tcp-backlog:TCP三次握手後,會將接受的連接放入隊列,該值就是隊列的大小,默認爲511,一般無需調整

C.對客戶端的操作:

client getName:獲取客戶端名稱

client setName XXX:爲客戶端設置名稱

client kill ip:port:殺掉指定ip地址與端口的客戶端

client pause timeout(ms):阻塞客戶端timeout毫秒(ps:該命令只對普通客戶端與發佈訂閱客戶端有效,對主從複製的節點是無效的)

monitor:監控其他客戶端正在執行的命令,併發量大的話,執行該命令的客戶端內存會暴漲,建議禁用or屏蔽

D.客戶端片段的統計:

info clients命令:

a.connected_clients:代表當前redis節點的客戶端連接數,需重點監控,一旦超過maxclients,新的客戶端連接將被拒絕

b.client_longest_output_list:當前所有輸入緩衝區中隊列對象個數的最大值

c.client_biggest_input_buf:當前所有輸入緩衝區中佔用的最大容量

d.blocked_clients:正在執行阻塞命令的客戶端個數

info stats命令:

a.Total_connections_received:redis自啓動以來處理的客戶端連接數總數

b.rejected_connections:redis自啓動以來拒絕的客戶端連接數,需重點監控

5.客戶端常見異常:

A.無法從連接池獲取到連接:jedisPool中的jedis對象默認是8個,若全部被佔用沒有歸還,再次使用則需要等待,若在maxWaitMillis時間內仍無法獲取帶jedis對象則拋JedisConnectionException異常(Timeout waiting for idle object)或者設置了blockWhenExhausted=false,則發現連接池中沒有資源時拋異常不進行等待(Pool exhausted)

原因如下:

a.客戶端高併發下連接池設置過小,供不應求

b.客戶端沒有正確使用連接池,連接獲取後沒釋放

c.客戶端存在慢查詢操作,釋放連接比較慢

d.服務端原因,命令阻塞等

B.客戶端讀寫超時:讀寫超時會拋JedisConnectionException異常(Read timed out)

原因如下:

a.讀寫超時間設置過短

b.命令本身就比較慢

c.客戶端與服務端網絡不正常

d.Redis自身發生阻塞

C.客戶端連接超時:連接超時會拋JedisConnectionException(connect timed out)異常

原因如下:

a.連接超時設置過短(connectionTimeout)

b.Redis發生阻塞,造成tcp-backlog已滿

c.客戶端與服務端網絡不正常

D.客戶端緩衝區異常:客戶端數據流異常,會拋JedisConnectionException異常(Unexpected end of... )

原因如下:

a.輸出緩衝區已滿

b.長時間閒置連接被服務器主動斷開

c.不正常的併發讀寫,jedis對象同時被多個線程併發操作,可能出現該異常

E.lua腳本正在運行:若redis當前正在執行lua腳本並超過lua-time-limit,此時jedis調用redis會拋JedisDataException異常(BUSY Redis is busy running a script......)

F.redis正在加載持久化文件:Jedis調用redis時,若redis正在加載持久化文件,則拋JedisDataException異常(LOADING Redis is loading the dataset in memory)

G.redis使用的內存超過maxmemory配置:超過maxmemory配置,則拋JedisDataException異常(OOM command not allowed when used memory>’maxmemory’)

H.客戶端連接數過大:客戶端連接數超過maxclients,新申請連接則拋JedisDataException異常(ERR max number of client reached)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章