需求
我在最近的一個任務中,存在一個redis高并發計算多個客戶端接收預警信息的時長問題。
模型是首先模擬多個客戶端連接預警服務器集群,然后向預警服務集群發送告警信息。隨后預警服務集群將會向客戶端推送告警信息。
此時,我記錄了發送告警至預警集群的時間,并且在客戶端還會記錄接收到告警的時間。
我將這個時間都會記錄到redis中,那么此時就會有一個問題,當多個客戶端搶占式往redis 讀取數據,計算,設置數據,這個過程是會被相互覆蓋的。
可以從上面的截圖來看,多個不同的客戶端讀取redis的數據,大部分讀取到了同一個數據,導致計算錯誤。
導致問題的示意圖如下:
為了解決這個問題,則可以編寫一個redis的鎖,用來控制數據的并發讀取以及寫入。
在python redis庫默認只有樂觀鎖的一種寫法,在這里我再推薦使用一個庫python-redis-lock,使用這個庫對redis多個客戶端并發的情況加鎖,真的很方便。
下面來看看怎么使用。
python-redis-lock
https://pypi.org/project/python-redis-lock/
在使用這個庫之前,需要安裝如下:
pip install python-redis-lock
使用鎖的示例:
lock = redis_lock.Lock(conn, "name-of-the-lock") if lock.acquire(blocking=False): print("Got the lock.") lock.release() else: print("Someone else has the lock.")
上面是單獨設置鎖的方式,還可以單獨設置所有redis的操作加入鎖。
# On application start/restart import redis_lock redis_lock.reset_all(redis_client)
修改業務代碼,增加lock操作
1. 首先導入redis_lock
import redis_lock
2.將redis連接的客戶端傳入lock中,并設置lock的名稱
# 設置redis連接 self.conn = redis.Redis(host='127.0.0.1', port=6379, decode_responses=True, db=3) # 設置redis鎖 self.lock = redis_lock.Lock(self.conn, "redis-lock")
3.將業務讀取、設置redis的部分加入鎖
while True: # 設置redis鎖,操作redis if self.lock.acquire(blocking=False): print("Got the lock.") # 獲取lock,執行業務處理 # 獲取當前redis鐘記錄的客戶端接收到告警的總時長 recv_time_sum_count_clients = self.conn.get(recv_time_sum_count_clients_key) if recv_time_sum_count_clients is None: recv_time_sum_count_clients = "0:0" # 獲取當前的統計數據 recv_time_sum, count_clients = recv_time_sum_count_clients.split(":") # 計算告警接收總時長 recv_time_sum = float(recv_time_sum) + recv_time # 計算收到預警的客戶端數量 count_clients = int(count_clients) + 1 # 寫入redis中 recv_time_sum_count_clients = "%s:%s" % (str(recv_time_sum), str(count_clients)) self.conn.set(recv_time_sum_count_clients_key, recv_time_sum_count_clients) print("user_id = %s, 計算平均時間成功, " "recv_time_sum = %s, count_clients = %s \n" % (self.user_id, recv_time_sum, count_clients)) # 釋放lock self.lock.release() # 退出循環 break else: print("Someone else has the lock.")
在客戶端的代碼中設置了鎖之后,再來執行一下,看看有無搶占讀取redis數據的情況,如下:
設置了鎖之后,客戶端由于并發導致redis數據讀取、設置錯誤的情況就可以避免了。
并且這個庫還可以使用到Django框架中,更多細節讀者可以到該庫Github中細細查閱,本篇章就不介紹了,哈哈。
到此這篇關于python3使用python-redis-lock解決并發計算問題的文章就介紹到這了,更多相關python-redis-lock 并發內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/u012887259/article/details/103870425