最近一段時間事情比較多,沒有更新《redis讀寫分離下的高可用設計與實現》的實現部分,除了之前的實現沒有達到高可用的原因外,還有一個重要的原因,我接手的另一個項目中redis頻繁get和set相同的值時,出現了不一致的情況,這讓我對手頭上的程序懷疑了很長一段時間,從1月中旬,到現在,大約一個多朋的時間,被這個windows下的redis折騰得不輕,下面把處理問題和方法和大家分享下,僅供參考。
先說一下場景,程序的功能是作業的調度中心,需要實時監控新的作業處理模塊的在線情況,於是利用redis做數據的存儲,每個新增加的結點,把自己的id添加到redis中,超時時間爲1.5秒,每一秒鐘上報一次心跳。程序運行一段時間,短則幾分鐘,長則幾個小時,會出現結點的丟失問題,查找問題的方法如下:
第一,所有的redis訪問加鎖,防止由於使用的類庫沒有處理好線程安全的問題。
第二,加鎖後仍然發現結點丟失的問題,查閱API說明文檔,問題可能出現在發佈和訂閱上,決定停止發佈訂閱功能。
第三,此時仍然不行,猜測可能是自己程序多線程沒有處理好,把程序改爲單線程運行,單個線程運行沒有問題。
第四,既然單線程沒有問題,那嘗試多個單線程的程序同時運行,讓每個程序模擬一個結點上報自己的數據,每個程序中應該都能得到所有結點的拓撲信息,但運行一段時間後也會出現丟失的問題,但在同一秒內,有的程序中報了結點的丟失,有的沒有報,初步判斷可能是由於set 和get之間時間差的問題。
第五,換linux下的redis用第四步中的相同程序運行,結果沒有發現問題。
結論:windows下的redis並沒有linux下的性能好,開發的時候儘可能使用linux版本的redis,畢竟上線的時候是linux,redis官方也只給出了linux的版本,沒必要爲平臺導致的redis差異花太多時間!
其中一個結點的實現如下,複製8份下面的文件,只需要修改node1爲node2,node3....node8,同時運行,則可以觀察到上面說到的丟失的問題。
#!/usr/bin/env python #coding=utf-8 import redis import time import random if __name__ == "__main__": rc = redis.Redis(host='127.0.0.1',port=6379,db=1,password='') node1 = "node:m1" node2 = "node:m2" node3 = "node:m3" node4 = "node:m4" node5 = "node:m5" node6 = "node:m6" node7 = "node:m7" node8 = "node:m8" TAG_NODE = "node:m*" print "start...", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) time.sleep(2) while True: try: rc.set(node1, 1, 0, 1500) rcds = rc.keys(TAG_NODE) if len(rcds) != 8: tmp_time = time.time() print 'error rcds len =' ,len(rcds), rcds ,tmp_time ,time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(tmp_time)) ext_node = rc.exists(node1) if not ext_node: print "cannot find node1 ", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) ext_node = rc.exists(node2) if not ext_node: print "cannot find node2 ", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) ext_node = rc.exists(node3) if not ext_node: print "cannot find node3 ", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) ext_node = rc.exists(node4) if not ext_node: print "cannot find node4 ", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) ext_node = rc.exists(node6) if not ext_node: print "cannot find node6 ", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) ext_node = rc.exists(node6) if not ext_node: print "cannot find node6 ", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) ext_node = rc.exists(node7) if not ext_node: print "cannot find node7 ", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) ext_node = rc.exists(node8) if not ext_node: print "cannot find node8 ", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) time.sleep(1) #time.sleep(random.random()) except Exception , e: print 'Exception===',e