多线程场景 Redis中List队列 LPush 和 remove 是否线程安全?

多线程场景 Redis中List队列 LPush 和 remove 是否线程安全?

1.业务场景如下

作者在rabbitmq消息队列场景中,实现了一个监控消息数据全部入库的程序,每个生产者发送消息的同时,插入一个keyredis 中的 list 队列中,消费成功之后,再从这个队列中删除该 key 值。

通过最后判断 redis 中的 list 队列是否有数据,来判断消费是否成功。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RxNKUlN0-1584710239192)()]

其中 生产者 是并发场景,消费者 也是集群的并发消费。

2.猜想

从官网可知redis 服务端是单线程实现的,命令操作都是原子;所以虽然客户端是多线程访问,但是服务端接收之后,还是会使用单线程进行操作,所以应该是线程安全的,不会出现数据不一致的情况。

3.验证

3.1环境

  • springboot2.0.4
    • springmvc

3.2生产者代码

    @GetMapping("/testRedisConcurrentLPush")
    public @ResponseBody
    String testRedisConcurrentLPush(HttpServletRequest request, Integer count) {
        for (int i = 0; i < count; i++) {
            new Thread(() -> {
                for (int j = 0; j < 5; j++) {
                    redisUtil.lSet("test_msg_list_8a8781fe70f6f5cf0170f6f5cf970000",
                            "key_msg");
                    redisUtil.incr("test_msg_list_count", 1);
                }
            }).start();
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return "成功";
    }

3.3消费者代码

@GetMapping("/testRedisConcurrentLRemove")
    public @ResponseBody
    String testRedisConcurrentLRemove(HttpServletRequest request, Integer count) {
        for (int i = 0; i < count; i++) {
            new Thread(() -> {
                for (int j = 0; j < 5; j++) {
                    redisUtil.lRemove("test_msg_list_8a8781fe70f6f5cf0170f6f5cf970000",
                            1, "key_msg");
                    redisUtil.decr("test_msg_list_count", 1);
                }
            }).start();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return "成功";
    }

4.测试

开两个 tab窗口 浏览器分别输入

  • 生产者多线程循环添加
http://127.0.0.1:8098/democratic/testRedisConcurrentLPush?count=20
  • 消费者多线程循环删除
http://127.0.0.1:8098/democratic/testRedisConcurrentLRemove?count=20

4.1测试结果:

  • test_msg_list_count 计算为 0

  • 队列数据为0,元素全部删除之后,队列消失

如果 生产者 count 设置20,消费者设置19

  • test_msg_list_count 计算为 5
  • 队列数据为5条

多次测试结果均符合预期,即线程安全。

如果有更加正确的验证方式 或者 本文结论证实错误,欢迎指正。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值