fruit这个key的值为100

image-20230608161917962

开1000线程去抢

image-20230608162922219

直接成负数了,👇未利用lua脚本

image-20230608163006344

1
2
3
4
5
6
7
8
9
10
@GetMapping("/nosafe")
public String exhaustFruit() {
ValueOperations operations = redisTemplate.opsForValue();
Integer integer = Integer.valueOf(String.valueOf(operations.get("fruit")));
if (integer < 1) {
return "被抢完了";
}
operations.increment("fruit", -1);
return "获得一个水果";
}

利用lua脚本来保证redis的原子性👇

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String lua = "local current = redis.call('get', 'fruit')\n" +
"if tonumber(current) > 0 then\n" +
" redis.call('decr', 'fruit')\n" +
" return 1\n" +
"end\n" +
"return 0\n";

@GetMapping("/safe")
public String exhaustFruitWithLuaScript() {
RedisScript longDefaultRedisScript = new DefaultRedisScript(lua, Long.class);
Integer execute = Integer.valueOf(String.valueOf(redisTemplate.execute(longDefaultRedisScript, null, "1")));
if (execute == 1) {
return "获得一个水果";
}
return "被抢完了";
}

重置下fruit的值

image-20230608163314917

2000个线程来抢

image-20230608163445024

查看结果树

image-20230608163523016

Redis中fruit结果正确

image-20230608163613585

再试一次

image-20230608163651392

结果

image-20230608163742562