1.lua脚本(集成实现了乐观锁,hmset ,expire等)

local key=KEYS[1];
local oldVerion=tonumber(ARGV[1]);
local seconds=ARGV[2];
local fieldLen = table.getn(ARGV)-2;
local idx=1;
local argvIdx=1;
local version = redis.call('HINCRBY',key,'version','0');
if(version~=oldVerion) then
return 0;
end
for idx=1,fieldLen,2 do
argvIdx=idx+2;
redis.call('HSet',key,ARGV[argvIdx],ARGV[argvIdx+1]);
end
version =redis.call('HINCRBY',key,'version','1');
redis.call('EXPIRE',key,seconds);
return version;

2.eval直接调用测试

传入参数

keysCount: 1

key: key11

version: 0

ttl: 6000

field1: icbc

field2:wh

eval "local key=KEYS[1];local oldVerion=tonumber(ARGV[1]);local seconds=ARGV[2];local fieldLen = table.getn(ARGV)-2;local idx=1;local argvIdx=1;local version = redis.call('HINCRBY',key,'version','0');if(version~=oldVerion) then return 0; end for idx=1,fieldLen,2 do argvIdx=(idx-1)+1+2; redis.call('HSet',key,ARGV[argvIdx],ARGV[argvIdx+1]); end version =redis.call('HINCRBY',key,'version','1');redis.call('EXPIRE',key,seconds);return version;"  1 key11 0 6000 field1 icbc field2 wh

3.java代码

 @Autowired
private StringRedisTemplate redisTemplate; private static final String LUA_SCRIPT_HMSETBYVERSION = "local key=KEYS[1];\n" +
"local oldVerion=tonumber(ARGV[1]);\n" +
"local seconds=ARGV[2];\n" +
"local fieldLen = table.getn(ARGV)-2;\n" +
"local idx=1;\n" +
"local argvIdx=1;\n" +
"local version = redis.call('HINCRBY',key,'version','0');\n" +
"if(version~=oldVerion) then\n" +
"\treturn 0;\n" +
"end\n" +
"for idx=1,fieldLen,2 do \n" +
"argvIdx=idx+2;\n" +
"redis.call('HSet',key,ARGV[argvIdx],ARGV[argvIdx+1]);\n" +
"end \n" +
"version =redis.call('HINCRBY',key,'version','1');\n" +
"redis.call('EXPIRE',key,seconds);\n" +
"return version;";
private static final String LUA_SCRIPT_HMSETBYVERSION_SHA1 = SHA1.encode(LUA_SCRIPT_HMSETBYVERSION);
public long compareAndHMset(String key, int version, Map<String, String> values, int seconds) {
if (CollectionUtils.isEmpty(values)) {
return 0;
} List<String> keys = Collections.singletonList(key);
List<String> argvs = new ArrayList<>(values.size() * 3); argvs.add(Integer.toString(version));
argvs.add(Integer.toString(seconds)); for (Map.Entry<String, String> item : values.entrySet()) {
argvs.add(item.getKey());
argvs.add(Strings.isNullOrEmpty(item.getValue()) ? "" : item.getValue());
} Long result = redisTemplate.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
Object nativeConnection = connection.getNativeConnection();
// 集群模式和单点模式虽然执行脚本的方法一样,但是没有共同的接口,所以只能分开执行
// 集群
if (nativeConnection instanceof JedisCluster) {
try {
return (Long) ((JedisCluster) nativeConnection).evalsha(LUA_SCRIPT_HMSETBYVERSION_SHA1,
keys,
argvs);
} catch (redis.clients.jedis.exceptions.JedisNoScriptException ex) {
return (Long) ((JedisCluster) nativeConnection).eval(LUA_SCRIPT_HMSETBYVERSION, keys, argvs);
} catch (Exception ex) {
return 0L;
}
} else {
// 单点 或 哨兵
try {
return (Long) ((Jedis) nativeConnection).evalsha(LUA_SCRIPT_HMSETBYVERSION_SHA1,
keys,
argvs);
} catch (redis.clients.jedis.exceptions.JedisNoScriptException ex) {
return (Long) ((Jedis) nativeConnection).eval(LUA_SCRIPT_HMSETBYVERSION, keys, argvs);
} catch (Exception ex) {
return 0L;
}
}
}
}); return result;
}

4.调用

return 0 < compareAndHMset("hashkey11",
1,
ImmutableMap.of("field1", "icbc2"),
6000
);

