溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

怎么解決python-redis-lock分布式鎖的問(wèn)題

發(fā)布時(shí)間:2021-11-01 09:11:22 來(lái)源:億速云 閱讀:169 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容介紹了“怎么解決python-redis-lock分布式鎖的問(wèn)題”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

問(wèn)題背景

在使用celery執(zhí)行我們的異步任務(wù)時(shí),為了提高效率,celery可以開(kāi)啟多個(gè)進(jìn)程來(lái)啟動(dòng)對(duì)應(yīng)的worker。
但是會(huì)出現(xiàn)這么一種情況:在獲取到數(shù)據(jù)源之后要對(duì)數(shù)據(jù)庫(kù)進(jìn)行掃描,根據(jù)UUID來(lái)斷定是插入還是更新,兩個(gè)worker 同時(shí) (相差0.001S)拿到了UUID但是在其中一個(gè)沒(méi)插入時(shí),另一個(gè)也掃描完了數(shù)據(jù)庫(kù),這時(shí)這兩個(gè)worker都會(huì)認(rèn)為自己拿到的UUID是在數(shù)據(jù)庫(kù)中沒(méi)有存在過(guò)的,所以都會(huì)調(diào)用INSERT方法來(lái)進(jìn)行插入操作。

幾種解決方案

為了解決這個(gè)問(wèn)題,一般有如下解決方案.
分布式鎖家族:

數(shù)據(jù)庫(kù):

  • 排它鎖(悲觀鎖)

  • 樂(lè)觀鎖

Redis

  1. 自己實(shí)現(xiàn)Redis SET SETNX 操作,結(jié)合Lua腳本確保原子操作

  2. RedLock Redis里分布式鎖實(shí)現(xiàn)的算法,爭(zhēng)議比較大,謹(jǐn)慎使用

  3. python-redis-lock 本文將要介紹的技術(shù)。這個(gè)庫(kù)提供的分布式鎖很靈活,是否需要超時(shí)?是否需要自動(dòng)刷新?是否要阻塞?都是可選的。沒(méi)有最好的算法,只有最合適的算法,開(kāi)發(fā)人員應(yīng)該根據(jù)實(shí)際需求場(chǎng)景謹(jǐn)慎選擇具體用哪一種技術(shù)去實(shí)現(xiàn)。

Zookeeper
這個(gè)應(yīng)該是功能最強(qiáng)大的,比較專(zhuān)業(yè),穩(wěn)定性好。我還沒(méi)使用過(guò),日后玩明白了再寫(xiě)篇文章總結(jié)一下。

擴(kuò)展思路

在celery的場(chǎng)景下也可以使用celery_once進(jìn)行任務(wù)去重操作, celery_once底層也是使用redis進(jìn)行實(shí)現(xiàn)的。
可以參考這篇

Talk is cheap, show me your code!

一個(gè)簡(jiǎn)單的demo

import random
import time
import threading
import redis_lock
import redis

HOST = 'YOUR IP LOCATE'
PORT = '6379'
PASSWORD = 'password'


def get_redis():
    pool = redis.ConnectionPool(host=HOST, port=PORT, password=PASSWORD, decode_responses=True, db=2)
    r = redis.Redis(connection_pool=pool)
    return r


def ask_lock(uuid):
    lock = redis_lock.Lock(get_redis(), uuid)
    if lock.acquire(blocking=False):
        print(" %s Got the lock." % uuid)
        time.sleep(5)
        lock.release()
        print(" %s Release the lock." % uuid)
    else:
        print(" %s Someone else has the lock." % uuid)


def simulate():
   for i in range(10):
        id = random.randint(0, 5)
        t = threading.Thread(target=ask_lock, args=(str(id)))
        t.start()


simulate()

Output:

 4 Got the lock.
 5 Got the lock.
 3 Got the lock.
 5 Someone else has the lock.
 5 Someone else has the lock.
 2 Got the lock.
 5 Someone else has the lock.
 4 Someone else has the lock.
 3 Someone else has the lock.
 3 Someone else has the lock.
 2 Release the lock.
 5 Release the lock.
 4 Release the lock.
 3 Release the lock.

“怎么解決python-redis-lock分布式鎖的問(wèn)題”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI