网站新闻公告表怎么做,2015做那个网站能致富,wordpress视频网站上传视频,已将绑定域名给另一个网站Redis 使用 Lua 脚本进行原子操作Intro之前写过一篇文章也是 Redis 使用 LUA 脚本实现分布式的 CAS 操作#xff0c;可以参考#xff1a;基于 Redis 实现 CAS 操作最近使用 Redis 的时候有一个需求#xff0c;只有值发生变化的时候才更新#xff0c;如果要更新的值和现在的… Redis 使用 Lua 脚本进行原子操作Intro之前写过一篇文章也是 Redis 使用 LUA 脚本实现分布式的 CAS 操作可以参考基于 Redis 实现 CAS 操作最近使用 Redis 的时候有一个需求只有值发生变化的时候才更新如果要更新的值和现在的值是一样的就不用更新有点类似于 SET NX只是 SET NX 只有值不存在的时候才会 SET我的需求则是要检查要 SET 的值和 Redis 里的值如果不一样就 SET一样就直接返回Implement我实现了针对 String 和 Hash 的 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不一样则更新值然后返回 1StackExchange.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 Taskbool 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 Taskbool 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.GetRequiredServiceIConnectionMultiplexer().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.GetRequiredServiceIConnectionMultiplexer().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 脚本的时候如果要使用不等于的逻辑需要小心一些和其他语言不同需要使用 ~ 而非 ! 来表示不等Referenceshttps://github.com/WeihanLi/WeihanLi.Redis/blob/dev/src/WeihanLi.Redis/RedisExtensions.cshttps://github.com/WeihanLi/WeihanLi.Redis/blob/dev/test/WeihanLi.Redis.UnitTest/RedisExtensionsTest.cs基于 Redis 实现 CAS 操作