时间: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.