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 相关文章推荐
深入了解php4(2)--重访过去
Oct 09 PHP
PHP XML error parsing SOAP payload on line 1
Jun 17 PHP
PHP开发中的错误收集,不定期更新。
Feb 03 PHP
nginx+php-fpm配置文件的组织结构介绍
Nov 07 PHP
ThinkPHP使用UTFWry地址库进行IP定位实例
Apr 01 PHP
php单文件版在线代码编辑器
Mar 12 PHP
php构造函数与析构函数
Apr 23 PHP
laravel学习教程之存取器
Jul 30 PHP
PHP封装的XML简单操作类完整实例
Nov 13 PHP
PHP设计模式之装饰器模式实例详解
Feb 07 PHP
php 多继承的几种常见实现方法示例
Nov 18 PHP
thinkphp5.1框架模板赋值与变量输出示例
May 25 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
新浪微博API开发简介之用户授权(PHP基础篇)
2011/09/25 PHP
PHP投票系统防刷票判断流程分析
2012/02/04 PHP
php异常处理方法实例汇总
2015/06/24 PHP
PHP面向对象继承用法详解(优化与减少代码重复)
2016/12/02 PHP
PHP5.6读写excel表格文件操作示例
2019/02/26 PHP
php根据地址获取百度地图经纬度的实例方法
2019/09/03 PHP
jquery创建div 实现代码
2009/04/27 Javascript
风吟的小型JavaScirpt库 (FY.JS).
2010/03/09 Javascript
ASP.NET jQuery 实例2 (表单中使用回车在TextBox之间向下移动)
2012/01/13 Javascript
js算法中的排序、数组去重详细概述
2013/10/14 Javascript
兼容主流浏览器的iframe自适应高度js脚本
2014/01/10 Javascript
jquery ztree实现下拉树形框使用到了json数据
2014/05/14 Javascript
JQuery实现动态表格点击按钮表格增加一行
2014/08/24 Javascript
javascript文本模板用法实例
2015/07/31 Javascript
使用jquery+CSS3实现仿windows10开始菜单的下拉导航菜单特效
2015/09/24 Javascript
用canvas 实现个图片三角化(LOW POLY)效果
2016/02/18 Javascript
jQuery EasyUI编辑DataGrid用combobox实现多级联动
2016/08/29 Javascript
原生JS取代一些JQuery方法的简单实现
2016/09/20 Javascript
Vue.js中组件中的slot实例详解
2017/07/17 Javascript
vue组件父与子通信详解(一)
2017/11/07 Javascript
Vue-cli-webpack搭建斗鱼直播步骤详解
2017/11/17 Javascript
微信小程序实现上传图片功能
2018/05/28 Javascript
vue实现父子组件之间的通信以及兄弟组件的通信功能示例
2019/01/29 Javascript
Python列表生成器的循环技巧分享
2015/03/06 Python
Python网站验证码识别
2016/01/25 Python
基于Python对象引用、可变性和垃圾回收详解
2017/08/21 Python
Python有序查找算法之二分法实例分析
2017/12/11 Python
Python管理Windows服务小脚本
2018/03/12 Python
python读写配置文件操作示例
2019/07/03 Python
python实现静态服务器
2019/09/05 Python
会计员岗位职责
2014/03/15 职场文书
2014年综治宣传月活动总结
2014/04/28 职场文书
教师师德演讲稿
2014/05/06 职场文书
和谐拯救危机观后感
2015/06/15 职场文书
公司会议开幕词
2016/03/03 职场文书
2019数学教师下学期工作总结
2019/06/27 职场文书