Redis 使用 Lua 脚本进行原子操作

Redis 使用 Lua 脚本进行原子操作

Intro

之前写过一篇文章也是 Redis 使用 LUA 脚本实现分布式的 CAS 操作,可以参考:基于 Redis 实现 CAS 操作

最近使用 Redis 的时候有一个需求,只有值发生变化的时候才更新,如果要更新的值和现在的值是一样的就不用更新,有点类似于 SET NX,只是 SET NX 只有值不存在的时候才会 SET,我的需求则是要检查要 SET 的值和 Redis 里的值,如果不一样就 SET,一样就直接返回

Implement

我实现了针对 StringHash 的 SET 检查,核心就是我们的 Lua 脚本

实现代码如下:

对于 Hash 会多一个参数 —— hash field name, 对于 string 则直接是 value 了,就会比 hash 少一个参数

private const string HashSetWhenValueChangedLuaScript = @"
if redis.call(""HGET"", KEYS[1], ARGV[1]) == ARGV[2] thenreturn 0
elseredis.call(""HSET"", KEYS[1], ARGV[1], ARGV[2])return 1
end
";private const string StringSetWhenValueChangedLuaScript = @"
if redis.call(""GET"", KEYS[1]) == ARGV[1] thenreturn 0
elseredis.call(""SET"", KEYS[1], ARGV[1])return 1
end
";

实现起来也比较简单,就是先取一下 Redis 中的数据,如果和输入的值是一样就返回 0,不一样则更新值,然后返回 1

StackExchange.Redis 使用 API

StackExchange.Redis 中可以使用 ScriptEvaluate/ScriptEvaluateAsync 来执行 Lua 脚本,为了方便使用我把他们封装成了扩展方法,实现如下:

public static bool StringSetWhenValueChanged(this IDatabase db, RedisKey key, RedisValue value)
{return (int)db.ScriptEvaluate(StringSetWhenValueChangedLuaScript, new[] { key }, new[] { value }) == 1;
}public static async Task<bool> StringSetWhenValueChangedAsync(this IDatabase db, RedisKey key, RedisValue value)
{return await db.ScriptEvaluateAsync(StringSetWhenValueChangedLuaScript, new[] { key }, new[] { value }).ContinueWith(r => (int)r.Result == 1);
}public static bool HashSetWhenValueChanged(this IDatabase db, RedisKey key, RedisValue field, RedisValue value)
{return (int)db.ScriptEvaluate(HashSetWhenValueChangedLuaScript, new[] { key }, new[] { field, value }) == 1;
}public static async Task<bool> HashSetWhenValueChangedAsync(this IDatabase db, RedisKey key, RedisValue field, RedisValue value)
{return await db.ScriptEvaluateAsync(HashSetWhenValueChangedLuaScript, new[] { key }, new[] { field, value }).ContinueWith(r => (int)r.Result == 1);
}

Sample

使用示例可以参考下面的测试用例:

[Fact]
public void StringSetWhenValueChangedTest()
{var key = $"{nameof(StringSetWhenValueChangedTest)}";var redis = DependencyResolver.Current.GetRequiredService<IConnectionMultiplexer>().GetDatabase();redis.StringSet(key, 1);// update to 1 if now is not 1Assert.False(redis.StringSetWhenValueChanged(key, 1));Assert.Equal(1, redis.StringGet(key));// update to 2 if now is not 2Assert.True(redis.StringSetWhenValueChanged(key, 2));Assert.Equal(2, redis.StringGet(key));
}[Fact]
public void HashSetWhenValueChangedTest()
{var key = $"{nameof(HashSetWhenValueChangedTest)}";var field = "testField";var redis = DependencyResolver.Current.GetRequiredService<IConnectionMultiplexer>().GetDatabase();redis.HashSet(key, field, 1);Assert.False(redis.HashSetWhenValueChanged(key, field, 1));Assert.Equal(1, redis.HashGet(key, field));Assert.True(redis.HashSetWhenValueChanged(key, field, 2));Assert.Equal(2, redis.HashGet(key, field));
}

More

在使用 Lua 脚本的时候,如果要使用不等于的逻辑需要小心一些,和其他语言不同,需要使用 ~= 而非 != 来表示不等

