职业生涯第一课---“Redis分布式锁优化:确保唯一性与效率“

前言

最近因为刚入职公司开启自己的实习生涯,工作和毕设论文同步进行,导致有段时间没更新博客了,今天来分享一下最近学到的一些知识。

场景介绍

BOSS让我写一些接口,他提出这样一个需求,该接口的参数有多个,其中包含shopname参数,该参数要根据调用者传入的shopname再在后边拼接一个id,作为一个新的字段来作为参数去调用别的接口。而且要保证ID的唯一性。因为BOSS要我写的接口是我们公司内部用的系统的接口,并发量不会太大,但我想万一真有两个人近乎一起用了该接口,该怎样保证获取的id的唯一性。于是就有了下面的经历。

该场景需要从Redis中获取一个唯一id并修改它的值,因为要保整其获取的id的唯一性,又因有一定的并发量,所以采用先占位再获取的方法,防止id重复。

待优化代码

这段代码是我本来自己写的,后来感觉质量不是太高,总觉得能有优化的地方,但由于公司就我一个Python,没办法去问别人,于是就去问ChatGPT。源代码如下。

# 获取当前id_flag,采取先占位再获取的方法,防止id重复
def get_curentid(report_num:int) -> int:def get_titleid_flag() -> int:titleid_flag = int(r.get("titleid_flag"))return titleid_flagdef set_titleid_flag(old_titleid_flag, new_titleid_flag: int) -> bool:if old_titleid_flag == get_titleid_flag():r.set("titleid_flag", new_titleid_flag)return Trueelse:return Falsetime_pull = time.time()time_end = time_pull + 5old_titleid_flag = get_titleid_flag()while True:if set_titleid_flag(old_titleid_flag, old_titleid_flag + report_num):return old_titleid_flagelif time.time() < time_end:old_titleid_flag = get_titleid_flag()continueelse:return -1

代码解释:

该函数是用来当前 id_flag 的方法。采用了先占位再获取的策略,以防止 id 的重复使用。下面是简单的解释:

  1. get_curentid(report_num:int) -> int: 这是主函数,它接受一个整数参数 report_num,表示要修改的id值,并返回一个整数作为当前的 id_flag。
  2. get_titleid_flag() -> int: 这个函数从Redis中获取当前的 titleid_flag,并将其转换为整数后返回。
  3. set_titleid_flag(old_titleid_flag, new_titleid_flag: int) -> bool: 这个函数尝试将 titleid_flag 的值从旧值更新为新值。在更新前先查询旧值有没有变化,若无变化则更新。如果更新成功,则返回 True,否则返回 False。
  4. 在主函数中通过循环不断尝试更新 titleid_flag 的值,直到更新成功或者超时时间到达。超时时间为 5 秒。
  5. 如果成功更新了 titleid_flag 的值,则返回旧的 titleid_flag,表示成功获取到了 id_flag。如果超时未能成功更新,则返回 -1,表示获取失败。

总之,这个函数通过Redis中的一个标识值来确保获取到的 id_flag 是唯一的,并且采用了一定的重试机制来应对可能的竞争条件或者网络延迟导致的更新失败情况。

然后问了ChatGPT后,他给了我一下优化建议。

代码可优化方向:

image.png

因为对原子操作和分布式锁之前没了解过,所以特意去搜索了解了一下。

原子操作介绍:

image.png

分布式锁介绍

image.png

一些好的提高并发度和性能的算法或方案

之后又问了ChatGPT有没有什么好的方案,他给出了一下方案,总结一下就是;确保访问唯一性,减少访问频次,限制并发数量。具体回答如下:

image.png

令牌桶算法和漏桶算法

除此之外,还了解了两个新的关于限流的算法。
image.png

优化后的代码

基于上述信息,我对原本的代码进行了下列优化,利用Redis的原子操作来优化这段代码,使用 Redis 的 SETNX(SET if Not eXists)命令来实现分布式锁。SETNX 命令可以在 key 不存在的情况下设置 key 的值,如果 key 已经存在,则不进行任何操作。

