百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

使用Redis构建全局并发锁(redis集群并发)

mhr18 2024-10-25 12:38 36 浏览 0 评论

谈起Redis的用途,小伙伴们都会说使用它作为缓存,目前很多公司都用Redis作为缓存,但是使用Redis仅仅作为缓存未免太大材小用了。深究Redis的原理后你会发现它有很多用途,在很多场景下能够使用它快速地解决问题。常见的用途有:分布式锁控制并发、结合bloom filter用于推荐去重、HyperLogLog用于统计UV、限流控制流量等等;这里我谈下Redis分布式锁控制并发的问题。

高并发是个老生常谈的问题,当产品达到一定规模用户量后,这个问题是不得不考虑的,即使当前用户量不大(例如博主现在的公司),但自己平时在设计API的时候最好也尽可能地考虑到并发问题。

Redis分布式锁控制并发主要是通过在Redis里面创建一个key,当其它进程准备占用的时候只能等待key释放再占用。Redis里面有一个原子性指令setnx,当key存在时,它返回0,表示当前已有进程占用,当它返回1时可以执行业务逻辑,此时没有进程占用,等逻辑执行完后,可以删除key释放锁,这样可以简单的控制并发。

但是细想之下你会发现,在业务逻辑执行的过程中如果发生异常,此时key并没有删除,这样就会造成死锁,死锁带来的后果想必大家都很清楚。为了解决这个问题,可以在setnx加锁后设置key的过期时间,当key到期自动删除。

但是仔细想想你还会发现,如果在执行setnx后,执行expire前Redis发生宕机了,这样就不会执行expire,也会造成死锁。由于setnx与expire是两条命令,并且expire依赖setnx的执行结果,为了解决这个问题可以使用set key value [expiration EX seconds|PX milliseconds] [NX|XX] ,这是一条原子性的指令,同时包含setnx和expire。

使用python实现的代码:

1 class RedisLock(object):
 2 """
 3 踩坑 Redis并发锁
 4 """
 5 
 6 def __init__(self, key):
 7 self.redis_conn = get_redis_conn()
 8 self.lock_key = "{}_redis_gil".format(key)
 9 
10 @staticmethod
11 def get_lock_value(cls):
12 """
13 获取value
14 :param cls:
15 :return:
16 """
17 cls.get_lok = cls.redis_conn.get(cls.lock_key)
18 return cls.get_lok
19 
20 @staticmethod
21 def set_lock(cls, random_value):
22 """
23 不能使用setnx 没有设置过期时间,可能会出现死锁
24 引入random_value :自己加的锁只能自己释放
25 :param cls:
26 :param random_value:
27 :return:
28 """
29 cls._lock = cls.redis_conn.set(cls.lock_key, random_value, nx=True, ex=5)
30 
31 # 如果返回null 表示key存在存在并发
32 if cls._lock:
33 return True
34 else:
35 LOGGER = logging.getLogger('core.utils')
36 LOGGER.warning(u"试题复制存在并发")
37 raise RsError("试题复制存在并发,请稍后再试")
38 
39 @staticmethod
40 def release(cls):
41 """
42 释放锁
43 :param cls:
44 :return:
45 """
46 cls.redis_conn.delete(cls.lock_key)
47 
48 @staticmethod
49 def redis_lock(cls):
50 """
51 只有当设置的value与do_something执行完后所获取的值相同时才删除key
52 防止在分布式redis中: clientA由于执行时间过期,clientB获取锁,
53 clientA执行完后释放锁(删除key),其实这时候删除的是B的key,
 喜欢的朋友可以进圈:609164807 一起交流 一起进步
54 为防止这种情况引入random_value 只有当前值为random_value时才删除
55 :param cls:
56 :return:
57 """
58 random_value = time.time()
59 if cls.set_lock(cls, random_value):
60 do_something()
61 now_value = cls.get_lock_value(cls)
62 if now_value == random_value:
63 cls.release()
64 return True
65 else:
66 return False
67 
68 
69 def do_something():
70 pass

在实际业务中调用Redis全局锁,进行加锁示例:

1 # 公库试题复制到平台考虑并发问题,加锁处理
 2 if self.visible_scope == 10:
 3 key = hash(self.question_id)
 4 cls = RedisLock(key)
 5 cls.redis_lock(cls)
 6 try:
 7 self.insert_question()
 8 except Exception:
 9 raise RsError("试题插入失败")
10 finally:
11 cls.release(cls)

如果是Redis集群下此方法可能仍然有问题,试想下:在一个redis集群中,主节点由于某种原因挂掉了,从节点变成了主节点,而此时redis锁还未同步到原从节点中,那么这个锁也就失效了,当其它进程申请锁时仍然可以申请成功。

针对这个问题,新版的redis引入了redlock,通过redlock.Redlock对多个redis节点进行加锁,当超过一半的节点加锁成功时锁才生效。这样在一定程度上提高了高可用性,但由于每次加锁和释放锁要对多个节点进行读写,所以性能上肯定是没有单节点锁高的。

喜欢的朋友可以点点关注,后台私信回复“Java”免费获取一份资料学习

相关推荐

【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库

如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...

Pure Storage推出统一数据管理云平台及新闪存阵列

PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...

对Java学习的10条建议(对java课程的建议)

不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...

SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!

官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...

JDK21有没有什么稳定、简单又强势的特性?

佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...

「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了

在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...

Java面试题及答案最全总结(2025版)

大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...

数据库日常运维工作内容(数据库日常运维 工作内容)

#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...

分布式之系统底层原理(上)(底层分布式技术)

作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...

oracle 死锁了怎么办?kill 进程 直接上干货

1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...

SpringBoot 各种分页查询方式详解(全网最全)

一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...

《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略

《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...

LoadRunner(loadrunner录制不到脚本)

一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...

Redis数据类型介绍(redis 数据类型)

介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...

RMAN备份监控及优化总结(rman备份原理)

今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...

取消回复欢迎 发表评论: