關於windows下redis頻繁get 和set相同值遇到的問題

    最近一段時間事情比較多,沒有更新《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


    

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