Redis Demo系列之(三)累加器

前言

累加器也是Redis场见的应用之一。值得注意的是Redis内的命令诸如incr等命令皆为原子操作。但是多命令组合而成的操作,为非原子操作。(如abc=incr(hello) get(hello) set(hello,abc)。此类操作需要使用MultiLua脚本保证Redis内操作的正确性。

本文相关代码,可在我的Github项目https://github.com/SeanYanxml/bigdata/tree/master/redis 目录下可以找到。
PS: (如果觉得项目不错,可以给我一个Star。)


Demos

/**
 * 记录Redis累加器。
 * 
 * */

public class RedisCounterDemo {

    // demo1: first not perfect
    public static Jedis jedis = new JedisPoolManager().getJedis();

    public static long INCR_END_COUNT = 10;
    public static long DECR_END_COUNT = 0;


    // 建议操作为 自增在前 操作在后。
    // 如果 操作在前 自增在后。会导致先执行操作,后判断。易导致数据总值变多。(即秒杀时,显示无库存。仍然认为有。造成损失。)
    public static boolean increase(String key){
        Long count = jedis.incr(key);
        if(count > INCR_END_COUNT){
            // do something
            return true;
        }
        return false;
    }

    public static boolean decrease(String key){
        Long count = jedis.decr(key);
        if(count > DECR_END_COUNT){
            // do something
            return true;
        }
        return false;
    }

    // 使用LUA 判断 
    // < LUA ERROR ? why? warn the type
    // have the string key first. 
    public static boolean execLua(String key){
        String script = "if tonumber(redis.call('get', KEYS[1])) > 100  then return redis.call('incr',KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(key), Collections.singletonList(key));
        if ((long)result > 0l) {
            // do something
            System.out.println("Hello");
            return true;
        }
        return false;
    }

    // 使用multi事务进行处理
    public static boolean execMulti(String key){
        return false;
    }

    public static void main(String[] args) {
        execLua("hello");
    }

}

//to number
//https://blog.csdn.net/u013916933/article/details/54962768

//https://stackoverflow.com/questions/21707021/lua-script-for-redis-which-sums-the-values-of-keys

//Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: ERR Error running script (call to f_1fb04376fc5dc524aeac5a008daa880db5104604): @user_script:1: user_script:1: attempt to compare number with nil 
//at redis.clients.jedis.Protocol.processError(Protocol.java:127)
//at redis.clients.jedis.Protocol.process(Protocol.java:161)
//at redis.clients.jedis.Protocol.read(Protocol.java:215)
//at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340)
//at redis.clients.jedis.Connection.getOne(Connection.java:322)
//at redis.clients.jedis.Jedis.getEvalResult(Jedis.java:2731)
//at redis.clients.jedis.Jedis.eval(Jedis.java:2671)
//at redis.clients.jedis.Jedis.eval(Jedis.java:2719)
//at com.yanxml.redis.demos.count.RedisCounterDemo.execLua(RedisCounterDemo.java:47)
//at com.yanxml.redis.demos.count.RedisCounterDemo.main(RedisCounterDemo.java:62)

Reference

[1]. redis 的incr/decr 的原子性是什么意思?
[2]. Redis研究(七)—如何判断set/get是否为原子操作
[3]. Redis 原子操作INCR
[4]. Redis 的操作为什么是的原子性的详解
[5]. redis如何实现原子性-LPOPRPUSH

你可能感兴趣的:(14.,大数据,-------14.4.,Redis,搬砖工具之Redis)