import redis
import time# 创建 Redis 客户端连接
redis_client = redis.Redis(host='localhost', port=6379, db=0)# 获取铺位评估报告当前 id_flag,采取先占位再获取的方法,防止id重复
def get_curentid(report_num: int) -> int:# 设置锁的过期时间,防止锁未正常释放导致死锁lock_timeout = 5  # 5秒# 生成锁的键名lock_key = "titleid_flag_lock"# 初始化等待时间wait_time = 0.1# 循环尝试获取锁while True:# 使用 SETNX 命令尝试获取锁lock_acquired = redis_client.setnx(lock_key, "locked")if lock_acquired:# 如果成功获取锁,则设置锁的过期时间redis_client.expire(lock_key, lock_timeout)# 获取当前 id_flagcurrent_id_flag = int(redis_client.get("titleid_flag") or 0)new_id_flag = current_id_flag + report_numredis_client.set("titleid_flag",new_id_flag)# 释放锁redis_client.delete(lock_key)return current_id_flagelse:# 如果获取锁失败,则等待一段时间后重试time.sleep(wait_time)# 等待时间指数增加wait_time *= 2  # 指数增长,可以根据实际情况调整return -1  # 获取失败时返回 -1# 测试代码
report_num = 10
current_id = get_curentid(report_num)
print("Current ID Flag:", current_id)

在这个优化版本中,通过使用 Redis 的 SETNX 命令来获取分布式锁,避免了之前循环重试的方式,提高了效率。同时,在获取锁成功后,设置了锁的过期时间,以防止锁未正常释放导致的死锁问题。同时为了引入指数退避策略,可以在获取锁失败后进行等待时间的指数增加。这样可以减少频繁重试锁的获取,降低系统负载,提高效率。

但是由于只是在开发环境下测试,也没办法模拟高并发情况来对比两段代码的运行结果,理论上优化后的是由优于前者的,但本地测试感官上是差不多。没人带真难受,老代码是我入职第一天晚上自己要的,服务器宝塔面板是第二天自己主动要的,Redis密码是自己在配置文件里查的,遇到问题也是自己解决的,我这两排工位没一个同事,感觉赛博孤岛似的,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/838695.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++并发:构建线程安全的队列

正文 线程安全队列的完整的类定义&#xff0c;其中采用了条件变量&#xff1a; #include <condition_variable> #include <memory> #include <mutex> #include <queue> template <typename T> class threadsafe_queue {private:mutable std::m…

谈谈 HTTP 的方法

目录 方法及其作用 扩展方法 GET 和 POST 的区别 PUT 和 POST 都是给服务器发送新增资源&#xff0c;有什么区别&#xff1f; PUT和PATCH都是给服务器发送修改资源&#xff0c;有什么区别&#xff1f; 方法及其作用 HTTP/0.9 只有1种请求方法&#xff1a;GETHTTP/1.0 新增…

【Linux】线程周边001之多线程

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.线程的理解 2.地址…

Github 2024-05-16 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-05-16统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目4TypeScript项目2C++项目1Go项目1HTML项目1CSS项目1Cuda项目1ChatGPT/Gemini UI: 跨平台聊天应用 创建周期:433 天开发语言:TypeSc…

吴恩达深度学习笔记:优化算法 (Optimization algorithms)2.8

目录 第二门课: 改善深层神经网络&#xff1a;超参数调试、正 则 化 以 及 优 化 (Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)第二周&#xff1a;优化算法 (Optimization algorithms)2.8 Adam 优化算法(Adam optimization algor…

短视频批量剪辑,智能素材文案生成,多账号授权私信回复与矩阵发布素材功能合集系统,短视频矩阵助手源码搭建部署源码开源部署方案。

目录 一、短视频矩阵助手系统是什么&#xff1f; 二、短视频矩阵助手系统可以为企业解决什么问题&#xff1f; 短视频矩阵助手可以解决哪些问题&#xff1f; 三、短视频矩阵助手系统功能有哪些&#xff1f; 四、总结 一、短视频矩阵助手系统是什么&#xff1f; 短视频矩阵…

提升MySQL性能的秘密:了解表压缩功能的使用及其对性能的影响。

在MySQL数据库的使用中&#xff0c;对于字段类型设计大家可能都有一些思路和方式&#xff0c;但是针对存储方面的设计&#xff0c;在表结构设计之初可能就没考虑过&#xff0c;只有当业务发展到一定规模才意识到它所带来的问题严重性。而物理存储主要是考虑是否要启用表的压缩功…

如何把一张图片分割为网页布局

将一张图片分割为适合网页布局的步骤主要涉及使用图像编辑软件&#xff0c;如Adobe Photoshop&#xff0c;进行切片操作。以下是详细的步骤指导&#xff1a; 1. 准备图片 确保你有一张想要分割的图片&#xff0c;并且已经打开了Adobe Photoshop。 2. 选择切片工具 在工具栏…

环保科普馆如何互动化加深观众环保认知?