References

  • https://github.com/WeihanLi/WeihanLi.Redis/blob/dev/src/WeihanLi.Redis/RedisExtensions.cs

  • https://github.com/WeihanLi/WeihanLi.Redis/blob/dev/test/WeihanLi.Redis.UnitTest/RedisExtensionsTest.cs

  • 基于 Redis 实现 CAS 操作

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

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

相关文章

奇妙的数学动图,美到令人窒息!

全世界只有3.14 % 的人关注了爆炸吧知识来源&#xff1a;制造科技原理&#xff0c;版权原作者所有。如有侵权联系删除&#xff01;论文查重券 限时免费领 官方授权 安全保障 真实有效点「在看」的人都变好看了哦

matlab井深测量,一种井深测量系统及方法与流程

本申请涉及钻井技术领域&#xff1a;&#xff0c;尤其涉及一种井深测量系统及方法。背景技术&#xff1a;&#xff1a;在钻井施工中过程中&#xff0c;施工人员需要实时了解井深的变换情况&#xff0c;因此&#xff0c;需要在钻井的过程中实时对井深进行测量。。目前&#xff0…

Log4Net使用指南

声明&#xff1a;本文内容主要译自Nauman Leghari的Using log4net&#xff0c;亦加入了个人的一点心得(节3.1.4)。请在这里下载示例代码 1 简介 1.1 Log4net的优点&#xff1a; 几乎所有的大型应用都会有自己的用于跟踪调试的API。因为一旦程序被部署以后…

搞怪菜鸟加入域全程图解[为企业部署Windows Server 2008系列十二]

在前面部署完毕了windows server 2008的服务器。那么现在我们需要考虑的是如何将客户端加入域。很多朋友在企业实际生产环境中经常遇到加入域的问题&#xff0c;那么在windows server 2008 域环境中呢&#xff0c;如何排除这些问题&#xff0c;本次课程就以雷人故事的角度专门为…

怎样让电脑速度变快_硬盘在电脑中起什么作用?

计算机中的所有数据都保存在硬盘上&#xff0c; 很简单&#xff0c;硬盘的作用就是存储数据。一、补充&#xff1a;1、移动硬盘(Mobile Hard disk)顾名思义是以硬盘为存储介质&#xff0c;计算机之间交换大容量数据&#xff0c;强调便携性的存储产品。2、市场上绝大多数的移动硬…

Qualcomm平台camera调试移植入门

2019独角兽企业重金招聘Python工程师标准>>> 1 camera基本代码架构 高通平台对于camera的代码组织&#xff0c;大体上还是遵循Android的框架&#xff1a;即上层应用和HAL层交互&#xff0c;高通平台在HAL层里面实现自己的一套管理策略&#xff1b; 在kernel中实现s…

Blazor WebAssembly 应用程序中进行 HTTP 请求

翻译自 Waqas Anwar 2021年5月13日的文章 《Making HTTP Requests in Blazor WebAssembly Apps》 [1]在我的前篇文章《Blazor Server 应用程序中进行 HTTP 请求》中&#xff0c;我介绍了在 Blazor Server 应用程序中进行 HTTP 请求的相关技术&#xff0c;在 Blazor Server App …

AI如果耍起了心眼,人类就像个白痴......

耍小心眼已经不是人类专利了。之前&#xff0c;有一群研究者整理了一个场景的List&#xff0c;细数了AI为了完成任务&#xff0c;而耍的小心眼&#xff0c;或者说作弊。例如&#xff0c;在让AI玩俄罗斯方块的时候&#xff0c;发现最佳完成任务的方式是直接暂停游戏&#xff1b;…

ASP.NET MVC数据验证(上)

关于ASP.NET MVC的验证&#xff0c;用起来很特别&#xff0c;因为MS的封装&#xff0c;使人理解起来很费解。也可能很多人都在Scott Guthrie等人写的一本《ASP.NET MVC 1.0》书中&#xff0c;见过NerdDinner项目中对Dinner对象修改和添加的时的数据验证。但有许多封装的地方&am…

Android 的基本组件之一 Gallery

声明&#xff1a;本人博客纯属个人学习过程中的一些仿写的简单练习记录&#xff0c;其他论坛也有类似内容&#xff01;&#xff08;可能不免有错误之处&#xff0c;还望见谅&#xff0c;指出&#xff09;这是一个最简单可以滑动查看图片的应用程序&#xff1a;首先创建项目名为…

