php使用redis的几种常见操作方式和用法示例


Posted in PHP onFebruary 20, 2020

本文实例讲述了php使用redis的几种常见操作方式和用法。分享给大家供大家参考,具体如下:

一、简单的字符串缓存

比如针对一些sql查询较慢,更新不频繁的数据进行缓存。

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379, 60);
$sql = 'select * from tb_order order by id desc limit 10';
//伪代码,从数据库中获取数据
$data = $db->query($sql);
$data = json_encode($data, JSON_UNESCAPED_UNICODE);
$key = md5($sql);
//缓存数据
$redis->set($key, $value, 60);
//获取数据
$data = $redis->get($key);
print_r(json_decode($data, true));

二、通过列表模拟简单队列

比如我们需要批量的发送邮件,可以把发送邮件的任务存入队列中,然后启多个php脚本从队列中读取任务去发送邮件。

也可以用来处理商品秒杀,用户点击抢购时,把一个个的用户抢购任务放入队列中,串行化处理,判断队列数量,防止超卖的发生。

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379, 60);
//循环的把发送1000条邮件任务插入队列
for ($ix = 0; $ix < 1000; $ix++) {
  $redis->lPush('send_email_queue', json_encode([
    'id' => $ix,
    'send' => 'xxx@qq.com',
    'receive' => 'yyy@qq.com',
    'title' => 'xxx',
    'body' => 'xxx',
  ]));
}
sleep(3);
//从队列中取任务,执行任务
while ($count = $redis->lLen('send_email_queue')) {
  echo "当前任务队列数 {$count} <br>";
  $task = $redis->rpop('send_email_queue');
  $task = json_decode($task, true);
  //伪代码,发送邮件
  $mailer->send($task['send'], $task['receive'], $task['title'], $task['body']);
  echo "任务 {$task['id']} 邮件发送成功<br>";
}

三、通过watch + multi 来实现乐观锁

乐观锁,顾名思义,乐观的认为数据不会被修改,只有当更新时才去判断数据是否被修改过,通常用版本号或时间戳来实现。

redis中通过watch和multi来实现,watch会监视给定的key是否发生更改,当exec的时候如果监视的key发生过改变,则整个事务会失败。

当然我们可以调用多次watch监视多个key。

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379, 60);
//设置商品的库存数为100
$redis->set('goods_stock_nums', 100);
//监视该key
$redis->watch('goods_stock_nums');
//开启事务
$redis->multi();
//修改库存数
$redis->decr('goods_stock_nums');
//提交事务,如果在此期间有其他请求修改了该key,那么事务会失败
if ($redis->exec()) {
  echo '抢购成功';
} else {
  echo '数据错误,请重新再试';
}

四、使用 set 来实现悲观锁

悲观锁,顾名思义,悲观的认为数据总是会被修改,所以在操作前都会先加上锁,操作完后,再释放锁。

<?php
function getRedis()
{
  $redis = new Redis();
  $redis->connect('127.0.0.1', 6379, 60);
  return $redis;
}
function lock($key, $random)
{
  $redis = getRedis();
  return $redis->set($key, $random, ['nx', 'ex' => 3]);
}
function unlock($key, $random)
{
  $redis = getRedis();
  //使用lua脚本保证原子性
  $script = 'if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end';
  return $redis->eval($script, [$key, $random], 1);
}
function decrGoodsStockNums()
{
  $redis = getRedis();
  //获取商品库存数
  $ret = $redis->get('goods_stock_nums');
  if ($ret === false) {
    return false;
  }
  if ($ret <= 0) {
    return false;
  }
  $random = mt_rand();
  //先获取锁
  if (lock('goods_stock_nums_lock', $random)) {
    //修改库存数
    $redis->decr('goods_stock_nums');
    //释放锁
    unlock('goods_stock_nums_lock', $random);
    return true;
  } else {
    usleep(100);
    decrGoodsStockNums();
  }
}
decrGoodsStockNums();

五、使用 publish + subscribe 完成发布和订阅

发布代码:

<?php
$redis = new Redis();
$redis->pconnect('127.0.0.1', 6379);
$ix = 0;
//发布内容
while (true) {
  $redis->publish('news', json_encode([
    'title' => '我是新闻标题' . $ix,
    'content' => '我是新闻内容' . $ix,
    'time' => date('Y-m-d H:i:s'),
  ]));
  $ix++;
  sleep(1);
}

订阅代码:

