解决python-redis-lock分布式锁的问题
作者:Loganer 发布时间:2023-05-23 18:57:49
python-redis-lock
官方文档
不错的博文可参考
问题背景
在使用celery执行我们的异步任务时,为了提高效率,celery可以开启多个进程来启动对应的worker。
但是会出现这么一种情况:在获取到数据源之后要对数据库进行扫描,根据UUID来断定是插入还是更新,两个worker 同时 (相差0.001S)拿到了UUID但是在其中一个没插入时,另一个也扫描完了数据库,这时这两个worker都会认为自己拿到的UUID是在数据库中没有存在过的,所以都会调用INSERT方法来进行插入操作。
几种解决方案
为了解决这个问题,一般有如下解决方案.
分布式锁家族:
数据库:
排它锁(悲观锁)
乐观锁
Redis
自己实现Redis SET SETNX 操作,结合Lua脚本确保原子操作
RedLock Redis里分布式锁实现的算法,争议比较大,谨慎使用
python-redis-lock 本文将要介绍的技术。这个库提供的分布式锁很灵活,是否需要超时?是否需要自动刷新?是否要阻塞?都是可选的。没有最好的算法,只有最合适的算法,开发人员应该根据实际需求场景谨慎选择具体用哪一种技术去实现。
设计思路:
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.
来源:https://blog.csdn.net/wyh1618/article/details/120973410
猜你喜欢
- 在使用操作XML文件时,我们可以使用Load方法直接加载xml文件即可,在ie和ff下通用。但是是XML字符串,则在两种浏览器下就会有所不同
- 1、合并列表(extend)跟元组一样,用加号(+)将两个列表加起来即可实现合并:In [1]: x=list(range(1, 13, 2
- Python常用的数据结构,有如下几种。但是我们用的最多的,还是字符串、列表、字典这3种。其实学习任何一门编程语言,最基础的就是学习它的数据
- Python内置函数isdigit()使用今天简单介绍一下Python中的isdigit()函数的用法:判断单个字符是否为数字判断字符串中是
- 是建立一个数据集 前面应该先定义此数据集 dim rs as adodb.recordset 然后就可以用 set rs=server.Cr
- 推荐阅读:使用python检测主机存活端口及检查存活主机下面给大家分享使用python语言实现获取主机名根据端口杀死进程代码。ip=os.p
- Python个人博客程序开发实例框架设计中,我们已经完成了 数据库设计、数据准备、模板架构、表单设计、视图函数设计、电子邮件支持 等总体设计
- 问题:数据库实际大小为600MB, 日志文件实际大小为33MB, 但日志文件占用空间为2.8GB!试了多种方式,SHIRNK DATABAS
- python可以返回多个值,确实挺方便函数里的return只能返回一个值,但是返回类型是没是限制的因此,我们可以“返回一个 tuple类型,
- 本文实例为大家分享了python实现定时发送邮件的具体代码,供大家参考,具体内容如下一、发送邮件import smtplib from em
- 一、简介我们在这里采用Python中的matplotlib来实现曲线图形的绘制。matplotlib是著名的python绘图库,它提供了一整
- Elasticsearch简介Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene&
- 我们在做诸如人群密集度等可视化的时候,可能会考虑使用热力图,在Python中能很方便地绘制热力图。下面以识别图片中的行人,并绘制热力图为例进
- python判断图片主色调,单个颜色:#!/usr/bin/env python# -*- coding: utf-8 -*-import
- // 执行AJAX请求的通用函数//带一个参数,是包含一系列选项的对象function ajax(options){//如果用户没有提供某个
- 在web开发中常常要使用js,为了提高效率一般都会制作js的类文件。这样在使用中更新复用都很方便。下面按照我工作中的一个案例,介绍如何定义j
- Python pip安装lxml出错的问题解决办法1. 在使用pip安装lxml过程中出现了一下错误: &
- Python是一门非常适合处理数据和自动化完成重复性工作的编程语言,我们在用数据训练机器学习模型之前,通常都需要对数据进行预处理,而Pyth
- 我要实现的就是下图的这种样式,可参考下面这两个网站的留言板,他们的实现原理都是一样的畅言留言板样式:网易跟帖样式:原理需要在评论表添加两个主
- <style> *{position:absolute;} #panel *{border:1px so