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 相关文章推荐
php桌面中心(二) 数据库写入
Mar 11 PHP
php下载远程文件类(支持断点续传)
Nov 14 PHP
php各种编码集详解和以及在什么情况下进行使用
Sep 11 PHP
PHP操作文件类的函数代码(文件和文件夹创建,复制,移动和删除)
Nov 10 PHP
PHP-redis中文文档介绍
Feb 07 PHP
php switch语句多个值匹配同一代码块应用示例
Jul 29 PHP
在Ubuntu 14.04上部署 PHP 环境及 WordPress
Sep 02 PHP
Yii框架关联查询with用法分析
Dec 02 PHP
浅析THINKPHP的addAll支持的最大数据量
Feb 03 PHP
PHP简单数据库操作类实例【支持增删改查及链式操作】
Oct 10 PHP
php mysql procedure实现获取多个结果集的方法【基于thinkPHP】
Nov 09 PHP
解决PHP curl或file_get_contents下载图片损坏或无法打开的问题
Oct 11 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
ThinkPHP数据操作方法总结
2015/09/28 PHP
CodeIgniter分页类pagination使用方法示例
2016/03/28 PHP
PHP获取用户访问IP地址的5种方法
2016/05/16 PHP
我也种棵OO树JXTree[js+css+xml]
2007/04/02 Javascript
使用户点击后退按钮使效三行代码
2007/07/07 Javascript
学习js在线html(富文本,所见即所得)编辑器
2012/12/18 Javascript
jQuery阻止同类型事件小结
2013/04/19 Javascript
JavaScript Math.ceil() 函数使用介绍
2013/12/11 Javascript
通过url查找a元素并点击
2014/04/09 Javascript
jQuery实现字符串按指定长度加入特定内容的方法
2015/03/11 Javascript
使用jQuery实现WordPress中的Ctrl+Enter和@评论回复
2016/05/21 Javascript
省市选择的简单实现(基于zepto.js)
2016/06/21 Javascript
JS实现title标题栏文字不间断滚动显示效果
2016/09/07 Javascript
JavaScript利用正则表达式替换字符串中的内容
2016/12/12 Javascript
浅谈Vue.js
2017/03/02 Javascript
基于Vue的移动端图片裁剪组件功能
2017/11/28 Javascript
Vue组件Draggable实现拖拽功能
2018/12/01 Javascript
vue-cli2与vue-cli3在一台电脑共存的实现方法
2019/09/25 Javascript
浅谈Tensorflow模型的保存与恢复加载
2018/04/26 Python
Python数据持久化shelve模块用法分析
2018/06/29 Python
Python多进程与服务器并发原理及用法实例分析
2018/08/21 Python
简单分析python的类变量、实例变量
2019/08/23 Python
通过实例学习Python Excel操作
2020/01/06 Python
Keras构建神经网络踩坑(解决model.predict预测值全为0.0的问题)
2020/07/07 Python
PyCharm 2020.1版安装破解注册码永久激活(激活到2089年)
2020/09/24 Python
HTML5时代CSS设置漂亮字体取代图片
2014/09/04 HTML / CSS
加拿大便宜的隐形眼镜商店:Clearly
2016/09/15 全球购物
Lookfantastic法国官网:英国知名美妆购物网站
2017/10/28 全球购物
帕克纽约:PARKER NY
2018/12/09 全球购物
应届生求职信写作技巧
2013/10/24 职场文书
电子邮箱格式怎么写
2014/01/12 职场文书
医药类个人求职的自我评价
2014/02/12 职场文书
岗位工作说明书
2014/07/29 职场文书
2014小学教师年度考核工作总结
2014/12/03 职场文书
先进集体事迹材料范文
2014/12/25 职场文书