redis的hmset乐观锁的实现的更多相关文章

  1. php+redis 学习 三 乐观锁

    <?php header('content-type:text/html;chaeset=utf-8'); /** * redis实战 * * 实现乐观锁机制 * * @example php ...

  2. redis事务和乐观锁

    1 MULTI/EXEC 执行本事务. MULTI set foo bar get foo set foo hello EXEC 在EXEC执行前,三条命令都放入队列中,然后EXEC触发执行.没有回滚 ...

  3. Redis分布式锁----乐观锁的实现,以秒杀系统为例

    本文使用redis来实现乐观锁,并以秒杀系统为实例来讲解整个过程. 乐观锁      大多数是基于数据版本(version)的记录机制实现的.即为数据增加一个版本标识,在基于数据库表的版本解决方案中, ...

  4. 五分钟学会悲观乐观锁-java vs mysql vs redis三种实现

    1 悲观锁乐观锁简介 乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果 ...

  5. redis中使用 check-and-set 操作实现乐观锁

    WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为. 被 WATCH 的键会被监视,并会发觉这些键是否被改动过了. 如果有至少一个被监视的键在 EXEC 执行之前 ...

  6. redis 乐观锁实践秒杀

    需求:有一个标(理解成抢红包也行,accountBalance预赋值1000元),大家可以抢购,每个用户抢购成功后,更新最后标的总数,在并发情况下,使用redis的乐观锁,保证更新标总值正确性,先往r ...

  7. 基于redis的乐观锁实践

    redis真是一个分布式应用场景下的好东西,对于我们的应用设计,功劳大大的! 今天要研究的是基于redis的事务机制以及watch指令(CAS)实现乐观锁的过程. 所谓乐观锁,就是利用版本号比较机制, ...

  8. redis的高级事务CAS(乐观锁)

    Optimistic locking using check-and-set(乐观锁) 乐观锁介绍:watch指令在redis事物中提供了CAS的行为.为了检测被watch的keys在是否有多个cli ...

  9. redis乐观锁(适用于秒杀系统)

    redis事务中的WATCH命令和基于CAS的乐观锁  在Redis的事务中,WATCH命令可用于提供CAS(check-and-set)功能.假设我们通过WATCH命令在事务执行之前监控了多个Key ...

随机推荐

  1. 前端每日实战:25# 视频演示如何用纯 CSS 创作一个慧星拖尾效果的 loader 动画

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/YLRLaM 可交互视频教程 此视频 ...

  2. export default{} 和 new Vue()都是什么意思

    在生成.导出.导入.使用 Vue 组件的时候,有些新手就会常常被位于不同文件的 new Vue() 和 export default{} 搞得晕头转向.它们含义到底是什么,又有什么异同呢? 首先,Vu ...

  3. /usr,/usr/local/ 还是 /opt 目录区别

    Linux 的软件安装目录是也是有讲究的,理解这一点,在对系统管理是有益的 /us(Unix Software Resource)r:系统级的目录,可以理解为C:/Windows/, /usr/lib ...

  4. VSCode必备插件

    通用组件 1.汉化插件 https://marketplace.visualstudio.com/items?itemName=MS-CEINTL.vscode-language-pack-zh-ha ...

  5. Python3解leetcode Average of Levels in Binary Tree

    问题描述: Given a non-empty binary tree, return the average value of the nodes on each level in the form ...

  6. Cluster基础(二):ipvsadm命令用法、部署LVS-NAT集群、部署LVS-DR集群

    一.ipvsadm命令用法 目标: 准备一台Linux服务器,安装ipvsadm软件包,练习使用ipvsadm命令,实现如下功能: 使用命令添加基于TCP一些的集群服务 在集群中添加若干台后端真实服务 ...

  7. MySQL:MySQL日期数据类型、MySQL时间类型使用总结

    MySQL 日期类型:日期格式.所占存储空间.日期范围 比较. 日期类型        存储空间      日期格式                日期范围------------  -------- ...

  8. 第一周训练 | STL和基本数据结构

    A - 圆桌问题: HDU - 4841 #include<iostream> #include<vector> #include<stdio.h> #includ ...

  9. 关于Calendar和Reminder(日历和提醒)编程指南

    Event Kit框架使你能访问用户的Calendar.app和Reminders.app信息.虽然这是两个不同的app,但是他们使用相同的框架处理数据.类似地,存储这些数据的数据库,被称为日历数据库 ...

  10. iOS逆向一个APP指令集

    一.脱壳获取.app文件 1.查询壳有没加密 otool -l  mac-o文件 | grep crypt 2.Clutch -i Clutch -d  num 3.脱壳后的位置 /private/v ...