Redis Demo系列之(三)累加器

释放双眼,带上耳机,听听看~!

前言

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

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


Demos


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
1/**
2 * 记录Redis累加器。
3 *
4 * */
5
6public class RedisCounterDemo {
7
8    // demo1: first not perfect
9    public static Jedis jedis = new JedisPoolManager().getJedis();
10
11    public static long INCR_END_COUNT = 10;
12    public static long DECR_END_COUNT = 0;
13
14
15    // 建议操作为 自增在前 操作在后。
16    // 如果 操作在前 自增在后。会导致先执行操作,后判断。易导致数据总值变多。(即秒杀时,显示无库存。仍然认为有。造成损失。)
17    public static boolean increase(String key){
18        Long count = jedis.incr(key);
19        if(count > INCR_END_COUNT){
20            // do something
21            return true;
22        }
23        return false;
24    }
25
26    public static boolean decrease(String key){
27        Long count = jedis.decr(key);
28        if(count > DECR_END_COUNT){
29            // do something
30            return true;
31        }
32        return false;
33    }
34
35    // 使用LUA 判断
36    // < LUA ERROR ? why? warn the type
37    // have the string key first.
38    public static boolean execLua(String key){
39        String script = "if tonumber(redis.call('get', KEYS[1])) > 100  then return redis.call('incr',KEYS[1]) else return 0 end";
40        Object result = jedis.eval(script, Collections.singletonList(key), Collections.singletonList(key));
41        if ((long)result > 0l) {
42            // do something
43            System.out.println("Hello");
44            return true;
45        }
46        return false;
47    }
48
49    // 使用multi事务进行处理
50    public static boolean execMulti(String key){
51        return false;
52    }
53
54    public static void main(String[] args) {
55        execLua("hello");
56    }
57
58}
59
60//to number
61//https://blog.csdn.net/u013916933/article/details/54962768
62
63//https://stackoverflow.com/questions/21707021/lua-script-for-redis-which-sums-the-values-of-keys
64
65//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
66//at redis.clients.jedis.Protocol.processError(Protocol.java:127)
67//at redis.clients.jedis.Protocol.process(Protocol.java:161)
68//at redis.clients.jedis.Protocol.read(Protocol.java:215)
69//at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340)
70//at redis.clients.jedis.Connection.getOne(Connection.java:322)
71//at redis.clients.jedis.Jedis.getEvalResult(Jedis.java:2731)
72//at redis.clients.jedis.Jedis.eval(Jedis.java:2671)
73//at redis.clients.jedis.Jedis.eval(Jedis.java:2719)
74//at com.yanxml.redis.demos.count.RedisCounterDemo.execLua(RedisCounterDemo.java:47)
75//at com.yanxml.redis.demos.count.RedisCounterDemo.main(RedisCounterDemo.java:62)
76
77

Reference

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

给TA打赏
共{{data.count}}人
人已打赏
安全运维

OpenSSH-8.7p1离线升级修复安全漏洞

2021-10-23 10:13:25

安全运维

设计模式的设计原则

2021-12-12 17:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索