redis 事務(wù),redis實(shí)現(xiàn)秒殺,悲觀鎖秒殺,樂觀鎖秒殺

事務(wù)

  • 操作

    # ex,過期時(shí)間(秒)
    # px,過期時(shí)間(毫秒)
    # nx,如果設(shè)置為True,則只有name不存在時(shí),當(dāng)前set操作才執(zhí)行
    # xx,如果設(shè)置為True,則只有name存在時(shí),當(dāng)前set操作才執(zhí)行
    redis_client.set('name', 'zs', ex=10)
    
    
  1. 事務(wù):

    1. 語法:

      MULTI (multi):開啟事務(wù),后續(xù)的命令會(huì)被加入同一個(gè)事務(wù)中。 事務(wù)中的操作會(huì)發(fā)送給服務(wù)端,但是不會(huì)立即執(zhí)行, 而是放到了該事務(wù)的對(duì)應(yīng)的一個(gè)隊(duì)列中,服務(wù)端返回QUEUED

      EXEC (exec):python文件引用中是execute,執(zhí)行EXEC后,事務(wù)中的命令才會(huì)被執(zhí)行,事務(wù)中的命令出現(xiàn)錯(cuò)誤時(shí),不會(huì)回滾也不會(huì)停止事務(wù), 而是繼續(xù)執(zhí)行。

      DISCARD(discard):取消事務(wù),事務(wù)隊(duì)列會(huì)清空,客戶端退出事務(wù)狀態(tài)

    2. ACID:

      原子性:不支持。不會(huì)回滾并且繼續(xù)執(zhí)行

      隔離性:支持。事務(wù)中命令順序執(zhí)行,并且不會(huì)被其他客戶端打斷(先EXEC的先執(zhí)行)。單機(jī)redis讀寫操作使用 單進(jìn)程單線程

      持久性:不支持,因?yàn)閞edis數(shù)據(jù)容易丟失

      一致性:不支持。 強(qiáng)一致性要求,可以通過樂觀鎖(watch)來實(shí)現(xiàn)

    3. WATCH:

      • redis機(jī)制的樂觀鎖
      • 機(jī)制:事務(wù)開啟前,設(shè)置對(duì)數(shù)的監(jiān)聽,EXEC時(shí),如果發(fā)現(xiàn)數(shù)據(jù)發(fā)生過修改,事務(wù)會(huì)自動(dòng)取消(DISCARD)。事務(wù)EXEC后,無論成敗,監(jiān)聽會(huì)被移除。
    4. setnx和悲觀鎖

      • setnx鍵不存在,才會(huì)設(shè)置成功
    5. 非事務(wù)性管道

      • redis實(shí)現(xiàn)了管道機(jī)制,可以將多個(gè)操作打包發(fā)給redis服務(wù)器
      • 可以單獨(dú)使用管道,不需要開啟事務(wù) 對(duì)于沒有事務(wù)要求的多個(gè)操作,可以直接使用非事務(wù)性管道進(jìn)行處理,減少事務(wù)產(chǎn)生的性能消耗。
      • 創(chuàng)建非事務(wù)性管道,通過transaction=False參數(shù)設(shè)置

redis樂觀鎖實(shí)現(xiàn)秒殺超賣需求

from redis import StrictRedis, WatchError
# 創(chuàng)建redis連接
# decode_responses = True 是指定數(shù)據(jù)是字符串的格式,host是連接地址,port是連接端口,db是連接的數(shù)據(jù)庫。
redis_client = StrictRedis(host='127.0.0.1', port=6379, db=0, decode_responses=True)

