阅读目录

  1.   什么事分布式锁
  2.   基于redis实现分布式锁

 

一、什么是分布式锁

我们在开发应用的时候,如果需要对某一个共享变量进行多线程同步访问的时候,可以使用我们学到的锁进行处理,并且可以完美的运行,毫无Bug!

注意这是单机应用,后来业务发展,需要做集群,一个应用需要部署到几台机器上然后做负载均衡,大致如下图:

上图可以看到,变量A存在三个服务器内存中(这个变量A主要体现是在一个类中的一个成员变量,是一个有状态的对象),如果不加任何控制的话,变量A同时都会在分配一块内存,三个请求发过来同时对这个变量操作,显然结果是不对的!即使不是同时发过来,三个请求分别操作三个不同内存区域的数据,变量A之间不存在共享,也不具有可见性,处理的结果也是不对的!

如果我们业务中确实存在这个场景的话,我们就需要一种方法解决这个问题!

为了保证一个方法或属性在高并发情况下的同一时间只能被同一个线程执行,在传统单体应用单机部署的情况下,可以使用并发处理相关的功能进行互斥控制。但是,随着业务发展的需要,原单体单机部署的系统被演化成分布式集群系统后,由于分布式系统多线程、多进程并且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,单纯的应用并不能提供分布式锁的能力。为了解决这个问题就需要一种跨机器的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题!

分布式锁应该具备哪些条件:

  1、在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行;
  2、高可用的获取锁与释放锁;
  3、高性能的获取锁与释放锁;
  4、具备可重入特性;
  5、具备锁失效机制,防止死锁;
  6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败

二、基于redis实现分布式锁

1、选用Redis实现分布式锁原因:

(1)Redis有很高的性能;
(2)Redis命令对此支持较好,实现起来比较方便

2、使用命令介绍:

(1)SETNX

  SETNX key val:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。

(2)expire

  expire key timeout:为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。

(3)delete

  delete key:删除key

  在使用Redis实现分布式锁的时候,主要就会使用到这三个命令。

3、实现思想:

(1)获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断。

(2)获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。

(3)释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放。

#连接redis
import time
import uuid
from threading import Thread import redis redis_client = redis.Redis(host="localhost",
port=6379,
# password=123,
db=10) #获取一个锁
# lock_name:锁定名称
# acquire_time: 客户端等待获取锁的时间
# time_out: 锁的超时时间
def acquire_lock(lock_name, acquire_time=10, time_out=10):
"""获取一个分布式锁"""
identifier = str(uuid.uuid4())
end = time.time() + acquire_time
lock = "string:lock:" + lock_name
while time.time() < end:
if redis_client.setnx(lock, identifier):
# 给锁设置超时时间, 防止进程崩溃导致其他进程无法获取锁
redis_client.expire(lock, time_out)
return identifier
elif not redis_client.ttl(lock):
redis_client.expire(lock, time_out)
time.sleep(0.001)
return False #释放一个锁
def release_lock(lock_name, identifier):
"""通用的锁释放函数"""
lock = "string:lock:" + lock_name
pip = redis_client.pipeline(True)
while True:
try:
pip.watch(lock)
lock_value = redis_client.get(lock)
if not lock_value:
return True if lock_value.decode() == identifier:
pip.multi()
pip.delete(lock)
pip.execute()
return True
pip.unwatch()
break
except redis.excetions.WacthcError:
pass
return False if __name__ == __main__:
count=10
  def seckill(i):
   identifier=acquire_lock('resource')
  print("线程:{}--获得了锁".format(i))
   time.sleep(1)
   global count
  if count<1:
   print("线程:{}--没抢到,票抢完了".format(i))
   return
   count-=1
   print("线程:{}--抢到一张票,还剩{}张票".format(i,count))
  release_lock('resource',identifier)   # 线程之间通用一个变量,
  # 此处也可以考虑使用进程, 进程的结果和线程反差很大
  for i in range(50):    t = Thread(target=seckill,args=(i,))   t.start()

