1. 程式人生 > >redis audit記憶體分析工具在redis cluster中的應用

redis audit記憶體分析工具在redis cluster中的應用

內容:

redis audit工具是使用ruby語言編寫的指令碼,用來分析redis哪些key佔記憶體比較多,及佔用記憶體較多的key鍵的過期時間。在分析redis記憶體增長時非常有幫助。在分析時,為了防止對生產庫的影響,一般在從庫上執行。但是在使用redis audit分析redis cluster從庫例項時發現報錯不能使用。於是花了些時間分析原因並使之能夠使用redis cluster從庫例項。

背景:

有個redis叢集由於接入了新業務系統,導致redis cluster記憶體8個例項增加了64g記憶體。另外還在以每天8g的速度增加。


使用工具rubyredis audit

查詢哪些key佔記憶體比較多,發現這個工具還不能支援redis cluster環境。


抽查了幾個key的過期時間,發現都是千萬年的過期時間。下面這個key46千年。

127.0.0.1:6410> ttl "b7b9dd35-1149-41ab-94d5-14906a68ab50_1464403073675"

(integer) 1462986538098

聯絡該系統的外購廠商檢視,解釋說這些key是少數的配置資訊。其他記憶體是正常增長,要求擴容。

實在沒辦法了,只好將aof檔案拷貝到一個非叢集空例項上進行回放,再使用redis audit進行分析。

---------------------------------------------------+--------------+-------------------+---------------------------------------------------


Key                                                | Memory Usage | Expiry Proportion | Last Access Time                                  
---------------------------------------------------+--------------+-------------------+---------------------------------------------------
e005a0c4-
242a-4888-8418-ca3b46b7951a_3547790698057
 | 
3.38%        | 100.0%            | 0 seconds                                        
cbd4d269-
8081-498b:10100000003215023              | 2.55%        | 100.0%            | 3 seconds                                         
cbd4d269-
488b-4fba-8a71-7c5125cfe268_90e1865f11559 | 0.57%        | 100.0%            | 61 days, 13 hours, 3 minutes, 12 seconds         
e82192ea-
439b-4b18-ad79-1b03d440042b_0000000000000 | 0.36%        | 100.0%            | 0 seconds                                        
fff01f23-
881e-434d-8061-5229c2c67a0a_E12861F9-5418 | 0.28%        | 100.0%            | 61 days, 13 hours, 3 minutes, 13 seconds         
2c69edf4-844d-4b6d-80ad-aa26046d5b34_015c7b47c43c1 | 0.17%        | 100.0%            | 0 seconds                                       

==============================================================================

Found 8 keys containing strings, like:

