首页   >   代码编程

spring项目中利用redis + lua脚本简单实现分布式锁

在以往的单机系统中,为了做到线程安全,我们可以使用jdk提供给我们的synchronized关键字,也可以使用juc包下面的Lock,但是在现在流程的SOA服务中,显然就没法用了,毕竟服务器再也不是同一台了,你管得了自己,管不了别人。

有问题,那就会有解决方案,那就是分布式锁,通常利用Redis或者Zookeeper来实现,亦或者是利用三方框架来解决(redisson),今天来教大家用redis实现一个超级简单的分布式锁。

实现思路:setnx + lua

setNx:全名“set if not exist”,如果key不存在就set,如果key已存在就不set;

LUA:lua 脚本功能是Reids 2.6版本的最大亮点,通过内嵌对 Lua 环境的支持,Redis解决了长久以来不能高效地处理CAS(check-and-set)命令的缺点;

废话不多说,直接上代码了

/**
 * set lock in redis, setNx(SET if Not eXists)
 *
 * @param key    key
 * @param value  value
 * @param expire second
 * @return result(0 - false, 1 - true)
 */
public Long setLock(String key, String value, Integer expire) {
    return redisTemplateJDKSerialization.execute((RedisCallback<Long>) connection -> {

        StringRedisSerializer serializer = new StringRedisSerializer();
        StringBuilder lua = new StringBuilder();

        lua.append("local key = KEYS[1]");
        lua.append("local value = ARGV[1]");
        lua.append("local ok = redis.call('setnx', key, value)");

        if (expire != null && expire > 0) {
            lua.append("local ttl = ARGV[2]");
            lua.append("if ok == 1 then");
            lua.append("    redis.call('expire', key, ttl)");
            lua.append("end ");

            lua.append("return ok");

            return connection.eval(serializer.serialize(lua.toString()), ReturnType.INTEGER, 1, serializer.serialize(key), serializer.serialize(value), serializer.serialize(expire.toString()));
        }

        lua.append("return ok");

        return connection.eval(serializer.serialize(lua.toString()), ReturnType.INTEGER, 1, serializer.serialize(key), serializer.serialize(value));
    });
}

上述代码中,不用lua脚本也是可以的,但是用了lua脚本会有一个更好的效果:

1、多个命令一次性提交,减少开销;

2、将内部的所有命令封装为一个原子操作;

3、执行之后lua脚本会保存在redis中,可多次复用;

QQ群Ⅰ: 686430774 (已满)

QQ群Ⅱ: 718410762 (已满)

QQ群Ⅲ: 638620451 (已满)

QQ群Ⅳ: 474195684

如果文章有帮到你,可以考虑请博主喝杯咖啡!

分享到:

欢迎分享本文,转载请注明出处!

作者:不忘初心

发布时间:2019-03-18

永久地址:https://www.jiweichengzhu.com/article/a9cd5e0496e14000a8fef4a483f72c38

评论