【设计模式】—— 中介者模式Mediator

前言&#xff1a;【模式总览】——————————by xingoo 模式意图 使用一个中介的对象&#xff0c;封装一组对象之间的交互&#xff0c;这样这些对象就可以不用彼此耦合。 这个中介者常常起着中间桥梁的作用&#xff0c;使其他的对象可以利用中介者完成某些行为活动&#…

contos6.5卸载php7,centos8 测地卸载php5.6 与卸载php7

centos8 yum php 默认安装 php7.1.2我想卸载php7 &#xff0c;安装php5.6yum remove php 无法彻底卸载干净。必须强制删除&#xff0c;使用下面命令查看全部php软件包rpm -qa|grep php&#xff0c;然后安装指定顺序卸载卸载php7.X[rootxxx php-memcached]# rpm -qa | grep phpp…

【招聘(上海)】美团酒店招聘 .NET 高级开发

美团酒店介绍&#xff1a;美团酒店是美团旗下的综合住宿服务平台&#xff0c;始终秉承“帮大家住得更好”的使命。成立以来&#xff0c;屡次刷新中国在线住宿行业新纪录。目前&#xff0c;美团已覆盖超过40万家国内酒店&#xff0c;以及全球200多个国家的50000多个城市。我们求…

mysql数据库主要用来做什么的_水晶头骨用来做什么的?

1927年一个小女孩在挖掘时&#xff0c;发现了一颗人头骨。这颗头骨是用水晶做成的&#xff0c;之后关于水晶头骨之谜一直被人津津乐道&#xff0c;人们一直在猜测水晶头骨用来做什么的&#xff1f;一共有多少个&#xff1f;在小女孩挖到这颗头骨之前&#xff0c;大英博物馆里就…

日本画风超级“诡异”毕业典礼上线,网友:有被吓到,谢谢!

转眼间又到了日本毕业季&#xff0c;四月份本来是日本毕业季。在日本&#xff0c;毕业季是非常仪式感的存在&#xff1a;学校里会满是穿着浴衣、盛装打扮的小哥哥小姐姐&#xff0c;拿着毕业证书&#xff0c;在樱花树下合照。图片来源&#xff1a;日剧《对不起&#xff0c;青春…

文本文件的读写

// 读文件 public TextWriter w; // 写文件 public TextReader r; // 读文本文件 private void button1_Click(object sender, System.EventArgs e) { if(openFileDialog1.ShowDialog() DialogResult.OK) { textBox1.Text openFileDialog1.FileName; r new StreamReader(ope…

博客编辑工具ckeditor

在asp网站开发过程当中常常用到漂亮的编辑工具。 在这个网站有不少&#xff1a;http://ckeditor.com/ 而且下载下来就可以使用&#xff0c;是开源的。它不像asp里面的.dll控件拖进来就可以使用&#xff0c;而是通过调用的方式使用。 下载下来解压之后就可以直接包含在项目中&am…

java单链表查询功能,Java 实现简答的单链表的功能

作者&#xff1a;林子木 博客网址&#xff1a;http://blog.csdn.net/wolinxuebin參考网址&#xff1a;http://blog.csdn.net/sunsaigang/article/details/5751780描写叙述&#xff1a;使用java实现简答的单链表的功能定义了一个MyList类包括的函数&#xff1a;getHead()返回头…

记一次 .NET 某流媒体独角兽 API 句柄泄漏分析

一&#xff1a;背景 1. 讲故事上上周有位朋友找到我&#xff0c;说他的程序CPU和句柄都在不断的增长&#xff0c;无回头趋势&#xff0c;查了好些天也没什么进展&#xff0c;特加wx寻求帮助&#xff0c;截图如下&#xff1a;看的出来这位朋友也是非常郁闷&#xff0c;出问题还出…

iphone最新款手机_苹果罕见“跌停”!遭遇6年来最惨淡一夜,2019年全球股市第一颗雷引爆...

2019年全球股市的第一颗大雷引爆了。受苹果下调营收预期影响&#xff0c;周四盘中&#xff0c;苹果股价一度跌至142.08美元&#xff0c;创逾一年半新低&#xff0c;日内跌幅超过10%&#xff0c;市值缩水750亿美元。最终&#xff0c;苹果收跌9.96%&#xff0c;创出自2013年1月以…