redis中使用java脚本实现分布式锁
转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/115.html?1455860390
edis被大量用在分布式的环境中,自然而然分布式环境下的锁如何解决,立马成为一个问题。例如我们当前的手游项目,服务器端是按业务模块划分服务器的,有应用服,战斗服等,但是这两个vm都有可能同时改变玩家的属性,这如果在同一个vm下面,就很容易加锁,但如果在分布式环境下就没那么容易了,当然利用redis现有的功能也有解决办法,比如redis的脚本。
redis在2.6以后的版本中增加了Lua脚本的功能,可以通过eval命令,直接在RedisServer环境中执行Lua脚本,并且可以在Lua脚本中调用Redis命令。
使用脚本的好处:
1.减少网络开销:可以把一些要批量处理的功能,发在一个脚本里面执行,减少客户端和redis的交互次数
2.原子操作:这主要就是我们在这边主要利用的功能,在分布式环境下保证数据的原子性。
3.复用:客户端发送的脚本会永久的存储在redis中,这就意味着其他客户端可以复用这一脚本而不需要使用代码完成同样的逻辑。
下面先看一段lua脚本:
代码如下:
local food=redis.call('hget',KEYS[1],'food');
food=food+ARGV[1];
redis.call('hset',KEYS[1],'food',food);
local diamond=redis.call('hget',KEYS[1],'diamond');
diamond=diamond+ARGV[2];
redis.call('hset',KEYS[1],'diamond',diamond);
注:redis.call是我们在脚本中调用redis命令,KEYS和ARGV2个数组,分别是键和参数,下标都是从1开始的,不是0。
这段脚本的功能是取出 KEYS指定的玩家food(粮草)和diamond(玉石),然后就行修改,最后保存在redis中,脚本的执行,保证了整个操作的原子性。
下面我们用java代码来看看具体的实现过程
代码如下:
Jedis jedis = new Jedis("192.168.128.128", 6379);
// 1.初始玩家数据到redis中
GamePlayer player = new GamePlayer();
player.setId(1001);
player.setName("ksfzhaohui");
player.setFood(100);
player.setDiamond(100);
Map<String, String> beanMap = BeanUtil.warp(player);// 将对象转换成map
String beanKey = getRedisBeanKey(player.getClass(), player.getId());
System.out.println("key:" + beanKey);
jedis.hmset(beanKey, beanMap);// 将玩家数据保存到redis中
首先模拟了一个玩家将玩家信息保存在redis中,这边的Id随便写了一个,正常的情况下都是通过redis的命令incr生成一个id
结果: 
代码如下:
String script = "local food=redis.call('hget',KEYS[1],'food');"
+ "food=food+ARGV[1];"
+ "redis.call('hset',KEYS[1],'food',food);"
+ "local diamond=redis.call('hget',KEYS[1],'diamond');"
+ "diamond=diamond+ARGV[2];"
+ "redis.call('hset',KEYS[1],'diamond',diamond);";
List<String> keys = new ArrayList<String>();
keys.add(beanKey);
List<String> args = new ArrayList<String>();
args.add("100");
args.add("100");
// 3.执行脚本
jedis.eval(script, keys, args);
指定键和参考,执行脚本,结果:

