美文网首页
大厂 分布式锁

大厂 分布式锁

作者: 茶艺瑶 | 来源:发表于2020-01-31 17:32 被阅读0次

在单机环境下,有个秒杀商品的活动,在短时间内,服务器压力和流量会陡然上升。这个就会存在并发的问题。想要解决并发需要解决以下问题

1、提高系统吞吐率也就是qps 每秒处理的请求书
2、避免商品在高并发的情况下,出现资源争抢导致的超买超买问题

解决问题一:采用内存型数据库提高系统的qps
解决问题二:就要用到经常会遇到的锁,例如MySQL 有读锁、写锁、排他锁、悲观锁、乐观锁。不过这里只讨论redis来实现锁

在Redis中我们用的最多的是Set方法,可是在Redis中有这么一个方法setnx来做锁,Redis的setnx指令,设置一个键值对,当且仅当键不存在的时候,才能设置成功。

这里用的是PHP的版本做列子

我们先看看如何设置一把简单的锁

$redis = new Redis();
$redis->connect('127.0.0.1', 6379); //连接Redis

$expire = 10;//有效期10秒
$key = 'lock';//key
$value = time() + $expire;//锁的值 = Unix时间戳 + 锁的有效期
$lock = $redis->setnx($key, $value,array('nx', 'ex' => 10));
//判断是否上锁成功,成功则执行下步操作
if(empty($lock))
{
   return "error";
}
//这里写我们的操作逻辑

当然这样做是不科学的,因为有一定并发概念的同学都知道,在高并发场景下。

1、假如有10000 个请求访问了redis 不存在的键,这样请求就是指接到了MySQL数据,造成CPU短时间内达到100%甚至宕机。这样场景俗称缓存击穿造成的缓存雪崩。
2、 假如CPU过高或者网络延时问题,造成锁没有被删除掉或者缓存键过期没有被回收的情况,就会形成死锁。

    try{
         $expire = 10;//有效期10秒
         $key = 'lock';//key
         $value = time() + $expire;//锁的值 = Unix时间戳 + 锁的有效期
         $lock = $redis->setnx($key, $value,array('nx', 'ex' => 10));
          if(empty($lock))
          {
              return "error";
          }
    }finally {
           //等程序运行完后 释放锁
           $redis->del($key);
    }

到了已经可以满足一定并发下的处理可,可以在更高的情况下面,会出现解锁的情况还是会出现解锁的人不是同一个人。

所以redis社区也有人建议使用UUID

try{
        $expire = 10;//有效期10秒
        $key = 'lock';//key
        $value = uuid();//锁的值 = Unix时间戳 + 锁的有效期
        $lock = $redis->setnx($key, $value,array('nx', 'ex' => 10));
         if(empty($lock))
         {
             return "error";
         }
   }finally {
          //等程序运行完后 释放锁,通过uuid判断是不是这个线程,如果是那就是当前进程可是释放锁
          if($redis->get($key) == $value){
              $redis->del($key);
          }
   }

这样处理已经可以在中小型企业可以完全够用了,可是如果你到了阿里,京东这些大规模的企业里面,这样写还是存在问题的,我们设置锁的有效时间是10秒,在这么大并发的情况下,我们的程序有可能运行时间超过三秒。

那么这样的情况下面,我们需要怎么处理呢?
一般的做法是加锁成功后,马上开一个线程,让他自己续命。时间有效时间为1/3

#让锁自动续命
while($redis->get($key)){
       $lock = $redis->setnx($key, $value,array('nx', 'ex' => 10));
       sleep(3);
}

到了这里一般的中大型企业已经购用了,因为Redis已经可以处理几w并发。利用并发redis把并发变成串行执行。

可是还是会遇到一些问题,因为redis肯定不是单机的,因为单机的redis只能处理8w的并发,这个时候就会出现一个问题,就是你的锁写在A服务器中,可是A服务器还没来得及时处理同步的时候,它就已经挂了,这里就会遇到一个大厂会平凡问的问题,你是如何处理这一块的内容。

简单点书就是主重架构出现锁失效的问题。

我们可是再加锁的时候


image.png

往每个节点添加锁,超过一半的时候,认为成功,当然也会出现一个问题,就是加锁没有一半以上,就认为失败,出现锁回滚问题。一年偶尔出现一两次而已,当然也不用怕,有运维在的大企业,有人工处理的。

这个时候大多数的运维或者架构师会选择性能比redis低的分布式锁。Zookeeper

Zookeeper

ZooKeeper 是一个开源的分布式协调服务,ZooKeeper框架最初是在“Yahoo!"上构建的,用于以简单而稳健的方式访问他们的应用程序。 后来,Apache ZooKeeper成为Hadoop,HBase和其他分布式框架使用的有组织服务的标准。 例如,Apache HBase使用ZooKeeper跟踪分布式数据的状态。ZooKeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。

hadoop本来就是做分布式存储的,所以Zookeeper基于Hadoop来制作,不过Zookeeper现在只有java端和c端。

可以参考这一块的内容
https://segmentfault.com/a/1190000016173878

相关文章

  • 大厂 分布式锁

    在单机环境下,有个秒杀商品的活动,在短时间内,服务器压力和流量会陡然上升。这个就会存在并发的问题。想要解决并发需要...

  • 分布式锁

    为什么要用分布式锁 数据库乐观锁redis分布式锁zookeeper分布式锁 使用分布式锁的场景 实现分布式锁的方...

  • 什么是分布式锁?几种分布式锁分别是怎么实现的?

    一、什么是分布式锁: 1、什么是分布式锁: 分布式锁,即分布式系统中的锁。在单体应用中我们通过锁解决的是控制共享资...

  • 4:Redis 分布式锁 (文末有项目连接)

    1:什么是缓存分布式锁 2:分布式锁的关键代码 3:业务代码使用分布式缓存锁 4:业务代码使用分布式缓存锁 5:测...

  • 锁(2)-- 分布式锁

    前言: 锁分3种:java锁、分布式锁、DB锁 分布式锁的几种实现方式 目前几乎很多大型网站及应用都是分布式部署...

  • java锁的概念

    参考文档探究分布式并发锁并发编程-锁的发展和主流分布式锁比较总结从构建分布式秒杀系统聊聊分布式锁探索并发编程(六)...

  • Redis实现分布式锁

    分布式下的分布式锁一般实现有三种: 基于数据库的乐观锁 基于redis的分布式锁 基于zookeeper的分布式锁...

  • 分布式锁

    为什么要用分布式锁? 分布式锁是悲观锁的实现; 如果采用乐观锁的方案就用不着分布式锁了。 能用乐观锁的地方尽量用乐...

  • 3.10:分布式锁

    本文将梳理微服务架构下,分布式锁的常用方案。整体包含以下三部分: 分布式锁的提出 分布式锁主流方案 分布式锁选择 ...

  • Redis实现分布式锁

    1. 分布式锁分类 数据库乐观锁 基于Redis的分布式锁 基于ZooKeeper的分布式锁 2. 组件依赖 po...

网友评论

      本文标题:大厂 分布式锁

      本文链接:https://www.haomeiwen.com/subject/otdgthtx.html