解决python-redis-lock分布式锁的问题

python-redis-lock

官方文档
不错的博文可参考

问题背景

在使用celery执行我们的异步任务时,为了提高效率,celery可以开启多个进程来启动对应的worker。
但是会出现这么一种情况:在获取到数据源之后要对数据库进行扫描,根据UUID来断定是插入还是更新,两个worker 同时 (相差0.001S)拿到了UUID但是在其中一个没插入时,另一个也扫描完了数据库,这时这两个worker都会认为自己拿到的UUID是在数据库中没有存在过的,所以都会调用INSERT方法来进行插入操作。

几种解决方案

为了解决这个问题,一般有如下解决方案.
分布式锁家族:

数据库:

  • 排它锁(悲观锁)
  • 乐观锁

Redis

  1. 自己实现Redis SET SETNX 操作,结合Lua脚本确保原子操作
  2. RedLock Redis里分布式锁实现的算法,争议比较大,谨慎使用
  3. 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.

到此这篇关于python-redis-lock分布式锁的文章就介绍到这了,更多相关python分布式锁内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Redis分布式锁python-redis-lock使用方法

    python-redis-lock 多个redis客户端访问同一个redis服务端,控制并发. github:https://pypi.org/project/python-redis-lock/ 在使用这个库之前,需要安装如下: pip install python-redis-lock 使用锁的示例: lock = redis_lock.Lock(conn, "name-of-the-lock") if lock.acquire(blocking=False): print(&qu

  • python如何使用Redis构建分布式锁

    这篇文章主要介绍了python如何使用Redis构建分布式锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在实际应用场景中,我们可能有多个worker,可能在一台机器,也可能分布在不同的机器,但只有一个worker可以同时持有一把锁,这个时候我们就需要用到分布式锁了. 这里推荐python的实现库,Redlock-py(Python 实现). 正常情况下,worker获得锁后,处理自己的任务,完成后自动释放持有的锁,是不是感觉有点熟悉,很容易

  • Python实现的redis分布式锁功能示例

    本文实例讲述了Python实现的redis分布式锁功能.分享给大家供大家参考,具体如下: #!/usr/bin/env python # coding=utf-8 import time import redis class RedisLock(object): def __init__(self, key): self.rdcon = redis.Redis(host='', port=6379, password="", db=1) self._lock = 0 self.lock

  • Redis实现分布式锁的几种方法总结

    Redis实现分布式锁的几种方法总结 分布式锁是控制分布式系统之间同步访问共享资源的一种方式.在分布式系统中,常常需要协调他们的动作.如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁. 我们来假设一个最简单的秒杀场景:数据库里有一张表,column分别是商品ID,和商品ID对应的库存量,秒杀成功就将此商品库存量-1.现在假设有1000个线程来秒杀两件商品,500个线程秒杀第一个商品,

  • 基于Redis实现分布式锁以及任务队列

    一.前言 双十一刚过不久,大家都知道在天猫.京东.苏宁等等电商网站上有很多秒杀活动,例如在某一个时刻抢购一个原价1999现在秒杀价只要999的手机时,会迎来一个用户请求的高峰期,可能会有几十万几百万的并发量,来抢这个手机,在高并发的情形下会对数据库服务器或者是文件服务器应用服务器造成巨大的压力,严重时说不定就宕机了,另一个问题是,秒杀的东西都是有量的,例如一款手机只有10台的量秒杀,那么,在高并发的情况下,成千上万条数据更新数据库(例如10台的量被人抢一台就会在数据集某些记录下 减1),那次这个

  • SpringBoot使用Redis实现分布式锁

    前言 在单机应用时代,我们对一个共享的对象进行多线程访问的时候,使用java的synchronized关键字或者ReentrantLock类对操作的对象加锁就可以解决对象的线程安全问题. 分布式应用时代这个方法却行不通了,我们的应用可能被部署到多台机器上,运行在不同的JVM里,一个对象可能同时存在多台机器的内存中,怎样使共享对象同时只被一个线程处理就成了一个问题. 在分布式系统中为了保证一个对象在高并发的情况下只能被一个线程使用,我们需要一种跨JVM的互斥机制来控制共享资源的访问,此时就需要用到

  • SpringBoot中使用redis做分布式锁的方法

    一.模拟问题 最近在公司遇到一个问题,挂号系统是做的集群,比如启动了两个相同的服务,病人挂号的时候可能会出现同号的情况,比如两个病人挂出来的号都是上午2号.这就出现了问题,由于是集群部署的,所以单纯在代码中的方法中加锁是不能解决这种情况的.下面我将模拟这种情况,用redis做分布式锁来解决这个问题. 1.新建挂号明细表 2.在idea上新建项目 下图是创建好的项目结构,上面那个parent项目是其他项目不用管它,和新建的没有关系 3.开始创建controller,service,dao(mapp

  • 基于Redis实现分布式锁的方法(lua脚本版)

    1.前言 在Java中,我们通过锁来避免由于竞争而造成的数据不一致问题.通常我们使用synchronized .Lock来实现.但是Java中的锁只能保证在同一个JVM进程内中可用,在跨JVM进程,例如分布式系统上则不可靠了. 2.分布式锁 分布式锁,是一种思想,它的实现方式有很多,如基于数据库实现.基于缓存(Redis等)实现.基于Zookeeper实现等等.为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件 互斥性:在任意时刻,只有一个客户端能持有锁. 不会发生死锁:即使客户端

  • C#实现Redis的分布式锁

    目录 Redis实现分布式锁(悲观锁/乐观锁) Redis连接池 使用Redis的SetNX命令实现加锁, 调用方式 Redis实现分布式锁(悲观锁/乐观锁) 对锁的概念和应用场景在此就不阐述了,网上搜索有很多解释,只是我搜索到的使用C#利用Redis的SetNX命令实现的锁虽然能用,但是都不太适合我需要的场景. Redis有三个最基本属性来保证分布式锁的有效实现: 安全性: 互斥,在任何时候,只有一个客户端能持有锁. 活跃性A:没有死锁,即使客户端在持有锁的时候崩溃,最后也会有其他客户端能获得

  • Redis实现分布式锁方法详细

    目录 1. 单机数据一致性 2. 分布式数据一致性 3. Redis实现分布式锁 3.1 方式一 3.2 方式二(改进方式一) 3.3 方式三(改进方式二) 3.4 方式四(改进方式三) 3.5 方式五(改进方式四) 3.6 小结 在单体应用中,如果我们对共享数据不进行加锁操作,会出现数据一致性问题,我们的解决办法通常是加锁. 在分布式架构中,我们同样会遇到数据共享操作问题,本文章使用Redis来解决分布式架构中的数据一致性问题. 1. 单机数据一致性 单机数据一致性架构如下图所示:多个可客户访

  • SpringBoot基于Redis的分布式锁实现过程记录

    目录 一.概述 二.环境搭建 三.模拟一个库存扣减的场景 四.总结 一.概述 什么是分布式锁 在单机环境中,一般在多并发多线程场景下,出现多个线程去抢占一个资源,这个时候会出现线程同步问题,造成执行的结果没有达到预期.我们会用线程间加锁的方式,比如synchronized,lock,volatile,以及JVM并发包中提供的其他工具类去处理此问题. 但是随着技术的发展,分布式系统的出现,各个应用服务都部署在不同节点,由各自的JVM去操控,资源已经不是在 线程 之间的共享,而是变成了 进程 之间的

  • Redis实现分布式锁的五种方法详解

    目录 1. 单机数据一致性 2. 分布式数据一致性 3. Redis实现分布式锁 3.1 方式一 3.2 方式二(改进方式一) 3.3 方式三(改进方式二) 3.4 方式四(改进方式三) 3.5 方式五(改进方式四) 3.6 小结 在单体应用中,如果我们对共享数据不进行加锁操作,会出现数据一致性问题,我们的解决办法通常是加锁. 在分布式架构中,我们同样会遇到数据共享操作问题,本文章使用Redis来解决分布式架构中的数据一致性问题. 1. 单机数据一致性 单机数据一致性架构如下图所示:多个可客户访

随机推荐