当前位置: 首页 > news >正文

宁波企业网站搭建图片怎么建立网站的流程

宁波企业网站搭建图片,怎么建立网站的流程,3d室内设计软件手机版,在哪里可以学做网站概念 PHP使用分布式锁#xff0c;受语言本身的限制#xff0c;有一些局限性。 通俗理解单机锁问题#xff1a;自家的锁锁自家的门#xff0c;只能保证自家的事#xff0c;管不了别人家不锁门引发的问题#xff0c;于是有了分布式锁。分布式锁概念#xff1a;是针对多个…概念 PHP使用分布式锁受语言本身的限制有一些局限性。 通俗理解单机锁问题自家的锁锁自家的门只能保证自家的事管不了别人家不锁门引发的问题于是有了分布式锁。分布式锁概念是针对多个节点的锁。避免出现数据不一致或者并发冲突的问题让每个节点确保在任意时刻只有一个节点能够对公共资源进行操作单机的锁只能够单节点使用多节点防不住。核心原理分布式锁的核心原理就是在每个节点执行时先去一个公共的地方判断是否持有锁如果有锁就说明资源被占用没锁就可以持有该资源。通俗举例多个部门开部门会议需要占用会议室的位置发现会议室门关着不知道里面有没有人此时门外面有个牌子说明是会议中还是会议结束离老远就知道会议室是不是被占用了避免会议竞争引起的错乱。 应用场景 分布式排它保证只有一个节点被访问常用于秒杀等并发问题的处理。分布式任务调度在分布式任务调度系统中多个节点可能会竞争执行同一个任务使用分布式锁可以确保只有一个节点能够执行该任务避免重复执行和冲突。并发下数据库事务幻读问题并发下的MySQL事务当中插入数据前先判断有没有没有再插入从而避免重复但是其它事务未提交就检测不到RR的隔离级别导致的但是插入相同数据又会导致唯一约束起作用从而报错添加分布式锁从而避免报错。这场景适用于唯一约束冲突报错很多的场景功能否则使用了会影响性能。 分布式锁的特点 互斥性相同时间只能有一个节点会获取该锁其它节点要么等待要么直接返回失败。可重入单个节点可重复获取该锁且不会发生阻塞PHP的语言特性不支持。安全获取锁的节点崩溃或失去连接、锁资源会释放。 可用的存储组件选择 Redis、MySQL乐观锁、或悲观锁、ZooKeeper、Etcd、Memcache等存储组件都可以实现分布式锁。 ZooKeeper、Etcd是Java生态PHP几乎不用。 Memcache很少用了一般都会用redis。 MySQL性能比不了Redis高并发过来容易被夯住数据不会自动过期删除需要逻辑判断。所以也不用。 分布式锁要求高性能和自动过期的兜底特性所以用Redis的set命令刚好。 Redis分布式锁又称为Redis Distributed Lock也叫RedLock。 用Redis手动实现分布式锁示例 这是花十分钟写出来的例子不建议商用。 class RedLock {//声明redisprivate $redis;/*** function 构造方法初始化redis* other void*/public function __construct() {$redis new Redis();$redis-connect(127.0.0.1, 6379);$this-redis $redis;}/*** function 非阻塞分布式锁* param $key string 锁名称* param $ttl int key自动过期时间单位毫秒* return array|false 成功返回数组失败返回false* other void*/public function addLock($lock_name, $ttl 10000) {$val base64_encode(openssl_random_pseudo_bytes(32));$set $this-redis-set($lock_name, $val, [NX, PX $ttl]);if($set false) {return false;}return [key $lock_name, val $val];}/*** function 阻塞式分布式锁* param $key string 锁名称* param $ttl int key自动过期时间单位毫秒* param $ttl int 超时时间单位毫秒* return array|false 成功返回数组失败返回false* other void*/public function addLockSpin($lock_name, $ttl 10000, $timeout 3000) {$start bcmul(microtime(true), 1000, 2);$val base64_encode(openssl_random_pseudo_bytes(32));$set $this-redis-set($lock_name, $val, [NX, PX $ttl]);if($set false) {while(true) {//超时$start_loop bcmul(microtime(true), 1000, 2);if(bcadd($start, $timeout, 2) $start_loop) {return false;}//尝试获取锁$set_loop $this-redis-set($lock_name, $val, [NX, PX $ttl]);if($set_loop) {return [key $lock_name, val $val];}usleep(50000);}}return [key $lock_name, val $val];}/*** function 释放锁资源* param $key array|false 锁资源* return bool* other void*/public function unLock($lock) {if($lock false) {return false;}$script if redis.call(GET, KEYS[1]) ARGV[1] thenreturn redis.call(DEL, KEYS[1])elsereturn 0end;if(! $this-redis-eval($script, [$lock[key], $lock[val]], 1)) {return false;}return true;} }$redLock new RedLock(); if($lock $redLock-addLockSpin(test_key)) {echo 抢到锁了处理一些业务逻辑;$redLock-unLock($lock); //记得及时释放锁资源 } else {echo 锁没有抢到; }现有的解决方案 java实现分布式锁有redissonPHP也有自己的包。 看过一些博主的用PHP实现分布式锁好多没有使用Lua这没办法保证多条Redis语句原子性的执行。 项目中能用到这种东西的对于高可用、原子性、稳定性有很强的依赖所以推荐使用成熟的扩展包。 composer require signe/redlock-php 文档https://packagist.org/packages/signe/redlock-php 执行之后看使用redis的monitor指令查看发现用了Lua说明这个包兼顾了原子性的操作。 我这个是示例记得无论最后执行成功还是失败都记得及时释放锁资源。非自旋写法 $server new \Redis; $server-connect(127.0.0.1, 6379); $servers [$server,];$redLock new \RedLock\RedLock($servers); $lock $redLock-lock(my_resource_name, 10000);if($lock) {echo 加锁成功;$redLock-unlock($lock); } else {echo 加锁失败; }自旋写法 $server new \Redis; $server-connect(127.0.0.1, 6379); $servers [$server,];$redLock new \RedLock\RedLock($servers); $lock $redLock-lock(my_resource_name, 10000);if($lock) {echo 加锁成功; // $redLock-unlock($lock); } else {while(true) {$lock2 $redLock-lock(my_resource_name, 10000);if($lock2) {echo 加锁成功2;//运行某些代码$redLock-unlock($lock2);return ;} } }如果需要拿到锁后释放锁前业务逻辑代码块再对拿到锁的分布式锁续期。 因为redis的key与val值都不变只变动过期时间所以使用PEXPIRE指令也可使用PSETEX指令。 又需要防止这个锁自动过期已经被其它节点占用已经改成了其它节点的数据所以value值需要验证是不是当前锁的value值。 两个操作为了保证原子性就用到了Lua。 //$redLock new \RedLock\RedLock($servers); //$lock $redLock-lock(my_resource_name, 20000);$script if redis.call(GET, KEYS[1]) ARGV[1] thenreturn redis.call(PEXPIRE, KEYS[1], KEYS[2])elsereturn 0end; $server-eval($script, [$lock[resource], 毫秒过期时间, $lock[token]], 2);PHP使用分布式锁的局限性问题 重入性无法实现PHP这门语言有局限性不适合和redis结合做分布式锁分布式锁的重入性无法实现因为脚本能执行完内存就被回收了无法像C/C那样轻松操控进程和线程。超时问题没有监控机制没有像redisson一样的watch dog看门狗的机制去监控业务执行过长导致redis分布式锁自动释放被其它锁占用的问题。 PHP使用分布式锁有种东施效颦的感觉。 为什么加锁时set指令要加NX set指令加nx表示只有在key不存在的情况下才能设置键值对。 多个节点加锁获取分布式锁资源实质就是在redis中设置一条值。因为分布式锁的排它性同一时间内只能有一个节点可以拿到该锁。 若用set不加nx就会产生覆盖造成业务错乱。 客户端宕机导致锁资源无法释放的死锁问题 redis单线程通常不会发生死锁问题。 Redis在客户端挂掉的情况的情况会导致分布式锁锁资源无法及时释放这可能会导致其它节点无法加锁从而阻塞类似死锁的效果。 添加过期时间做兜底即可。 对高可用MySQL可以主从Redis也可以从而保证分布式锁存储的高可用性。 分布式锁redis操作的原子性问题 就算是redis事务multi也是弱事务仍旧会出现并发安全问题最好使用LuaRedis的方式去实现原子性的分布式锁这会把一些指令集当做一个任务队列去处理保证原子性。 如何设置拿到锁资源后的超时时间 对于Javaredisson有watch dog的自动监控机制但是PHP没有。 PHP也很难实现原因有2 不知道自动续期的时机业务流程没走完分布式锁临近过期才续期业务流程走完了还续什么期这个时机高并发场景下难以获取净增加复杂度。PHP语言本身缺少锁机制就算知道了要续期加锁与续期监控缺少锁机制的强关联加锁一个进程监控又一个进程进程间通信是一个问题PHP进程间通信与Redis操作无法原子执行又是一个问题也就是说就算被通知要续期了再续期时锁资源超时自动释放后可能都被别的节点占用了。 PHP能做的只能是设置更多的超时时间来防止锁资源自动释放被其它节点抢走。 缺点也很明显一旦这个节点挂掉锁资源需要很长时间才能释放这个时间段的分布式锁无法被任意一个节点使用。 锁资源的错误释放问题 时序图 步骤客户端1客户端2补充1获取锁成功//2执行中获取锁失败客户端1的锁阻塞了客户端23执行中获取锁失败客户端2自旋不断尝试获取锁4锁资源到期自动释放获取锁成功由于客户端1的锁资源过期才导致客户端2拿到的分布式锁5释放锁执行中这一步才是客户端1真正释放(删)锁的时刻但是由于没做验证这个释放(删)的过程会把会话2创建的锁给释放(删)掉造成误删除 为了避免这个问题val值可设置为节点标识。 所以redis在get值的时候需要判断val值是不是当前的节点标识。 为了保证原子性查询和删除两个操作需要用Lua脚本。 其次要注意不管节点程序执行成功或者失败只要该走的流程走完了都需要及时释放锁。 分布式锁的可重入问题 PHP解决不了。 假设同一个节点递归或循环添加分布式锁是否让同一节点重复加同一把锁大部分场景不需要但是也得看业务场景。 这种机制是为了避免第一层循环添加成功之后失败的问题。 对于非PHP而言重入问题还需要再维持一个redis hashkey为锁名field为节点的唯一标识value为重入次数重入1次次数加1。因为重入相当于重新获取锁但是不会新增锁资源如果这个时间被删掉那么重入时会加锁成功但锁资源被强制释放此时重入后的业务逻辑还不一定执行完毕。所以删除时需要判断value值是否为0如果不为0说明有重入这两步操作也是需要再一个Lua脚本中。 分布式锁的自旋机制 自旋可以理解为内部死循环内部不断重试直到满足条件直观感受就是被阻塞。 如果没有自旋10个节点只有1个能加锁成功其余9个失败如果这9个全部失败掉看起来差点意思。 因此可以选择被阻塞期间不断重试所谓的自旋方案其实很好理解重试伪代码如下: while(加锁失败) {usleep(10000);重新尝试加锁代码if(加锁成功) {return 加锁成功;} }此处也可以添加一个次数限制防止永久死循环的兜底策略 $retry_count 0; while(true) {$retry_count ;if(加锁成功) {return 加锁成功;}if($retry_count 20) {echo 1;return 重试次数过多;}usleep(30000); }也可以根据时间去做限制防止永久死循环的兜底策略 $start_time microtime(true); while(true) {if(加锁成功) {return 加锁成功;}if($start_time 5 microtime(true)) {return 超时; }usleep(30000); }Redis主从架构对分布式锁的高可用问题 节点1再master上获取到了分布式锁叫lock1此时master还没有同步到slave结果master挂掉了。 此时故障转移slave做顶梁柱节点2也获取到了slave的分布式锁也叫lock1。 这种情况违背了分布式锁的排它性。概率很小但是有可能发生。 setnx无法解决分布式场景下的锁排它性问题。 这个是运维层面要考虑的东西。 手动实现分布式锁容易被忽略的问题 分布式锁这种工程化的东西每个零件都有用虽然RedLock底层用redis set指令实现。 若忘记加超时时间上锁的节点挂掉没有释放锁资源其它节点会一直拿不到锁严重影响业务。若忘记加value值判断去释放锁A节点在执行业务逻辑超时自动释放锁资源被B节点抢去等A节点执行完业务代码后释放锁会把B节点的锁删除。若忘记用Lua脚本这导致redis在执行任务期间同一客户端的多个脚本不会在一个Redis内置的任务队列处理保证不了原子性超卖的并发安全问题就是这样产生的。覆盖问题redis分布式锁设置值时用的setnx思想有值则不设置避免覆盖若用set整不好把原先的覆盖掉了。对于像JavaPHP不行语言手动实现可能缺少key的监控过期以及重入性问题。
http://www.w-s-a.com/news/397329/