python基于redis实现分布式锁的更多相关文章

  1. 基于 redis 的分布式锁实现 Distributed locks with Redis debug 排查错误

    小结: 1. 锁的实现方式,按照应用的实现架构,可能会有以下几种类型: 如果处理程序是单进程多线程的,在 python下,就可以使用 threading 模块的 Lock 对象来限制对共享变量的同步访 ...

  2. 基于redis 实现分布式锁的方案

    在电商项目中,经常有秒杀这样的活动促销,在并发访问下,很容易出现上述问题.如果在库存操作上,加锁就可以避免库存卖超的问题.分布式锁使分布式系统之间同步访问共享资源的一种方式 基于redis实现分布式锁 ...

  3. 基于redis的分布式锁

    <?php /** * 基于redis的分布式锁 * * 参考开源代码: * http://nleach.com/post/31299575840/redis-mutex-in-php * * ...

  4. 基于Redis的分布式锁真的安全吗?

    说明: 我前段时间写了一篇用consul实现分布式锁,感觉理解的也不是很好,直到我看到了这2篇写分布式锁的讨论,真的是很佩服作者严谨的态度, 把这种分布式锁研究的这么透彻,作者这种技术态度真的值得我好 ...

  5. 基于 Redis 的分布式锁

    前言 分布式锁在分布式应用中应用广泛,想要搞懂一个新事物首先得了解它的由来,这样才能更加的理解甚至可以举一反三. 首先谈到分布式锁自然也就联想到分布式应用. 在我们将应用拆分为分布式应用之前的单机系统 ...

  6. 基于redis的分布式锁(转)

    基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...

  7. 基于redis的分布式锁实现

    1.分布式锁介绍 在计算机系统中,锁作为一种控制并发的机制无处不在. 单机环境下,操作系统能够在进程或线程之间通过本地的锁来控制并发程序的行为.而在如今的大型复杂系统中,通常采用的是分布式架构提供服务 ...

  8. 基于redis的分布式锁(不适合用于生产环境)

    基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...

  9. 转载:基于Redis实现分布式锁

    转载:基于Redis实现分布式锁  ,出处: http://blog.csdn.net/ugg/article/details/41894947 背景在很多互联网产品应用中,有些场景需要加锁处理,比如 ...

随机推荐

  1. MySQL MHA--故障切换模式(GTID模式和非GTID模式)

    GTID和非GTID故障切换模式选择 MySQL 5.6版本引入GTID来解决主从切换时BINLOG位置点难定位的问题,MHA从0.56版本开始支持基于GTID的复制,在切换时可以采用GTID模式和非 ...

  2. USB之设备插入波形变化2

    =============  本系列参考  ============= <圈圈教你玩USB>.<Linux那些事儿之我是USB> 协议文档:https://www.usb.or ...

  3. HTML&CSS基础-meta标签

    HTML&CSS基础-meta标签 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.常见字符集 1>ASCII 我们知道计算机是由外国人发明的,他们当时也没有考虑到 ...

  4. 团队项目-Beta冲刺

    请大家在每次作业开头添加格式描述: 这个作业属于哪个课程 <课程的链接> 这个作业要求在哪里 <作业要求的链接> 团队名称 <写上团队名称>(附上团队博客链接) 这 ...

  5. 卓越Code第一次作业

    第一次团队作业 序言 所属课程 https://edu.cnblogs.com/campus/xnsy/2019autumnsystemanalysisanddesign 作业要求 https://w ...

  6. 第五次作业——Alpha项目测试

    第五次作业——Alpha项目测试 格式描述: 这个作业属于哪个课程 2019秋软工17级系统分析与设计 这个作业要求在哪里 作业要求 团队名称 杨荣模杰和他的佶祥虎 这个作业的目标 测试其他组项目并写 ...

  7. jquery选择器之全选择器

    在CSS中,经常会在第一行写下这样一段样式 * {padding: 0; margin: 0;} 通配符*意味着给所有的元素设置默认的边距.jQuery中我们也可以通过传递*选择器来选中文档页面中的元 ...

  8. Unity经典案例之:Fire Balls

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  9. 微信小程序~自定义属性设置和获取(data-)

    自定义属性语法以data-开头: <button data-info="自定义数据" bindtap="testClick">自定义属性测试< ...

  10. 大数据开发之keras代码框架应用

    总体来讲keras这个深度学习框架真的很“简易”,它体现在可参考的文档写的比较详细,不像caffe,装完以后都得靠技术博客,keras有它自己的官方文档(不过是英文的),这给初学者提供了很大的学习空间 ...