
别慌,我去年帮3个PHP项目调过Redis缓存,从美食博客到小型电商,踩过的坑能写一本“避坑指南”。今天就把我 的“笨办法”分享给你——不用记复杂命令,不用懂底层原理,跟着步骤做,保证你1小时内把Redis缓存用起来。
从0到1:PHP连接Redis的准备工作
先明确一个基础认知:Redis和PHP是“两个独立的程序”——就像你用微信发消息给朋友,微信是“客户端”,朋友的手机是“服务器”。要让它们“通话”,得先把两边都“装好”,再“打通链路”。我去年帮朋友的PHP博客调缓存时,他一开始以为“Redis是PHP的一个函数”,结果折腾了半天都没连上——现在你知道了,先把“服务器”和“客户端扩展”都搞定。
第一步:装Redis服务器——Windows/Linux都能5分钟搞定
不管你用Windows还是Linux,Redis服务器的安装都很简单:
如果是Linux(Ubuntu/CentOS):直接用包管理器装,命令是sudo apt-get install redis-server
(Ubuntu)或者sudo yum install redis
(CentOS)。装完后要启动服务:sudo systemctl start redis
,再设为开机自启:sudo systemctl enable redis
——去年帮朋友的Linux服务器装Redis,他忘了设自启,结果服务器重启后Redis没启动,网站直接报错,后来查了半小时才发现。
如果是Windows:不用编译,直接去Redis官网(https://redis.io/download,加nofollow)下Windows版本的压缩包(比如redis-5.0.14-win32-x64.zip
),解压到C盘(比如C:redis
),然后双击redis-server.exe
就能启动——注意,这个窗口不能关,关了Redis就停了(如果要后台运行,可以用redis-server service-install
安装成系统服务)。
启动后,打开命令行输入redis-cli
,如果显示127.0.0.1:6379>
,说明Redis服务器“活了”!
第二步:装PHP Redis扩展——最容易踩坑的一步
很多新手卡在这一步:“我按教程装了扩展,可phpinfo里看不到Redis!”其实90%的问题是版本不匹配——就像你穿鞋子,38码的脚不能穿40码的鞋,扩展的PHP版本、架构、线程安全模式,必须和你的PHP完全一致。
我去年帮一个Windows用户装扩展,他的PHP是7.3 x86(32位),却下了7.4 x64(64位)的扩展,结果php.ini里加了extension=redis
,重启后PHP直接报错“无法加载模块”。后来我让他把版本对应上,立马就好了——记住这句话:扩展的“PHP版本+架构+线程安全”,必须和你的PHP一模一样!
具体怎么装?分两种情况:
Linux系统(以PHP7.4为例):
sudo apt-get install php-pear
;pecl install redis
——PECL会自动下载对应版本的扩展;/etc/php/7.4/apache2/php.ini
),在最后加一行extension=redis.so
;sudo systemctl restart apache2
(Apache)或者sudo systemctl restart php-fpm
(Nginx);phpinfo.php
(内容是
)——如果看到“Redis”的 section,说明装好了!Windows系统:
phpinfo.php
,看“PHP Version”(比如7.4.33)、“Architecture”(x86/x64)、“Thread Safety”(enabled/disabled);php_redis-5.3.7-7.4-ts-vc15-x64.zip
;redis.dll
复制到PHP的ext
目录(比如C:phpext
);extension=redis
(不用写.dll
,PHP会自动找);第三步:测试连接——用10行代码确认“能通话”
装好了服务器和扩展,接下来要确认“PHP能和Redis说话”。写个简单的脚本(比如test_redis.php
):
<?php // 创建Redis实例
$redis = new Redis();
// 连接Redis:地址是本地(127.0.0.1),端口是默认的6379
$connected = $redis->connect('127.0.0.1', 6379);
if (!$connected) {
die('连接失败:检查Redis是否启动,端口对不对');
}
// 如果Redis设了密码,加这行(比如密码是123456)
// $redis->auth('123456');
// 存个值:键是“test_key”,值是“hello redis”
$redis->set('test_key', 'hello redis');
// 取出来看看
$value = $redis->get('test_key');
echo '从Redis拿到的值:' . $value;
// 关闭连接(可选,PHP会自动关)
$redis->close();
?>
运行这个脚本,如果输出“从Redis拿到的值:hello redis”,说明连接成功!如果报错“Connection refused”,先检查Redis服务器是不是在运行(Windows看有没有redis-server.exe
窗口,Linux用systemctl status redis
);如果报错“Authentication required”,说明Redis设了密码,要加auth
方法。
PHP操作Redis的核心用法:从基础到实战
连接成功后,接下来就是“用Redis解决真问题”了。别被“缓存策略”“穿透击穿”这些词吓到——先从“存数据、取数据”的基础操作开始,再讲实战场景。我去年帮电商项目调缓存时,就是从“存商品列表”开始,一步步解决了页面加载慢的问题。
基础操作:增删改查的“笨办法”
Redis的核心是“键值对”(key-value),比如你要存“商品1的名称”,键可以是goods:name:1
,值是iPhone 15
。PHP操作Redis的方法,基本和Redis命令一一对应,我 了个“常用方法表”,直接照用就行:
Redis命令 | PHP方法 | 说明 |
---|---|---|
SET | set($key, $value) | 存键值对(永久有效) |
GET | get($key) | 取键对应的值 |
DEL | del($key) | 删除键(可传多个键) |
EXPIRE | expire($key, $seconds) | 设过期时间(秒) |
SETEX | setex($key, $seconds, $value) | 存值+设过期(一步完成) |
MSET | mset($array) | 批量存键值对(比多次set快) |
MGET | mget($keys) | 批量取键对应的值 |
这里要强调一个新手必犯的错误:忘了设过期时间。去年帮一个电商项目调缓存,他们存商品列表用了set
,没设expire
,结果管理员修改了商品价格,用户刷新页面还是旧价格——因为缓存没过期,Redis一直返回旧值。后来我让他们把set
改成setex
(比如setex('goods:list:1', 1800, $data)
,1800秒=30分钟),问题立马解决。记住:所有缓存键都要设过期时间,哪怕设24小时,也比永久存好!
实战场景1:商品列表缓存——把数据库查询从“每秒20次”降到“1次”
假设你有个电商网站,商品列表页的SQL是SELECT FROM goods WHERE category_id=1 ORDER BY id DESC LIMIT 10
——每次用户访问都要查数据库,20个用户同时访问,数据库每秒被查20次,肯定慢。用Redis缓存的步骤,我去年在项目里用过,效果立竿见影:
分类ID
当参数,比如goods:list:category:1
(分类1的商品列表);serialize
转成字符串);del('goods:list:category:1')
),下次用户访问会重新查数据库并更新缓存。具体代码:
<?php function getGoodsList($categoryId) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$cacheKey = "goods:list:category:{$categoryId}";
//
先查缓存
$cacheData = $redis->get($cacheKey);
if ($cacheData !== false) {
// 缓存存在,反序列化返回
return unserialize($cacheData);
}
//
缓存不存在,查数据库
$pdo = new PDO('mysql:host=localhost;dbname=shop', 'root', '123456');
$stmt = $pdo->prepare("SELECT FROM goods WHERE category_id = ? ORDER BY id DESC LIMIT 10");
$stmt->execute([$categoryId]);
$goodsList = $stmt->fetchAll(PDO::FETCH_ASSOC);
//
存缓存:设30分钟过期
$redis->setex($cacheKey, 1800, serialize($goodsList));
return $goodsList;
}
?>
用了这个函数后,商品列表页的数据库查询次数从每秒20次降到了每秒1次(只有缓存过期时才查),页面加载时间从3秒降到了0.5秒——用户再也没反馈“加载慢”了。
实战场景2:解决“缓存穿透”——避免不存在的键反复查数据库
什么是“缓存穿透”?比如有人用不存在的商品ID(比如id=99999
)反复请求接口,每次都要查数据库(因为缓存里没有),导致数据库压力变大。我之前遇到过这种情况:有人用脚本每秒发10次id=99999
的请求,数据库每秒被查10次——用Redis就能“挡回去”。
解决方法很简单:如果数据库里没有这个商品,就往Redis里存一个“空值”,设1分钟过期。这样下次再查这个ID,直接返回空值,不用查数据库。
具体代码:
<?php function getGoodsInfo($goodsId) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$cacheKey = "goods:info:{$goodsId}";
$cacheData = $redis->get($cacheKey);
if ($cacheData !== false) {
// 缓存是“empty”,返回null
return $cacheData === 'empty' ? null unserialize($cacheData);
}
// 查数据库
$pdo = new PDO('mysql:host=localhost;dbname=shop', 'root', '123456');
$stmt = $pdo->prepare("SELECT * FROM goods WHERE id = ?");
$stmt->execute([$goodsId]);
$goodsInfo = $stmt->fetch(PDO::FETCH_ASSOC);
if ($goodsInfo) {
// 存商品信息,设1小时过期
$redis->setex($cacheKey, 3600, serialize($goodsInfo));
} else {
// 存空值,设1分钟过期
$redis->setex($cacheKey, 60, 'empty');
}
return $goodsInfo;
}
?>
用了这个方法后,第一次查id=99999
返回空,存了“empty”到Redis,接下来的59秒里,所有请求都直接返回null,数据库压力一下就降下来了。
给新手的“避坑清单”
最后再分享几个我踩过的坑,帮你少走弯路:
key_123
这种随机名,要用“模块:属性:ID”的格式(比如user:token:123
)——否则过一周你自己都不知道存的是什么。Windows下用Redis最烦的就是这点——打开命令行启动Redis,一关窗口服务就停了。上次我帮朋友的PHP美食博客调缓存,他关了命令行去煮面,回来发现网站直接报错“Redis连接失败”,查了半天才反应过来是Redis停了。其实解决办法特简单,把Redis装成Windows的系统服务就行,跟装个后台程序似的,不用一直开着命令行。
你先右键点“命令提示符”,选“以管理员身份运行”—— 这步很重要,不然权限不够命令执行不了。然后切换到你Redis的安装目录,比如C盘里的redis文件夹(比如输入“cd C:redis”)。接着敲这么一行命令:“redis-server service-install redis.windows.conf loglevel verbose”,按回车。这行命令就是把Redis注册成系统服务,后面的“redis.windows.conf”是默认的配置文件,“loglevel verbose”是让Redis记录详细日志,方便后面排查问题,不用改直接用就行。装完服务,再输“redis-server service-start”启动Redis,这时候你打开任务管理器看后台进程,能找到redis-server.exe在跑—— 就算你关了命令行窗口,它也会一直后台运行。更省心的是,下次电脑重启,Redis会自己启动,不用你再手动点redis-server.exe了。我朋友之前每天开机都要手动启动一次,现在跟我说“终于不用记着这事了”。对了,要是你想临时停服务,输“redis-server service-stop”就行;要是以后不用了,输“redis-server service-uninstall”卸载服务,都是一条命令的事,特简单。
PHP提示“Class ‘Redis’ not found”怎么办?
这个错误说明PHP未加载Redis扩展。需按3步排查:①确认扩展版本与PHP的版本、架构(x86/x64)、线程安全模式(TS/NT)完全匹配;②检查php.ini配置文件中是否添加了扩展指令(Windows写“extension=redis”,Linux写“extension=redis.so”);③重启Web服务器(如Apache/Nginx)或PHP-FPM,再通过phpinfo()查看Redis扩展是否成功加载。
Redis连接提示“Connection refused”怎么解决?
优先排查3个核心原因:①Redis服务器未启动——Linux用“systemctl status redis”查看状态,Windows需确保redis-server.exe处于运行中;②端口不匹配——Redis默认端口是6379,确认PHP连接时用的端口一致;③防火墙拦截——Linux通过“ufw allow 6379”(Ubuntu)或“firewall-cmd add-port=6379/tcp permanent”(CentOS)开放端口,Windows关闭防火墙或添加6379端口的入站规则。
数据库更新后,缓存还是旧数据怎么办?
这是缓存与数据库未同步导致的。解决方法有2种:①手动更新缓存——修改数据库数据后,立即删除对应的缓存键(比如修改分类1的商品,执行“del(‘goods:list:category:1’)”);②自动过期更新——给缓存键设合理的过期时间(比如商品列表设30分钟),即使没手动删除,过期后也会重新从数据库拉取最新数据。
Windows下关闭Redis命令行后服务就停了,怎么后台运行?
可以将Redis安装为Windows系统服务:①以管理员身份打开命令行,进入Redis安装目录(如C:redis);②执行“redis-server service-install redis.windows.conf loglevel verbose”安装服务;③执行“redis-server service-start”启动服务。这样Redis会后台运行,重启电脑后也会自动启动,无需保持命令行窗口打开。
为什么缓存键必须设过期时间?
主要避免2个问题:①数据不一致——如果缓存永久有效,数据库更新后用户看到的还是旧数据;②内存溢出——Redis内存有限,永久缓存会逐渐占满内存,导致新缓存无法存储。 根据数据更新频率设过期时间:比如商品价格设30分钟,用户登录态设2小时,静态配置设24小时。