如今&#xff0c;多媒体技术的广泛应用&#xff0c;已经为环保、天文、生物等各类主题展厅注入了新的活力&#xff0c;在这些展馆中&#xff0c;它凭借独特的互动体验&#xff0c;以及深入浅出的教育方式&#xff0c;赢得了广大观众的热烈追捧。今天&#xff0c;我们就一同探讨…

阿里巴巴发布最新财报,营收重回增长轨道

KlipC报道&#xff1a;5月14日&#xff0c;阿里巴巴集团发布2024财年及第四财季最新财报&#xff0c;财报显示第四财季收入2218.74亿元&#xff0c;同比增长7%&#xff0c;超出市场预期。2024财年收入同比增长8%&#xff0c;达9411.68亿元。 第四财季净利润244.2亿元人民币&am…

【设计模式】JAVA Design Patterns——Aggregator Microservices(聚合器微服务模式)

&#x1f50d;目的 用户对聚合器服务进行一次调用&#xff0c;然后聚合器将调用每个相关的微服务。 &#x1f50d;解释 真实世界例子 网络市场需要有关产品及其当前库存的信息。 它调用聚合服务&#xff0c;聚合服务依次调用产品信息微服务和产品库存微服务&#xff0c;返回组合…

制作coco类型数据集

COCO格式数据集简介 COCO数据集是一个大型的、丰富的物体检测&#xff0c;分割和字幕数据集。这个数据集以scene understanding&#xff08;场景理解&#xff09;为目标&#xff0c;主要从复杂的日常场景中截取&#xff0c;图像中的目标通过精确的segmentation&#xff08;分…

道路运输驾驶员从业资格报考条件

根据《中华人民共和国道路运输条例》、交通运输部《道路运输从业人员管理规定》和上级交通运输部门的管理要求&#xff0c;参加道路运输从业资格培训时应遵守以下规定&#xff1a; 1、年龄不超过60周岁。 2、驾驶员要取得相应的机动车驾驶证&#xff08;C4以上&#xff09;。…

一步步教您轻松搭建YOLO训练环境(视频教程)

一步步教您轻松搭建YOLO训练环境 YOLO&#xff08;You Only Look Once&#xff09;是一种流行的实时目标检测算法。为了安装和部署YOLO的训练环境&#xff0c;你需要按照以下步骤进行操作&#xff1a; 一、前期准备 确定硬件要求&#xff1a;YOLO通常在具有GPU的计算机上运行…

不懂技术可以当项目经理吗?看完这篇你就知道了

项目经理作为项目的核心负责人&#xff0c;主要负责项目的规划、组织、协调和控制。 如果你不懂技术&#xff0c;但具备出色的项目管理技能&#xff0c;你仍然可以成功地管理项目。你可以通过与技术团队建立紧密的合作关系&#xff0c;明确项目需求&#xff0c;并依赖技术团队…

远程医疗系统

在远程医疗系统中&#xff0c;为了充分发挥其推动医疗科技创新的作用&#xff0c;系统可以包含以下功能点&#xff0c;并服务于不同类型的用户&#xff1a; 一、系统功能点 远程会诊系统&#xff1a; 实时视频会诊&#xff1a;医生与患者或医生与医生之间的实时视频交流。 病…

IntelliJ IDEA - 查看项目工程代码量统计

首先安装一个统计插件——Statistic 接着在左下角可以看到 Statistic Logo 插件&#xff0c;点击即可看到统计面板

SCSS详解

SCSS&#xff08;Sassy CSS&#xff09;是Sass 3引入的新语法&#xff0c;完全兼容CSS3&#xff0c;并且继承了Sass的强大功能。与原始的Sass语法不同&#xff0c;SCSS语法使用了和CSS一样的块语法&#xff0c;即使用大括号“{}”将不同的规则分开&#xff0c;使用分号“;”将具…

正则表达式和sed

一、正则表达式 主要用来匹配字符串&#xff08;命令结果&#xff0c;文本内容&#xff09;&#xff0c; 通配符匹配文件&#xff08;而且是已存在的文件&#xff09; 基本正则表达式 扩展正则表达式 1.元字符 . 匹配任意单个字符&#xff0c;可以是一个汉字 […

在C#中编写递归函数时,为了避免无限递归

在C#中编写递归函数时&#xff0c;为了避免无限递归&#xff08;也称为栈溢出&#xff09;&#xff0c;你需要确保递归调用有一个明确的终止条件。这个终止条件通常基于一个或多个参数&#xff0c;当这些参数满足某个特定条件时&#xff0c;递归就会停止并返回结果。 以下是一…