[0;33m765b506e-9052-4002-b2e4-c2062e392da6_1464172442715, 74be1490-1501-4634-bfb1-9ea25b14ed9a_1464923898832, 27b4e195-0208-4434-9345-91a2f127c173_1464572544882, 32b18e20-0997-4c80-b335-f69ad857e86d_1464077619056, 2b5456e5-4948-4f7d-9a9f-2679b566a732_1464362686736, 3038b6e7-3929-4023-88ac-3eec1e198075_1462865085803, 71b10e08-8399-4572-a807-a2a59277a66f_1464250132607, 73b4706e-4016-4651-9755-06a44aa16a1a_1464751883853[0m

These keys use [0;1;4m0.08%[0m of the total sampled memory (16 bytes)

[0;1;4m100.0%[0m of these keys expire (8), with maximum ttl of 16938711 days, 9 hours, 33 minutes, 23 seconds

Average last accessed time: [0;1;4m0 seconds[0m - (Max: 0 seconds Min:0 seconds)

==============================================================================

Found 8 keys containing strings, like:

[0;33m47160e49-4421-44f1-a6aa-de40d00fa752_1464230697555, 752e6455-9511-4f71-9eff-5932d0b5c5d5_1461976447739, e0053117-4541-49f8-a998-da86ea0740f3_14641242393705948206e-1219-4f76-a877-a535b4bf8a53_14648874592614470937e-1641-4fd5-bba7-47ac21477536_1464716582874, 2595e912-8264-45f4-b109-ea06f843b4ef_146482509873963821e85-9080-497f-9438-adae16a551cd_1463280482719, 774e7379-8333-412f-a7fa-b5b0b0d7e44f_1464358656511[0m

These keys use [0;1;4m0.08%[0m of the total sampled memory (16 bytes)

[0;1;4m100.0%[0m of these keys expire (8), with maximum ttl of 16938711 days, 9 hours, 33 minutes, 14 seconds

Average last accessed time: [0;1;4m0 seconds[0m - (Max: 0 seconds Min:0 seconds)

通過分析發現幾乎所有的key都是萬年以上的過期時間。要求廠商再次排查,原來是將過期時間單位看錯了,多乘了幾個0

經過這次問題分析,發現分析過程比較麻煩,最好工具redis audit直接分析redis cluster。於是嘗試查詢下redis audit在redis cluster執行時出錯的原因。

根據前面在redis cluster下執行出錯的資訊進行debug redis audit指令碼,發現真實的報錯如下:


根據報錯資訊猜測是key被分片到其他節點。

redis 3.0的客戶端工具redis-cli有個選項-c 是用來連線redis cluster叢集的,但是rubyredis客戶端api沒有提供類似功能。在網上查找了ruby訪問redis cluster客戶端redis-rb-cluster (https://github.com/antirez/redis-rb-cluster)

修改了redis-audit程式碼使用rubyRedisCluster建立連線,執行後發現還是有同樣的報錯。

檢視redis-rb-cluster提供的案例example.rb:呼叫的是get介面和set,並能從cluster中成功的設定和獲取key


具體在redis-rb-cluster檔案cluster.rb中封裝的介面中,先是根據key獲取slot,然後根據slot在獲取可以所在的例項(也就是host和埠)。。


檢視slot函式,發現redis cluster使用的是CCITT standardsXMODEM CRC 16 algorithm。百度了下CCITTCCITT是國際電報電話諮詢委員會的簡稱,它是國際電信聯盟(ITU)的前身。Xmodem是在1978年由Ward Christensen建立的用於調變解調器糾錯的協議。


瞭解了redis cluster連線方法,就很容易解決redis-audit工具的問題,將原來的連線方式修改為先獲取randomkey,根據key找到對應的節點,並建立連線。


本來到這兒可以結束了,但是為了查詢下這些key最終都指向哪個例項了,將選擇的節點都打印出來,發現都是同一個節點:

192.168.0.5:6379

192.168.0.5:6379

192.168.0.5:6379

192.168.0.5:6379

192.168.0.5:6379

192.168.0.5:6379

而其slot都是在節點6379slot區間:8192-10239。這個節點192.168.0.5是發起查詢例項192.168.0.6的主庫節點。這裡解釋下,為了防止redis audit分析工具對生產庫的影響,規定redis audit只能對redis的從庫執行,這樣redis的主庫是不受影響的。

那麼為什麼在redis cluster叢集中在redis從例項上查詢資料,連線會被定向到redis主例項上呢?查了redis cluster官方文件http://redis.io/commands/readonly,發現如果需要查詢redis cluster的從例項資料,需要執行函式redis.readonly()。否則,redis cluster會自動將客戶端的連線重新定向到從庫對應的主庫。

通過近兩天的時間分析,瞭解了redis cluster的分片演算法,學習了ruby連線redisredis cluster的方法原理。並修改了redis audit工具,使之能夠適用redis cluster的架構。

下面是經過和其他同事討論規範後的redis audit修改程式碼:請見標黃部分:

[[email protected]]$ more redis-audit.rb

#!/usr/bin/ruby

….省略其他程式碼

host = ARGV[0]

port = ARGV[1].to_i

db = ARGV[2].to_i

sample_size = ARGV[3].to_i

password = ARGV[4]

redis = Redis.new(:host => host, :port => port, :password => password, :db => db)

begin

         redis.readonly()

rescue Exception => e

    puts "The redis instance is not a cluster member."

End

修改後redis audit可以支援在redis cluster從庫上進行分析了。

總結:

在使用redis audit分析redis cluster從庫例項時,需要修改指令碼redis-audit.rb,在連線redis時呼叫方法redis.readonly()方法,這個是redis cluster從庫例項特殊要求的。隨著redis cluster的廣泛使用,希望能夠對後續redis cluster從庫的記憶體問題分析有所幫助。