BeanUtil代码:
代码如下:
public class BeanUtil {
private static Logger logger = Logger.getLogger(BeanUtil.class);
private static final String CLASS = "class";
/**
* 将指定的对象数据封装成map
*
* @param bean
* 对象数据
* @return
*/
@SuppressWarnings("all")
public static Map<String, String> warp(Object bean) {
Map<String, String> propertyMap = new HashMap<String, String>();
try {
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass())
.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : ps) {
String propertyName = propertyDescriptor.getName();
if (propertyName != null && !propertyName.equals(CLASS)) {
Method getter = propertyDescriptor.getReadMethod();
if (getter != null) {
propertyMap.put(propertyName,
String.valueOf(getter.invoke(bean, null)));
}
}
}
} catch (Exception e) {
logger.error(e);
}
return propertyMap;
}
}
redis中使用java脚本实现分布式锁的更多相关文章
- redis集群+JedisCluster+lua脚本实现分布式锁(转)
https://blog.csdn.net/qq_20597727/article/details/85235602 在这片文章中,使用Jedis clien进行lua脚本的相关操作,同时也使用一部分 ...
- 【spring boot】【redis】spring boot基于redis的LUA脚本 实现分布式锁
spring boot基于redis的LUA脚本 实现分布式锁[都是基于redis单点下] 一.spring boot 1.5.X 基于redis 的 lua脚本实现分布式锁 1.pom.xml &l ...
- 在redis中使用lua脚本
在实际工作过程中,可以使用lua脚本来解决一些需要保证原子性的问题,而且lua脚本可以缓存在redis服务器上,势必会增加性能. 不过lua也会有很多限制,在使用的时候要注意. 在Redis中执行Lu ...
- 新姿势!Redis中调用Lua脚本以实现原子性操作
背景:有一服务提供者Leader,有多个消息订阅者Workers.Leader是一个排队程序,维护了一个用户队列,当某个资源空闲下来并被分配至队列中的用户时,Leader会向订阅者推送消息(消息带有唯 ...
- 【JSP】JSP中的Java脚本
前言 现代Web开发中,在JSP中嵌入Java脚本不是推荐的做法,因为这样 不利于代码的维护.有很多好的,替代的方法避免在JSP中写Java脚本.本文仅做为JSP体系技术的一个了解. 类成员定 ...
- redis中使用lua脚本
lua脚本 Lua是一个高效的轻量级脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能 使用脚本的好处 1.减少网络开销,在Lua脚 ...
- Redis中的原子操作(2)-redis中使用Lua脚本保证命令原子性
Redis 如何应对并发访问 使用 Lua 脚本 Redis 中如何使用 Lua 脚本 EVAL EVALSHA SCRIPT 命令 SCRIPT LOAD SCRIPT EXISTS SCRIPT ...
- Redis学习笔记(三)使用Lua脚本实现分布式锁
Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行. 使用Lua脚本的好处如下: 1.减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放 ...
- Redis中的Java分布式缓存
为什么在分布式Java应用程序中使用缓存?今天学习了两节优锐课讲解分布式缓存的内容,收获颇多,分享给大家. 在提高应用程序的速度和性能时,每毫秒都是至关重要的.例如,根据Google的一项研究,如果网 ...
随机推荐
- jQuery选择器引擎和Sizzle介绍
一.前言 Sizzle原来是jQuery里面的选择器引擎,后来逐渐独立出来,成为一个独立的模块,可以自由地引入到其他类库中.我曾经将其作为YUI3里面的一个module,用起来畅通无阻,没有任何障碍. ...
- EasyUI detailview 使用心得
view: detailview, detailFormatter: function (rowIndex, rowData) { return "<div class='easyui ...
- 对偶理论、拉格朗日对偶问题、LP线性规划对偶性质
Lagrange 对偶问题 定义其的对偶问题: Lagrange函数 考虑线性规划问题 若取集合约束D={x|x≥0},则该线性规划问题的Lagrange函数为 线性规划的对偶问题为: 对偶定理原问题 ...
- sky简介
sky简介 sky是一种构建高性能.跨平台手机APP的新的途径.更值得关注的是,sky是一种渲染引擎.脚本引擎.一个框架和一系列的材料设计模式的窗体组件.sky是当前以及未来手机APP的一种优化手段. ...
- [转]Java学习日记之 volatile
用在多线程,同步变量. 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B.只在某些动作时才进行A和B的同步.因此存在A和B不一致的情况.volatile就是用来 ...
- OPC的理解Open Packaging Conventions
Open Packaging Conventions (OPC) 博客地址:www.cnblogs.com/icmzn OPC是一个文件容器技术.被微软创建,用来存储XML或者非XML文件结合起来的规 ...
- XAF How to show custom forms and controls in XAF (Example)
XAF How to show custom forms and controls in XAF (Example) https://www.devexpress.com/Support/Center ...
- maven pox配置
Maven教程初级篇02:pom.xml配置初步 1. 创建项目并更改项目基本配置信息 在命令行下运行如下命令创建一个项目: 1 mvn archetype:create -DgroupId=net. ...
- 定时自动关闭messagebox
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- StoryBoard 简单使用
StoryBoard简单使用 故事版(storyboard)是一种简洁的图形界面,程序员可以采取拖的形式搭建一个界面,现在使用的xcode默认都会创建一个main.storyboard,作为app的入 ...