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 相关文章推荐
如何在WIN2K下安装PHP4.04
Oct 09 PHP
PHP版自动生成文章摘要
Jul 23 PHP
需要发散思维学习PHP
Jun 29 PHP
用PHP实现小写金额转换大写金额的代码(精确到分)
Jan 10 PHP
phpexcel导出excel的颜色和网页中的颜色显示不一致
Dec 11 PHP
解析PHP中$_FILES的使用以及注意事项
Jul 05 PHP
php取整函数ceil,floo,round的用法及介绍
Aug 31 PHP
php获取网页中图片、DIV内容的简单方法
Jun 19 PHP
php上传中文文件名乱码问题处理方案
Feb 03 PHP
php中使用url传递数组的方法
Feb 11 PHP
php实现批量修改文件名称的方法
Jul 23 PHP
PHP身份证校验码计算方法
Aug 10 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
php cookies中删除的一般赋值方法
2011/05/07 PHP
微信公众号点击菜单即可打开并登录微站的实现方法
2014/11/14 PHP
Smarty模板简单配置与使用方法示例
2016/05/23 PHP
PHP实现数据分页显示的简单实例
2016/05/26 PHP
Thinkphp自定义代码生成工具及用法说明(附下载地址)
2016/05/27 PHP
解决PHP上传非标准格式的图片pjpeg失败的方法
2017/03/12 PHP
深入浅析PHP的session反序列化漏洞问题
2017/06/15 PHP
基于jquery的多彩百分比 动态进度条 投票效果显示效果实现代码
2011/08/28 Javascript
jquery+css实现的红色线条横向二级菜单效果
2015/08/22 Javascript
js鼠标点击按钮切换图片-图片自动切换-点击左右按钮切换特效代码
2015/09/02 Javascript
js匿名函数作为函数参数详解
2016/06/01 Javascript
浅谈javascript控制HTML5的全屏操控,浏览器兼容的问题
2016/10/10 Javascript
AngularJS 表单验证手机号的实例(非必填)
2017/11/12 Javascript
完美解决手机浏览器顶部下拉出现网页源或刷新的问题
2017/11/30 Javascript
使用微信小程序开发弹出框应用实例详解
2018/10/18 Javascript
jQuery 动态粒子效果示例代码
2020/07/07 jQuery
[01:25]DOTA2自定义游戏灵园鬼域等你踏足
2015/10/30 DOTA
Python使用新浪微博API发送微博的例子
2014/04/10 Python
python基于queue和threading实现多线程下载实例
2014/10/08 Python
Python学生信息管理系统修改版
2018/03/13 Python
Pycharm之快速定位到某行快捷键的方法
2019/01/20 Python
Python datetime 格式化 明天,昨天实例
2020/03/02 Python
keras.utils.to_categorical和one hot格式解析
2020/07/02 Python
python3 kubernetes api的使用示例
2021/01/12 Python
pytorch下的unsqueeze和squeeze的用法说明
2021/02/06 Python
canvas实现手机的手势解锁的步骤详细
2020/03/16 HTML / CSS
凯特·丝蓓英国官网:Kate Spade英国
2016/11/07 全球购物
怎样声明子类
2013/07/02 面试题
好家长事迹材料
2014/01/23 职场文书
公司承诺书格式
2014/05/21 职场文书
用人单位终止解除劳动合同证明书
2014/10/06 职场文书
2014年创卫工作总结
2014/11/24 职场文书
毕业生个人总结
2015/02/28 职场文书
乔布斯辞职信(中英文对照)
2015/05/12 职场文书
2015年安全保卫工作总结
2015/05/14 职场文书
Java 超详细讲解hashCode方法
2022/04/07 Java/Android