• 分布式锁


    1.前沿

        上几篇文章分别介绍了数据库里面的锁及java里面的锁,大概了解到锁就是为了数据的一致性,防止出现数据错乱,但是单机环境下用java的syn和lock来实现多线程异步执行的同步性,能

    有效解决高并发的问题,但是实际中大公司往往为了实现系统的高可用,会选择分布式集群部署。因此如果单纯的靠syn和lock已经满足不了要求。

    2.业务场景描述

        业务场景1:譬如要实现一个排期的业务,需要往数据库表里的数据每天的0点执行插入一条数据,这时会用到定时任务,spring目前已经很好的集成了quartz,可以很方便的使用注解的形式来实现一个定时

    任务,在单机环境下,很快就满足了任务,但是发现部署到生产环境,采用的是nginx集群部署分配,这时,两台机器在某一刻的时候,会同时执行定时任务代码,这时就出现了一个问题,任务重复执行,导致

    业务出错,首先发布的项目在两台机器上,项目代码是一致的,那如何保证只有一台执行了。

       解决办法1:在执行业务代码的时候,可以加入一张log表,在执行任务之前先判断下,是否有当天的log,一旦发现有了,就不执行,貌似能解决问题,但无法保证线程的执行顺序,可能还是会出现执行2次代码。

       解决办法2:既然只要保证一台机器执行,是否可以指定其中的一台机器执行,譬如我可以判断部署机器的ip地址来执行,当然也有问题,譬如这台机器刚好挂了,那某一天的任务可能就不执行了。

       解决办法3:直接把定时任务抽出一台机器,不管业务里面的代码逻辑,只管执行,可以将A和B的执行controller抽出,由定时任务工程C通过http请求调用nginx随机转发,返回一个状态码来判断是否成功。当然这里涉及部署的定时任务工程C也是单机部署,如果是集群部署,同样存在这个问题,因此需要引入分布式锁来解决问题。

          业务场景2:要实现B2C网站一个支付的功能,卖家在平台出售商品,平台先临时保管资金,等卖家冻结资金释放之后,才能进行提现。这里首先考虑的是支付时的并发问题,即假设有好几个人同时在购买

    某一个店铺下的商品,这时如果多线程访问支付,可能出现脏读,譬如资金余额原本是20,A买了30,B买了40,这时按理应该是20+30+40=90,但最终拿到的结果可能是50或60.另外假设卖家在卖货收入的同时,刚刚他准备去提现,这不能保证是一个有序进行的,很容易出现脏读。   因此也需要引入一个支付锁,来锁定账户来保证账户的一致性和安全性。

    3.实现分布式锁的方案

    1.基于数据库实现分布式锁

    2.基于缓存(redis)实现分布式锁

    3.基于Zookeeper实现分布式锁

    4.分布式 局限性

    分布式场景中的数据一致性问题一直是一个比较重要的话题。分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项。”所以,很多系统在设计之初就要对这三者做出取舍。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可

  • 相关阅读:
    B树与B+详解
    处理器拦截器(HandlerInterceptor)详解(转)
    过滤器(Filter)与拦截器(Interceptor )区别
    Redis和MemCache静态Map做缓存区别
    Ubuntu16.10下mysql5.7的安装及远程访问配置
    windows中mysql5.7保存emoji表情
    基于Quartz.NET 实现可中断的任务(转)
    Ubuntu16.10下使用VSCode开发.netcore
    ubuntu16.10 安装ibus中文输入法
    ubuntu 中安装mysql 使用默认用户密码登录
  • 原文地址:https://www.cnblogs.com/edison20161121/p/10294851.html
Copyright © 2020-2023  润新知