<?php
$redis = new Redis();
$redis->pconnect('127.0.0.1', 6379);
//订阅内容
$redis->subscribe(['news'], function ($redis, $channel, $msg) {
  $msg = json_decode($msg, true);
  echo "标题: {$msg['title']} 内容: {$msg['content']} 时间: {$msg['time']} <br>";
});

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php5数字型字符串加解密代码
Apr 24 PHP
php 文件状态缓存带来的问题
Dec 14 PHP
IIS7.X配置PHP运行环境小结
Jun 09 PHP
MySQL的FIND_IN_SET函数使用方法分享
Mar 27 PHP
PHP中4个加速、缓存扩展的区别和选用建议
Mar 12 PHP
PHP读取大文件的类SplFileObject使用介绍
Apr 09 PHP
thinkPHP模板中for循环与switch语句用法示例
Nov 30 PHP
微信开发之获取JSAPI TICKET
Jul 07 PHP
Windows平台实现PHP连接SQL Server2008的方法
Jul 26 PHP
Laravel 中使用简单的方法跟踪用户是否在线(推荐)
Oct 30 PHP
php ZipArchive实现多文件打包下载实例
Oct 31 PHP
PHP code 验证码生成类定义和简单使用示例
May 27 PHP
PHP使用openssl扩展实现加解密方法示例
Feb 20 #PHP
php使用redis的有序集合zset实现延迟队列应用示例
Feb 20 #PHP
解决windows上php xdebug 无法调试的问题
Feb 19 #PHP
laravel框架路由分组,中间件,命名空间,子域名,路由前缀实例分析
Feb 18 #PHP
laravel框架select2多选插件初始化默认选中项操作示例
Feb 18 #PHP
laravel框架使用FormRequest进行表单验证,验证异常返回JSON操作示例
Feb 18 #PHP
PHP For循环字母A-Z当超过26个字母时输出AA,AB,AC
Feb 16 #PHP
You might like
《星际争霸2》终章已出 RTS时代宣告终结
2017/02/07 星际争霸
PHP 中英文混合排版中处理字符串常用的函数
2007/04/12 PHP
一贴学会PHP 新手入门教程
2009/08/03 PHP
Smarty模板变量调节器用法分析
2016/05/23 PHP
PHP线程的内存回收问题
2016/07/08 PHP
PHP十六进制颜色随机生成器功能示例
2017/07/24 PHP
动态添加js事件实现代码
2009/03/12 Javascript
jQuery事件绑定和委托实例
2014/11/25 Javascript
JavaScript插件化开发教程(六)
2015/02/01 Javascript
js实现ifram取父窗口URL地址的方法
2015/02/09 Javascript
原创jQuery弹出层插件分享
2015/04/02 Javascript
js实现每日自动换一张图片的方法
2015/05/04 Javascript
asp.net中oracle 存储过程(图文)
2015/08/12 Javascript
jQuery实现图片向左向右切换效果的简单实例
2016/05/18 Javascript
AngularJS ng-bind 指令简单实现
2016/07/30 Javascript
Select2.js下拉框使用小结
2016/10/24 Javascript
微信端开发--登录小程序步骤
2017/01/11 Javascript
80%应聘者都不及格的JS面试题
2017/03/21 Javascript
JS简单获取当前日期和农历日期的方法
2017/04/17 Javascript
three.js中文文档学习之创建场景
2017/11/20 Javascript
基于webpack4搭建的react项目框架的方法
2018/06/30 Javascript
js实现烟花特效
2020/03/02 Javascript
使用Python3中的gettext模块翻译Python源码以支持多语言
2015/03/31 Python
利用python获取当前日期前后N天或N月日期的方法示例
2017/07/30 Python
python实现截取屏幕保存文件,删除N天前截图的例子
2019/08/27 Python
css3.0新属性效果在ie下的解决方案
2010/05/10 HTML / CSS
英国最大的在线奢侈手表零售商:Jura Watches
2018/01/29 全球购物
学生档案自我鉴定
2013/10/07 职场文书
活动总结格式范文
2014/04/26 职场文书
关于教师节的广播稿
2014/09/10 职场文书
大学生作弊检讨书
2014/09/11 职场文书
2014国庆节餐厅促销活动策划方案
2014/09/16 职场文书
四风批评与自我批评范文
2014/10/14 职场文书
导师对论文的学术评语
2015/01/04 职场文书
Django显示可视化图表的实践
2021/05/10 Python
一条慢SQL语句引发的改造之路
2022/03/16 MySQL