相关文章:

  • 像京东一样的网站wordpress入门视频教程7 - 如何在文章里加入视频和音乐
  • 惠州网站建设排名wordpress3万篇文章优化
  • 创建网站的三种方法北京建王园林工程有限公司
  • jsp网站建设模板下载十大免费excel网站
  • 网络公司网站图片网站建立好了自己怎么做优化
  • 云主机是不是可以搭建无数个网站百度快速seo优化
  • 房地产怎么做网站推广建立音乐网站
  • 川畅科技联系 网站设计网站开发的教学视频
  • 为什么学网站开发凡科登陆
  • 设计师常备设计网站大全中山精品网站建设信息
  • 杭州建设工程网seo服务是什么
  • 兼职做问卷调查的网站wordpress mysql设置
  • 怎么在百度上能搜到自己的网站山西seo谷歌关键词优化工具
  • 网站搭建免费模板飞鱼crm下载
  • 网站开发竞品分析app制作公司深圳
  • 网站建设ssc源码修复设计班级网站建设
  • 网站重定向凡科做网站不要钱
  • 佛山html5网站建设微信营销软件破解版
  • 网站单页做301南京百度推广
  • 私人做网站要多少钱展芒设计网页
  • 怎样网站制作设计如何在网上推广农产品
  • 做关键词排名卖网站聚名网
  • 吉林省住房城乡建设厅网站首页体育器材网站建设方案
  • 网站建设及维护专业手机金融界网站
  • 常州网站建设工作室建立网站有怎么用途
  • 如何盗取网站推广策划书模板
  • 游戏网站建设计划书网络开发需要学什么
  • 手机网站维护费网站开发包括网站过程
  • 懂做游戏钓鱼网站的网站建设技术的发展
  • 网站被百度收录百度一下你就知道 官网