Redis的批处理命令-管道和Lua脚本

redis 管道,一次性的把多条命令发送到服务器端,节省网络开销

管道没有考虑事务和一致性的问题,如果pipeline有10条命令,其中地2-4条没有成功,其他的命令也会提交,只是把结果返回回来。

public class RedisPipeLine {
    public static void main(String[] args) {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(20);
        jedisPoolConfig.setMaxIdle(10);
        jedisPoolConfig.setMinIdle(5);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, "192.168.0.109",6379,3000,null);
        Jedis jedis = null;
        jedis = jedisPool.getResource();
        Pipeline piple = jedis.pipelined();
        for (int i = 0; i < 10; i++) {
            piple.incr("helloworld");
            piple.set("Allen"+i, Math.random()+"");
        }
        List list = piple.syncAndReturnAll();
        System.out.println(list);
    }
}

执行结果为:

[1, OK, 2, OK, 3, OK, 4, OK, 5, OK, 6, OK, 7, OK, 8, OK, 9, OK, 10, OK]

Process finished with exit code 0

在redis中查看执行的效果:

127.0.0.1:6379> keys Allen*
 1) "Allen"
 2) "Allen1"
 3) "Allen3"
 4) "Allen9"
 5) "Allen8"
 6) "Allen2"
 7) "Allen5"
 8) "Allen6"
 9) "Allen4"
10) "Allen7"
11) "Allen0"
12) "Allen-Lingling"
127.0.0.1:6379> get Allen5
"0.11796745342678339"
127.0.0.1:6379> 

Reids Lua 脚本,可以实现对批量命令的事务和原子操作

大量的使用lua脚本会影响redis的并行度。因为他把你写的script当作是一条命令执行,redis的命令执行单线程是顺序的。

分布式锁可以用lua脚本来实现。

Lua 脚本实例:

127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"
127.0.0.1:6379> 

在java中使用Lua脚本:

public class RedisLuaScript {
    public static void main(String[] args) {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(20);
        jedisPoolConfig.setMaxIdle(10);
        jedisPoolConfig.setMinIdle(5);
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, "192.168.0.109",6379,3000,null);
        Jedis jedis = null;
        jedis = jedisPool.getResource();
        jedis.set("product_Stock","15");
        String luaScript = "local count = redis.call('get',KEYS[1]) "+
                "local a = tonumber(count) "+
                "local b = tonumber(ARGV[1]) "+
                "if a>= b then " +
                "redis.call('set',KEYS[1],a-b) " +
               // "bb==0" +
                "return 1 " +
                "end " +
                "return 0 ";
        Object obj = jedis.eval(luaScript, Arrays.asList("product_Stock"),Arrays.asList("10"));
        System.out.println(obj);
    }
}

执行结果:

1

Process finished with exit code 0

在reids中查看库存结果:

127.0.0.1:6379> get product_Stock
"5"
127.0.0.1:6379> 

在script中加入解注释: "bb==0", 执行会报错,前面执行的减库存操作会回滚

Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: ERR Error compiling script (new function): user_script:1: '=' expected near '==' 
	at redis.clients.jedis.Protocol.processError(Protocol.java:132)
	at redis.clients.jedis.Protocol.process(Protocol.java:166)
	at redis.clients.jedis.Protocol.read(Protocol.java:220)
	at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:318)
	at redis.clients.jedis.Connection.getOne(Connection.java:296)
	at redis.clients.jedis.Jedis.getEvalResult(Jedis.java:2845)
	at redis.clients.jedis.Jedis.eval(Jedis.java:2779)
	at redis.clients.jedis.Jedis.eval(Jedis.java:2831)
	at allen.redis.RedisLuaScript.main(RedisLuaScript.java:33)

Process finished with exit code 1

在reids中查看库存结果:

127.0.0.1:6379> get product_Stock
"15"
127.0.0.1:6379> 

猜你喜欢

转载自blog.csdn.net/pengweismile/article/details/112495065
今日推荐