python學習筆記4-redis multi watch實現鎖庫存


  python 關於redis的基本操作網上已經很多了,這里主要介紹點個人覺得有意思的內容1.redis的事務操作以及watch 樂觀鎖;后面描述2.tornado下異步使用redis的方式
     
  redis是單進程單線程模型,本身應對外部請求的是單任務的,也是多線程安全的,這個大家都應該知道的, 所以才會經常有人用redis做計數服務。
     
  首先redis 的事務處理只能使用pipeline:In redis-py MULTI and EXEC can only be used through a Pipeline object.
   
  很多人喜歡在處理電商庫存,例如秒殺活動的時候用redis做計數器,不過下面這段代碼采用了事務來控制庫存,是不是有點問題呢?
if __name__ == "__main__":
    with sms_redis.pipeline() as pipe:
        while 1:
            try:
                # 事務開始
                pipe.multi()
                count = int(sms_redis.get('stock_count'))
                if count > 0:  # 有庫存
                    pipe.set('stock_count', count - 1)
                # 事務結束
                pipe.execute()
                # 把命令推送過去
                break
            except Exception:
                traceback.print_exc()
                continue
  問題在於誤以為pipe.multi() 事務處理執行后,就可以鎖住該庫存,這里強調下:
redis 本身沒有悲觀鎖的概念,也就是說對於客戶的是無法鎖住redis中的值的,當然你可以通過其它曲徑實現,比如SETNX, 這里先不談;
redis 的事務可以認為是一段命令的批量執行和執行結果一次性返還,事務操作本身沒有問題,執行過程不會中斷,但是在pipe.execute() 的時候事務才真正向redis_server 提交,但是很遺憾在redis_server 執行之前庫存都有機會被其它客戶端修改,完全起不到鎖庫存概念
 
  那么如何才能實現鎖庫存呢?watch是一個很好的解決方案:
   watch 字面就是監視的意思,這里可以看做為數據庫中樂觀鎖的概念,誰都可以讀,誰都可以修改,但是修改的人必須保證自己watch的數據沒有被別人修改過,否則就修改失敗了;
 
if __name__ == "__main__":
    with sms_redis.pipeline() as pipe:
        while 1:
            try:
                #關注一個key
                pipe.watch('stock_count’)
                count = int(pipe.get('stock_count'))
                if count > 0:  # 有庫存
                    # 事務開始
                    pipe.multi()
                    pipe.set('stock_count', count - 1)
                    # 事務結束
                    pipe.execute()
                    # 把命令推送過去
                break
            except Exception:
                traceback.print_exc()
                continue
  如果在watch后值被修改,在執行pipe.execute()的時候會報異常WatchError: Watched variable changed.
這里可以簡單的實現基於redis中的鎖庫存的邏輯。
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM