广州seo排名外包,沈阳网站推广优化公司哪家好,抖音seo招商,电脑版h5制作软件首先分布式锁和我们平常讲到的锁原理基本一样#xff0c;目的就是确保#xff0c;在多个线程并发时#xff0c;只有一个线程在同一刻操作这个业务或者说方法、变量。在一个进程中#xff0c;也就是一个jvm 或者说应用中#xff0c;我们很容易去处理控制#xff0c;在jdk … 首先分布式锁和我们平常讲到的锁原理基本一样目的就是确保在多个线程并发时只有一个线程在同一刻操作这个业务或者说方法、变量。在一个进程中也就是一个jvm 或者说应用中我们很容易去处理控制在jdk java.util 并发包中已经为我们提供了这些方法去加锁 比如synchronized 关键字 或者Lock 锁都可以处理。但是我们现在的应用程序如果只部署一台服务器那并发量是很差的如果同时有上万的请求那么很有可能造成服务器压力过大而瘫痪。想想双十一 和 三十晚上十点分支付宝红包等业务场景自然需要用到多台服务器去同时处理这些业务那么这些服务可能会有上百台同时处理但是请我们大家想一想如果有100台服务器 要处理分红包的业务现在假设有1亿的红包1千万个人分金额随机那么这个业务场景下是不是必须确保这1千万个人最后分的红包金额总和等于1亿。如果处理不好~~每人分到100万那马云爸爸估计大年初一就得宣布破产了~~1常规锁会造成什么情况首先说一下我们为什么要搞集群简单理解就是需求量(请求并发量)变大了一个工人处理能力有限那就多招一些工人来一起处理。假设1千万个请求平均分配到100台服务器上每个服务器 接收10w的请求(这10w个请求并不是在同一秒中来的可能是在1,2个小时内可以联想下我们三十晚上开红包等到10.20开始有的人立马开了有的人是不是等到12点了才想起来~)那这样的话平均到每一秒上的请求也就不到1千个这种压力一般的服务器还是可以承受的。第一个请求到来后是不是需要在1亿里面给他分一部分钱金额随机假设第一个人分到了100那是不是要在这1亿中减去100块剩下99999900 块~第二个用户再来分金额随机这次分200块那是不是就需要在剩下的99999900块中再减去200块剩下99999700 块。等到第10w个用户来一看还有1000w那这1000w全成他的了。等于是在每个服务器中去分1亿也就是10w个用户分了一个亿最后总计有100个服务器要分100亿。如果真这样了虽说马云爸爸不会破产(据最新统计马云有2300亿人民币)那分红包的开发项目组以及产品经理可以GG了~简化结构图如下2分布式锁怎么去处理 那么为了解决这个问题让1000万用户只分1亿而不是100亿这个时候分布式锁就派上用处了。分布式锁可以把整个集群就当作是一个应用一样去处理那么也就需要这个锁要独立于每一个服务之外而不是在服务里面。假设第一个服务器接收到用户1的请求后那么这个时候他就不能只在自己的应用中去判断还有多少钱可以分了而需要去外部请求专门负责管理这1亿红包的人(服务)问他哎我这里要分100块给我100。管理红包的妹子(服务)一看还有1个亿那好给你100块然后剩下99999900块。第二个请求到来后被服务器2获取继续去询问管理红包的妹子我这边要分10块管理红包的妹子先查了下还有99999900那就说好给你10块。那就剩下99999890块 等到第1000w个请求到来后服务器100拿到请求继续去询问管理红包的妹子你要100妹子翻了翻白眼对你说就剩1块了爱要不要那这个时候就只能给你1块了(1块也是钱啊买根辣条还是可以的)。这些请求编号1,2不代表执行的先后顺序正式的场景下应该是 100台服务器每个服务器持有一个请求去访问负责管理红包的妹子(服务)那在管红包的妹子那里同时会接收到100个请求这个时候就需要在负责红包的妹子那里加个锁就可以了(抛绣球)你们100个服务器谁拿到锁(抢到绣球)谁就进来和我谈我给你分其他人就等着去吧经过上面的分布式锁的处理后马云爸爸终于放心了决定给红包团队每人加一个鸡腿。简化的结构图如下3分布式锁的实现有哪些 说到分布式锁的实现还是有很多的有数据库方式的有redis分布式锁有zookeeper分布式锁等等我们如果采用redis作为分布式锁那么上图中负“责红包的妹子(服务)”就可以替换成redis请自行脑补。3.1为什么redis可以实现分布式锁首先redis是单线程的这里的单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性)即一个线程处理所有网络请求其他模块仍用了多个线程。在实际的操作中过程大致是这样子的服务器1要去访问发红包的妹子也就是redis那么他会在redis中通过setnx key value 操作设置一个key 进去value是啥不重要重要的是要有一个key也就是一个标记而且这个key你爱叫啥叫啥只要所有的服务器设置的key相同就可以。假设我们设置一个如下图那么我们可以看到会返回一个1那就代表了成功。如果再来一个请求去设置同样的key如下图这个时候会返回0那就代表失败了。那么我们就可以通过这个操作去判断是不是当前可以拿到锁或者说可以去访问“负责发红包的妹子”如果返回1那我就开始去执行后面的逻辑如果返回0那就说明已经被人占用了我就要继续等待。当服务器1拿到锁之后进行了业务处理完成后还需要释放锁如下图所示删除成功返回1那么其他的服务器就可以继续重复上面的步骤去设置这个key以达到获取锁的目的。当然以上的操作是在redis客户端直接进行的通过程序调用的话肯定就不能这么写比如java 就需要通过jedis 去调用但是整个处理逻辑基本都是一样的通过上面的方式我们好像是解决了分布式锁的问题但是想想还有没有什么问题呢 对问题还是有的可能会有死锁的问题发生比如服务器1设置完之后获取了锁之后忽然发生了宕机。那后续的删除key操作就没法执行这个key会一直在redis中存在其他服务器每次去检查都会返回0他们都会认为有人在使用锁我需要等。为了解决这个死锁的问题我们就就需要给key 设置有效期了。 设置的方式有2种1第一种就是在set完key之后直接设置key的有效期 expire key timeout 为key设置一个超时时间单位为second超过这个时间锁会自动释放避免死锁。这种方式相当于把锁持有的有效期交给了redis去控制。如果时间到了你还没有给我删除key那redis就直接给你删了其他服务器就可以继续去setnx获取锁。2第二种方式就是把删除key权利交给其他的服务器那这个时候就需要用到value值了比如服务器1设置了value 也就是 timeout 为 当前时间1 秒 这个时候服务器2 通过get 发现时间已经超过系统当前时间了那就说明服务器1没有释放锁服务器1可能出问题了服务器2就开始执行删除key操作并且继续执行setnx 操作。但是这块有一个问题也就是不光你服务器2可能会发现服务器1超时了服务器3也可能会发现如果刚好服务器2setnx操作完成服务器3就接着删除是不是服务器3也可以setnx成功了那就等于是服务器2和服务器3都拿到锁了那就问题大了。这个时候怎么办呢这个时候需要用到 “GETSET key value” 命令了。这个命令的意思就是获取当前key的值并且设置新的值。假设服务器2发现key过期了开始调用 getset 命令然后用获取的时间判断是否过期如果获取的时间仍然是过期的那就说明拿到锁了。如果没有则说明在服务2执行getset之前服务器3可能也发现锁过期了并且在服务器2之前执行了getset操作重新设置了过期时间。那么服务器2就需要放弃后续的操作继续等待服务器3释放锁或者去监测key的有效期是否过期。这块其实有一个小问题是服务器3已经修改了有效期拿到锁之后服务器2也修改了有效期但是没能拿到锁但是这个有效期的时间已经被在服务器3的基础上有增加一些但是这种影响其实还是很小的几乎可以忽略不计。3.2为什么zookeeper可以实现分布式锁百度百科是这么介绍的ZooKeeper是一个分布式的开放源码的分布式应用程序协调服务是Google的Chubby一个开源的实现是Hadoop和Hbase的重要组件。那对于我们初次认识的人可以理解成ZooKeeper就像是我们的电脑文件系统我们可以在d盘中创建文件夹a并且可以继续在文件夹a中创建 文件夹a1a2。那我们的文件系统有什么特点那就是同一个目录下文件名称不能重复同样ZooKeeper也是这样的。 在ZooKeeper所有的节点也就是文件夹称作 Znode而且这个Znode节点是可以存储数据的。我们可以通过“ create /zkjjj nice” 来创建一个节点这个命令就表示在跟目录下创建一个zkjjj的节点值是nice。同样这里的值和我在前面说的redis中的一样没什么意义你随便给。另外ZooKeeper可以创建4种类型的节点分别是1持久性节点2持久性顺序节点3临时性节点4临时性顺序节点首先说下持久性节点和临时性节点的区别持久性节点表示只要你创建了这个节点那不管你ZooKeeper的客户端是否断开连接ZooKeeper的服务端都会记录这个节点。临时性节点刚好相反一旦你ZooKeeper客户端断开了连接那ZooKeeper服务端就不再保存这个节点。再说下顺序性节点顺序性节点是指在创建节点的时候ZooKeeper会自动给节点编号比如0000001 0000002 这种的。最后说下zookeeper有一个监听机制客户端注册监听它关心的目录节点当目录节点发生变化(数据改变、被删除、子目录节点增加删除)等zookeeper会通知客户端。下面我们继续结合我们上面的分红包场景描述下在zookeeper中如何加锁。假设服务器1创建了一个节点 /zkjjj ,成功了那服务器1就获取了锁服务器2再去创建相同的锁那么他就会失败这个时候他就就只能监听这个节点的变化。等到服务器1处理完业务删除了节点后他就会得到通知然后去创建同样的节点获取锁处理业务再删除节点后续的100台服务器与之类似注意这里的100台服务器并不是挨个去执行上面的创建节点的操作而是并发的当服务器1创建成功那么剩下的99个就都会注册监听这个节点等通知以此类推。 但是大家有没有注意到这里还是有问题的还是会有死锁的情况存在对不对当服务器1创建了节点后挂了没能删除那其他99台服务器就会一直等通知那就完蛋了。。。这个时候呢就需要用到临时性节点了我们前面说过了临时性节点的特点是客户端一旦断开就会丢失也就是当服务器1创建了节点后如果挂了。那这个节点会自动被删除这样后续的其他服务器就可以继续去创建节点获取锁了。但是我们可能还需要注意到一点就是惊群效应举一个很简单的例子,当你往一群鸽子中间扔一块食物,虽然最终只有一个鸽子抢到食物,但所有鸽子都会被惊动来争夺,没有抢到..就是当服务器1节点有变化会通知其余的99个服务器但是最终只有1个服务器会创建成功这样98还是需要等待监听那么为了处理这种情况就需要用到临时顺序性节点大致意思就是之前是所有99个服务器都监听一个节点现在就是每一个服务器监听自己前面的一个节点。假设100个服务器同时发来请求这个时候会在 /zkjjj 节点下创建 100 个临时顺序性节点 /zkjjj/000000001, /zkjjj/000000002,一直到 /zkjjj/000000100,这个编号就等于是已经给他们设置了获取锁的先后顺序了。当001节点处理完毕删除节点后002收到通知去获取锁开始执行执行完毕删除节点通知003~以此类推。