时间:2023-02-11 09:49:21 | 栏目:Python代码 | 点击:次
python-redis-lock
在使用celery执行我们的异步任务时,为了提高效率,celery可以开启多个进程来启动对应的worker。
但是会出现这么一种情况:在获取到数据源之后要对数据库进行扫描,根据UUID来断定是插入还是更新,两个worker 同时 (相差0.001S)拿到了UUID但是在其中一个没插入时,另一个也扫描完了数据库,这时这两个worker都会认为自己拿到的UUID是在数据库中没有存在过的,所以都会调用INSERT方法来进行插入操作。
为了解决这个问题,一般有如下解决方案.
分布式锁家族:
数据库:
Redis
设计思路:
Zookeeper
这个应该是功能最强大的,比较专业,稳定性好。我还没使用过,日后玩明白了再写篇文章总结一下。
在celery的场景下也可以使用celery_once进行任务去重操作, celery_once底层也是使用redis进行实现的。
可以参考这篇
Talk is cheap, show me your code!
一个简单的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.