# 1. 創(chuàng)建管道 默認(rèn)會(huì)開啟事務(wù)
pipeline = redis_client.pipeline()
while True:
    try:
        # 2. 設(shè)置數(shù)據(jù)的監(jiān)聽  一旦設(shè)置了監(jiān)聽 就不會(huì)自動(dòng)開啟事務(wù)  后續(xù)操作都會(huì)變成立即執(zhí)行
        pipeline.watch('count')
        # 3. 獲取數(shù)據(jù)  可以立即得到結(jié)果
        count = pipeline.get('count')
        # 判斷庫存滿足,滿足減少庫存并生成訂單
        if int(count) > 0:
            # 4. 手動(dòng)開啟事務(wù) 開啟后 后續(xù)的操作會(huì)加入到事務(wù)中
            pipeline.multi()
            # 減少庫存
            pipeline.decr('count')
            # 提交事務(wù) 如果監(jiān)聽的數(shù)據(jù)中途被修改,會(huì)拋出WatchErrou錯(cuò)誤,可以捕獲異常,
            pipeline.execute()       # 無論成功失敗, 監(jiān)聽都會(huì)移除
            print('生成訂單')
        else:
            # 沒有庫存,手動(dòng)移除監(jiān)聽
            pipeline.reset()
            print("已售罄")
        break
    except WatchError as e:
        # 監(jiān)聽的數(shù)據(jù)被修改,重試。
        print("重試")
        continue
   # 在redis 終端設(shè)計(jì)一個(gè)庫存數(shù)據(jù)
在redis 終端設(shè)計(jì)一個(gè)庫存數(shù)據(jù)
1562764435772.png

redis悲觀鎖實(shí)現(xiàn)秒殺超賣需求

from redis import StrictRedis
# 創(chuàng)建redis連接
# decode_responses = True 是指定數(shù)據(jù)是字符串的格式,host是連接地址,port是連接端口,db是連接的數(shù)據(jù)庫。
redis_client = StrictRedis(decode_responses=True)

while True:
    # 設(shè)置個(gè)字段 a 并且等于1  setnx 鍵不存在,才會(huì)設(shè)置成功
    order_lock = redis_client.setnx('a', 1)
    if order_lock:
        reserver_count = redis_client.get('count')
        if int(reserver_count) > 0:
            redis_client.decr('count')
            print('生成訂單')
        else:
            print('已售罄')
        # 完成處理,移除鎖
        redis_client.delete('a')
        break

非事務(wù)管道

from redis import StrictRedis
redis_client = StrictRedis(decode_responses=True)
# 創(chuàng)建非事務(wù)型管道 通過teansaction = False 設(shè)置
pipeline = redis_client.pipeline(transaction = False)
# 這些操作不會(huì)添加到事務(wù)中
a = pipeline.set('name','zs')
# 只是將管道中的操作一起發(fā)送給redis服務(wù)器, 不會(huì)進(jìn)行watch遍歷和檢查
c = pip.execute()
print(a)
print(c)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • MULTI、EXEC、DISCARD和WATCH命令是Redis事務(wù)功能的基礎(chǔ)。Redis事務(wù)允許在一次單獨(dú)的步驟...
    金星show閱讀 577評(píng)論 0 0
  • 原文來源Redis的事務(wù)功能詳解MULTI、EXEC、DISCARD和WATCH命令是Redis事務(wù)功能的基礎(chǔ)。R...
    白紙糊閱讀 1,856評(píng)論 1 0
  • 五種數(shù)據(jù)結(jié)構(gòu)簡介 Redis是使用C編寫的,內(nèi)部實(shí)現(xiàn)了一個(gè)struct結(jié)構(gòu)體redisObject對(duì)象,通過結(jié)構(gòu)體...
    彥幀閱讀 7,153評(píng)論 0 14
  • 基于內(nèi)存的NoSQL數(shù)據(jù)庫。提供五種數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)。字符串、列表、集合、有序集合、散列表。Redis 支持很多特性...
    韓絕交閱讀 811評(píng)論 0 1
  • redis事務(wù) Redis 通過 MULTI 、 DISCARD 、 EXEC 和 WATCH 四個(gè)命令來實(shí)現(xiàn)事務(wù)...
    全能程序猿閱讀 2,252評(píng)論 0 11

友情鏈接更多精彩內(nèi)容