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

博客网站推广法互联网乌镇峰会

博客网站推广法,互联网乌镇峰会,wordpress删除版权信息,网页设计基础课程最终代码(通用类) 1 面试中、实际工作中#xff0c;经常涉及到 redis 分布式锁#xff0c;正确写法如下。先奉上代码#xff0c;再讲解。 ?php namespace app\common\library; /*** 通用分布式锁(原子操作)*/ class Lock {/*** 获取redis实例* return \Redis* throws…最终代码(通用类) 1 面试中、实际工作中经常涉及到 redis 分布式锁正确写法如下。先奉上代码再讲解。 ?php namespace app\common\library; /*** 通用分布式锁(原子操作)*/ class Lock {/*** 获取redis实例* return \Redis* throws \RedisException*/public static function redis(){$redis new \Redis();$redis-connect(192.168.4.147,6179);return $redis;}/*** 加锁(原子操作)* param string $key 要加锁的key* param string $value 必须是唯一值* param int $expires 锁的过期时间(秒)* return bool* throws \RedisException*/public static function lock(string $key,string $value,int $expires): bool{# redis实例$redis self::redis();# 原子操作 -- 设置锁且设置过期时间return $redis-set($key,$value,[nx,ex$expires]);}/*** 解锁(原子操作)* param string $key 要解锁的key* param string $value 加锁时的值* return mixed|\Redis* throws \RedisException*/public static function unlock(string $key,string $value){# redis实例$redis self::redis();# lua 脚本$lua if redis.call(GET,KEYS[1]) ARGV[1] thenreturn redis.call(DEL,KEYS[1])elsereturn 0end;return $redis-eval($lua,[$key,$value],1);}/*** 生成唯一值* return string*/public static function generateValue(): string{return microtime(true).mt_rand(10000,99999);} }2 使用方式 use app\common\library\Lock; # 抢到锁 if(Lock::lock($key,$value,300)){try{# 业务逻辑}catch (\Exception $e){}finally {# 释放锁Lock::unlock($key,$value);} }讲解 使用场景 抢红包、秒杀下单、扣库存、… 目的 在并发情况下避免业务逻辑的重复执行导致性能低下或数据不一致。重复执行没意义的工作浪费性能比如数据清理、数据归档、检测日志等 。重复执行有意义的工作导致数据出错比如重复多扣了库存。 一些常见的写法 1 setnx expire 说到 redis 的分布式锁很多同学马上会想到 setnx expire先用 setnx 抢锁如果抢到之后再用expire 给锁设置一个过期时间防止忘记释放。 setnx 是 set if not exists 的缩写表示如果 key 不存在则去设置成功返回1否则返回0。 //抢锁 if($redis-setnx($key,$value)){//设置过期时间$redis-expire($key,300);try{//业务逻辑}catch (\Exception $e){}finally {//释放锁$redis-del($key);} }注这个方案的问题在于setnx 和 expire 两个命令分开了不是原子操作。如果执行完加锁操作(setnx)后正要执行 expire 设置过期时间进程崩了或者要重启维护那么这个锁就长生不老了别的线程永远也获取不到这个锁了。 2 使用Lua脚本(包含setnx expire两条指令) 抢锁的改进如下解决了上面写法1抢锁时的非原子操作。利用 lua 脚本把多个指令一起执行达到原子操作的目的。 # lua脚本$lua if redis.call(setnx,KEYS[1],ARGV[1]) 1 thenredis.call(expire,KEYS[1],ARGV[2])elsereturn 0end;# 执行lua脚本并传入参数return $redis-eval($lua,[$key,$value,$expires],1);3 SET的扩展命令(SET EX PX NX) 效果等同于写法2也是原子性的。 //抢锁 if($redis-set($key,$value,[NX,EX300])){try{//业务逻辑}catch (\Exception $e){}finally {//释放锁$redis-del($key);} }SET key value[EX seconds][PX milliseconds][NX|XX] NX :表示key不存在的时候才能set成功也即保证只有第一个客户端请求才能获得锁而其他客户端请求只能等其释放锁才能获取。 EX seconds :设定key的过期时间时间单位是秒。 PX milliseconds: 设定key的过期时间单位为毫秒 XX: 仅当key存在时设置值 注但是这个方案还有个问题「锁被别的线程误删」 比如线程A执行完后去释放锁但它不知道当前的锁可能是线程B持有。线程A就把线程B的锁释放了但线程B临界区业务代码可能还没执行完成。 释放锁的代码改进如下判断所有者是否是自己然后再释放。也用原子操作 # redis实例 $redis $this-redis(); # lua 脚本 $lua if redis.call(GET,KEYS[1]) ARGV[1] thenreturn redis.call(DEL,KEYS[1]) elsereturn 0 end ; return $redis-eval($lua,[$key,$value],1);4 SET EX PX NX 校验所有者再删除 改进后最终的代码见文章开头。 后记 注意请根据实际业务情况合理设置锁的过期时间 expires 。 一、 无论如何依然存在一个问题「锁过期释放了业务还没执行完」 假设线程A获取锁成功一直在执行业务代码300秒过后它还没执行完。这时候锁就过期了别的线程又请求进来获取到锁了也开始执行业务代码。问题就来了业务代码并不是严格串行执行。 一般情况中小项目中做好日志、容错判断等即可。如果你项目到了一定规模如果你追求锁的决定安全性解决方案是自动续期。 这个话题值得再另写一篇文章讲解。自行上网搜索学习此处省略。 JAVA 提供了很好的一个分布式锁框架 Redisson 它很好的解决了此问题。PHP 暂时我还没找到好的类库。 还有就是自己实现自动续期。 二、 多个 redis 实例、集群模式时解决方案请看官方提供的 RedLock。这又值得另写一篇文章讲解。自行上网搜索学习此处省略。
http://www.w-s-a.com/news/909303/

相关文章:

  • 做网站视频网站备案 新闻审批号
  • 织梦网站怎么居中视频网站开发与制作
  • 网站上海备案佛山网站seo哪家好
  • 品牌形象网站有哪些珠海市区工商年报在哪个网站做
  • 注册域名不建设网站seo外包服务方案
  • 如何进行外贸网站建设wordpress文章输入密码可见
  • 政务网站建设索引常州做网站信息
  • 南宁做网站找哪家好wordpress 更改首页
  • 一个人在家做网站建设品牌策划流程
  • 小网站广告投放wordpress页面添加js
  • 仿制别人的竞价网站做竞价犯法吗wordpress添加版块
  • wordpress主题 站长互联网站备案表
  • 广州品牌策划公司排行南宁seo网络推广公司
  • 营销型网站图片肯德基网站开发
  • 网站的外链是什么wordpress开启菜单
  • 文字字体是什么网站西安博达网站建设
  • 北京南昌网站建设网站查看空间商
  • 网站建设人员职责分布乐清市网站建设设计
  • 网站建设etw网站建设陕西
  • 网站文章页内链结构不好可以改吗wordpress英文模板下载
  • 北京天通苑 做网站哈尔滨快速网站排名
  • 网站开发负责人是什么职位试剂网站建设
  • 什么是展示型网站wordpress链接视频
  • 佳木斯城乡建设局网站过年做哪个网站能致富
  • 石家庄快速网站搭建设计公司属于什么企业
  • 中小学智慧校园建设平台网站sem竞价推广
  • 想创建一个网站官方网站建设推广
  • 江门网站优化民间it网站建设
  • 科研实验室网站建设wordpress加载模板
  • 用r做简易的网站软件园二期做网站的公司