zoukankan      html  css  js  c++  java
  • 深入理解Spring Redis的使用 (九)、通过Redis 实现 分布式锁 的 BUG,以及和数据库加锁的性能测试

    在多节点的项目中,经常要涉及到某些方法加锁的控制。而这个时候,简单易用的synchronized已经不能满足多节点的部署结构。

    之前在项目中,用的比较多的是数据库的更新锁:for udpate。但是这个有个缺点,就是对于本来就容易出现瓶颈的数据库,造成了更大的压力。同时,如果是锁表的语句,同时表数据量特别大,基本服务器直接宕机了。

    所以,决定绕开数据库,直接使用Redis来实现分布式锁。查了下资料,找到一些文章,思路都一致:

    http://www.jeffkit.info/2011/07/1000/

    http://my.oschina.net/u/1995545/blog/366381

    于是参考文章,通过Spring aop注解方法来实现对方法的多节点加锁。

    之前的文章给了实现的代码。并没有什么难度,注解+AOP。

    但是今天做压力测试的时候,发现这个大有问题。

    测试环境:

    1000线程,每个线程执行1次。(这种更接近真实的tomcat环境)

    sleep时间和执行时间:

    * 20ms 约等于cpu线程切换时间,59998
    * 50ms 43177
    * 100ms 20555
    * 150ms 7014
    * 200ms 2970 性能尚可

    但是,如果设置200ms,有可能有些线程,从最开始阻塞不断sleep,到最后全部结束了,才拿到锁。如果程序不结束,那么该线程就一直堵死,无法预料究竟多久能拿到锁。如果去设置等待多久超时断开,那么频繁的失败,对于用户肯定是无法接受的。

    于是又测试数据库的锁

    一张70W数据的表,

    通过pk行级锁,执行时间1163(需要被锁数据存在的情况下,才能加上对应的锁),而且如果是每个线程都是各自的数据行的话,相互不阻塞会更快.(SSD固态硬盘。。。)

    通过其他列表锁,一秒执行一次的感觉,直接卡死,停止测试

    所以,通过sleep来等待,并发高的情况下,将会导致某些线程失控。

    但是wait notify,又是针对单节点下才能使用。

    也可以做到最细粒度,然后再用redis加锁,这样,降低线程堵死的可能性。

    总结:

    要么使用阻塞的方式来调度线程,

    要么就实现一个可以在分布式环境下的类似NIO的reactor模式来进行调度。

    保证先入先出,即使有些慢的状态下,不至于先来的反而堵死,造成差的体验。

    或者为每个请求设置超时时间,超时抛出异常。

     

  • 相关阅读:
    python 中给文件加锁——fcntl模块
    python生成二维码
    uwsgi常用配置
    php curl实现get和post请求
    python __enter__ 与 __exit__的作用,以及与 with 语句的关系
    python文件操作总结
    Python时间,日期,时间戳之间转换
    Python random模块(获取随机数)
    wigs的理解和应用
    shiro中接入单点登录功能
  • 原文地址:https://www.cnblogs.com/luochengqiuse/p/4802989.html
Copyright © 2011-2022 走看看