`
zhaomengsen
  • 浏览: 209275 次
  • 性别: Icon_minigender_1
  • 来自: 河北
社区版块
存档分类
最新评论

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实现分布式锁,自旋式加锁,lua原子性解锁

    本文将深入探讨如何使用Redis实现分布式锁,以及如何利用自旋式加锁和Lua脚本实现原子性解锁。 首先,我们来理解分布式锁的基本概念。分布式锁是在多节点之间共享资源时,用于协调各个节点的访问控制机制。在分布式...

    redis分布式锁工具类

    现在很多项目单机版已经不满足了,分布式变得越受欢迎,同时也带来很多问题,分布式锁也变得没那么容易实现,分享一个redis分布式锁工具类,里面的加锁采用lua脚本(脚本比较简单,采用java代码实现,无须外部调用...

    springboot基于redis分布式锁

    不过,以上代码提供了一个基本的实现思路,帮助你理解如何在SpringBoot应用中使用Redis实现分布式锁。 通过提供的Word文档,你应该能够找到更详细的配置和使用步骤。记得在实际项目中根据具体需求进行调整,确保...

    用Redis实现分布式锁_redis_分布式_

    2. Redlock:由Redis作者Antirez提出的分布式锁算法,通过在多台Redis实例上实现锁来提高可用性和容错性。 综上所述,Redis是实现分布式锁的理想选择,其高效、原子性的特性使得在分布式系统中控制共享资源成为可能...

    基于 Redis 的分布式锁

    为了避免这种情况,可以使用Lua脚本来执行加锁和解锁的操作,因为Lua脚本在Redis中是原子性执行的,可以保证操作的原子性,从而保证锁的安全性。 4. 性能与可用性:使用Redis实现分布式锁,可以保证很高的性能,...

    redis分布式锁.zip

    在实际项目中,为了提高代码的健壮性和可维护性,通常会封装一个 Redis 分布式锁的客户端库,例如 Java 中的 Jedis 或 lettuce 库。这些库提供了更高级别的接口,隐藏了底层的 Redis 操作细节,使开发者更容易地使用...

    使用Redis实现分布式锁.zip

    分布式锁是一种在分布式系统中实现同步的技术,常用于限制对共享资源的并发访问。Redis,一个高性能的键值存储系统,被广泛用作实现分布式锁的工具,因其高可用性、快速响应和丰富的数据结构支持。本文将深入探讨...

    42_分布式锁是啥?对比下redis和zk两种分布式锁的优劣?.zip

    - 原生支持分布式,通过 Zookeeper 的临时节点实现锁,天然具备高可用性。 - 提供顺序性和原子性的操作,保证了锁的公平性。 - 支持watcher机制,可以实时监听锁状态变化,提升响应速度。 - **缺点:** - 实现...

    Redis从入门到精通(八)Redis实战(五)分布式锁误删与原子性问题、Redisson 测试项目代码

    通过以上分析,我们了解到Redis在分布式锁实现中的核心概念,以及如何利用Redisson来安全有效地管理分布式锁。在实际项目中,结合这些知识,你可以编写出可靠的代码,确保分布式系统的稳定运行。

    基于redis的分布式锁

    分布式锁是一种在分布式系统中实现锁机制的方法,它允许多个节点在共享资源上进行互斥访问。在微服务架构和大型互联网应用中,由于服务之间的数据一致性与并发控制至关重要,因此分布式锁扮演了非常关键的角色。...

    SpringBoot 使用 Redis 分布式锁解决并发问题.docx

    分布式锁的实现方式有多种,包括数据库乐观锁、基于Redis的分布式锁以及基于ZooKeeper的分布式锁。 本文主要关注基于Redis的分布式锁。Redis是一个内存数据存储系统,由于其快速响应和丰富的数据结构,常被用来实现...

    用注解实现redis分布式锁,防止短时间内重复请求

    1. **获取锁**:当方法被调用时,尝试在Redis中使用`SETNX`命令设置一个键(例如,以方法名作为键),如果键不存在则设置成功,表示获取锁成功;如果键已存在,则表示锁已被其他线程持有,当前线程需要等待。 2. **...

    Spring Boot+Redis 分布式锁:模拟抢单.pdf

    jedis提供了`del`方法来删除Redis中的key,但在分布式锁的上下文中,通常会使用一个带有条件判断的脚本,以确保安全性。 模拟抢单的场景是一个非常典型的分布式锁应用场景,可以帮助理解其在实际业务中的使用。在抢...

    Redis分布式锁代码示例

    以上就是在SpringBoot项目中使用Redis实现分布式锁的基本流程。需要注意的是,这只是一个基础示例,实际生产环境中可能需要考虑更多复杂情况,如锁的续期、超时处理以及异常情况下的解锁等。此外,Redis还提供了...

    springboot+分布式锁分布式锁

    以下将详细阐述如何在SpringBoot项目中利用Redis实现分布式锁。 1. **引入依赖**:首先,在SpringBoot项目中添加Redis和Spring Data Redis的相关依赖,这将允许我们通过Spring的数据访问抽象来操作Redis。 2. **...

    java+redis+lua实现重复提交操作拦截.zip

    - 在Java部分,可能会使用try-catch-finally结构,确保即使在执行过程中发生异常,也能正确释放Redis锁。 通过以上方式,项目"java+redis+lua实现重复提交操作拦截"创建了一个健壮的系统,能够有效防止在网络延迟...

    Redission分布式锁-本地单机Redis实战-springboot-redis-lock.zip

    - 实现分布式锁:在业务代码中使用RedissonClient创建RLock实例,调用lock()和unlock()方法。 8. **最佳实践**: - 锁超时机制:为防止死锁,设置合理的锁超时时间。 - 异常处理:捕获并处理可能出现的异常,如...

    分布式Redis原子操作示例

    分布式Redis原子操作示例,近期项目中遇到分布式项目中多节点大并发操作redis同一个key。此案例利用java调用LUA脚本实现redis操作的原子性。分享出来大家参考。

Global site tag (gtag.js) - Google Analytics