#Linux数据库管理Day07:Redis基础,Redis结合LNMP
一、Redis 概述
1.1 基本定义
Redis 全称 Remote Dictionary Server(远程字典服务器),是一款高性能的键值对(Key/Value)分布式内存数据库,支持数据持久化(定期把内存里的数据存储到硬盘),同时支持多种数据类型与主从复制备份。
官方中文站点:www.redis.cn
1.2 核心特点
在大数据、高并发场景下应用广泛,核心特性如下:
- 高性能:数据全部存储在内存中,读写速度极快
- 持久化:支持 RDB 快照、AOF 日志两种持久化方式,保障数据安全可靠
- 多数据类型支持:包含字符串(string)、哈希(hash)、列表(list)、集合(set)等,适配不同业务场景
- 分布式部署:支持集群模式,实现数据高可用与负载均衡
- 丰富的功能:支持事务、发布订阅、Lua 脚本、管道(pipeline)等高级功能
缓存的作用是提升读写速度。并非所有数据都适合缓存,仅热点数据需要做缓存
1.3 典型应用场景
- 计数器与排行榜:利用 Redis 原子递增命令实现高性能计数器;通过有序集合实现排行榜功能
- 分布式锁:通过
SETNX命令配合过期时间实现分布式锁,避免多线程/多节点同时修改资源 - 实时消息系统:基于发布/订阅模式、Stream 数据结构实现轻量级实时消息,适配在线聊天、消息推送等场景
- 日志收集:利用 List 数据结构作为消息队列,实现日志收集与异步消费
- 会话管理:基于高性能内存存储实现 Web 应用的 Session 统一管理,提升访问性能
1.4 实验环境说明
本次实验使用单台 Redis 主机完成所有部署与操作。
| 主机名 | IP地址 |
|---|---|
| redis-1 | 192.168.8.122 |
二、Redis 安装与基础服务管理
本次实验使用源码包 redis-4.0.8.tar.gz 进行编译安装。
2.1 编译安装步骤
- 安装编译依赖
[root@redis-1 ~]# yum -y install gcc make
- 解压源码包并进入目录
[root@redis-1 ~]# tar -xf redis-4.0.8.tar.gz
[root@redis-1 ~]# cd redis-4.0.8/
- 编译并安装
[root@redis-1 redis-4.0.8]# make
[root@redis-1 redis-4.0.8]# make install
2.2 服务初始化(官方脚本)
Redis 源码提供 install_server.sh 初始化脚本,可一键配置服务、设置开机自启。
执行脚本后可自定义端口、配置文件路径等,全部回车则使用默认值:
[root@redis-1 ~]# cd redis-4.0.8/
[root@redis-1 redis-4.0.8]# ./utils/install_server.sh #执行初始化脚本
交互流程与默认配置:
Welcome to the redis service installer
This script will help you easily set up a running redis server
Please select the redis port for this instance: [6379] #监听端口
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf] #配置文件名
Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log] #日志位置
Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379] #文件存储位置
Selected default - /var/lib/redis/6379
Please select the redis executable path [/usr/local/bin/redis-server] #主程序位置
Selected config:
Port : 6379
Config file : /etc/redis/6379.conf
Log file : /var/log/redis_6379.log
Data dir : /var/lib/redis/6379
Executable : /usr/local/bin/redis-server
Cli Executable : /usr/local/bin/redis-cli
Is this ok? Then press ENTER to go on or Ctrl-C to abort.
Copied /tmp/6379.conf => /etc/init.d/redis_6379
Installing service...
Successfully added to chkconfig! #设置开机自启动
Successfully added to runlevels 345! #在345级别开机自启动
Starting Redis server... #启动Redis服务
Installation successful!
[root@redis-1 redis-4.0.8]# cd #回到家目录
2.3 服务管理命令
- 查看端口监听状态
[root@redis-1 ~]# ss -antpu | grep redis
tcp LISTEN 0 128 127.0.0.1:6379 : users:(("redis-server",pid=4335,fd=6))
- 服务脚本路径
[root@redis-1 ~]# ls /etc/init.d/redis_6379
/etc/init.d/redis_6379
- 启停与状态查看
[root@redis-1 ~]# /etc/init.d/redis_6379 stop # 停止服务
[root@redis-1 ~]# /etc/init.d/redis_6379 start # 启动服务
[root@redis-1 ~]# /etc/init.d/redis_6379 status # 查看服务状态
Redis is running (4361)
2.4 Redis 连接方式
客户端工具为 redis-cli,支持多种连接形式:
- 格式:
redis-cli -h 主机地址 -p 端口号 -a "密码"
- 标准连接(指定地址、端口、密码)
[root@redis-1 ~]# redis-cli -h localhost -p 6379 -a ""
localhost:6379> PING
PONG
localhost:6379> EXIT
- 默认本地连接
[root@redis-1 ~]# redis-cli
127.0.0.1:6379> PING
PONG
127.0.0.1:6379> EXIT
- 非交互模式直接执行命令
[root@redis-1 ~]# redis-cli PING
PONG
2.5 常用基础操作指令
1. Key 通用操作
Redis 基础命令整理表
| 命令示例 | 功能说明 | 返回结果说明 |
|---|---|---|
KEYS * | 查询当前数据库中所有键名 | 无数据返回 (empty list or set);有数据列出全部key |
KEYS a* | 模糊匹配:查询以 a 开头的所有键 | 仅输出前缀匹配成功的key |
KEYS ??? | 模糊匹配:查询名称为3个字符的键 | ? 代表单个任意字符 |
SET name zhangsan | 单个String键值写入,覆盖原有值 | OK 代表设置成功 |
MSET age 25 gender male class class1 | 批量一次性写入多组String键值(原子操作) | OK 代表全部设置成功 |
GET name | 获取单个key对应的value | 返回对应字符串,键不存在返回 (nil) |
MGET name age | 批量查询多个key的值 | 按输入顺序依次返回对应value |
EXISTS name | 判断指定key是否存在 | (integer) 1=存在;(integer) 0=不存在 |
TTL age | 查看key剩余过期时间 | -1=永久不过期;正数=剩余秒数;-2=键已过期/不存在 |
EXPIRE age 10 | 给指定key设置过期时间(单位:秒) | (integer) 1=设置成功;0=键不存在设置失败 |
LPUSH students tom jim bob | 左侧插入数据(列表的开头位置即索引为 0 的位置),创建/操作List列表类型 | 返回列表当前元素总个数 |
TYPE name | 查看指定key的数据类型 | 输出 string/list/hash/set 等类型名 |
MOVE students 10 | 将当前库的key移动到指定编号数据库 | (integer) 1=移动成功;0=键不存在或目标库已有同名键 |
SELECT 10 | 切换Redis数据库(默认0号,范围0~15) | OK 切换完成,提示符后缀显示库编号 |
SAVE | 同步持久化,将内存数据写入RDB磁盘文件 | OK 持久化完成 |
DEL class | 删除指定单个key | 返回成功删除的键数量 |
FLUSHDB | 清空当前所选数据库全部键 | OK 清空完成 |
FLUSHALL | 清空所有16个数据库全部键 | OK 清空完成 |
SHUTDOWN | 关闭Redis服务进程 | 断开客户端连接,提示符变为 not connected> |
EXIT | 退出 redis-cli 客户端连接 | 直接退回服务器终端 |
redis-cli | 服务器终端登录Redis客户端 | 进入 127.0.0.1:6379> 交互界面 |
补充注意点:
KEYS命令线上环境禁止使用,海量键会阻塞Redis,生产使用SCAN迭代遍历;MSET是原子命令,批量写入要么全部成功,要么全部不生效;FLUSHDB / FLUSHALL属于高危删除命令,操作前务必备份数据;- Redis 默认提供 0~15 共16个独立数据库,库之间数据完全隔离。
[root@redis-1 ~]# redis-cli
# 查看当前库所有key
127.0.0.1:6379> KEYS *
(empty list or set)
# 查看以a开头的key
127.0.0.1:6379> KEYS a*
"age"
# 查看名称长度为3个字符的key
127.0.0.1:6379> KEYS ???
"age"
# 判断key是否存在,返回1存在,0不存在
127.0.0.1:6379> EXISTS name
(integer) 1
127.0.0.1:6379> EXISTS hahaha
(integer) 0
# 查看key剩余生命周期,-1表示永久有效,-2表示key不存在/已过期
127.0.0.1:6379> TTL age
(integer) -1
# 给key设置过期时间(单位:秒)
127.0.0.1:6379> EXPIRE age 10
(integer) 1
127.0.0.1:6379> TTL age
(integer) 9
127.0.0.1:6379> TTL age
(integer) 1
127.0.0.1:6379> TTL age
(integer) -2
# 查看key的数据类型
127.0.0.1:6379> TYPE name
string
127.0.0.1:6379> TYPE students
list
# 删除指定key
127.0.0.1:6379> DEL class
(integer) 1
2. String 字符串类型操作
# 存储单个字符串key
127.0.0.1:6379> SET name zhangsan
OK
# 批量存储多个字符串key
127.0.0.1:6379> MSET age 25 gender male class class1
OK
# 获取单个字符串值
127.0.0.1:6379> GET name
"zhangsan"
# 批量获取多个值
127.0.0.1:6379> MGET name age
"zhangsan"
"25"
3. List 列表类型操作
# 从左侧向列表插入元素(创建列表)
127.0.0.1:6379> LPUSH students tom jim bob
(integer) 3
4. 数据库切换与移动
Redis 默认提供 16 个数据库(编号 0-15),默认操作 0 号库:
# 将key移动到指定编号的库
127.0.0.1:6379> MOVE students 10
(integer) 1
# 切换到指定编号的库
127.0.0.1:6379> SELECT 10
OK
127.0.0.1:6379[10]> KEYS *
"students"
# 切回0号库
127.0.0.1:6379[10]> SELECT 0
OK
5. 持久化与清空操作
# 手动触发RDB持久化,将内存数据保存到磁盘
127.0.0.1:6379> SAVE
OK
# 清空当前库所有数据
127.0.0.1:6379> FLUSHDB
OK
# 清空所有库的所有数据,需慎重
127.0.0.1:6379> FLUSHALL
OK
# 关闭Redis服务
127.0.0.1:6379> SHUTDOWN
not connected> EXIT
三、Redis 常用配置与进阶设置
配置文件默认路径:/etc/redis/6379.conf
3.1 核心配置项说明
常用配置项与示例:
| 配置项 | 作用 | 示例值 |
|---|---|---|
bind | 监听的IP地址,默认127.0.0.1仅本地访问 | 192.168.8.122 |
protected-mode | 保护模式,开启后限制远程访问 | no |
port | 服务监听端口 | 6351 |
pidfile | PID文件路径 | /var/run/redis_6379.pid |
loglevel | 日志级别 | notice |
logfile | 日志文件路径 | /var/log/redis_6379.log |
databases | 数据库数量 | 16 |
dir | 数据持久化文件存储目录 | /var/lib/redis/6379 |
requirepass | 连接认证密码 | 123456 |
配置文件快速查看命令:
[root@redis-1 ~]# vim /etc/redis/6379.conf
[root@redis-1 ~]# cat -n /etc/redis/6379.conf | sed -rn '70p;89p;93p;159p;167p;172p;187p;264p;501p'
70 bind 192.168.8.122 #修改监听地址
89 protected-mode no #关闭保护模式
93 port 6351 #监听端口修改为6351
159 pidfile /var/run/redis_6379.pid
167 loglevel notice
172 logfile /var/log/redis_6379.log
187 databases 16
264 dir /var/lib/redis/6379
501 requirepass 123456 #设置连接密码为12345
3.2 修改配置后启动与连接测试
- 启动服务并验证端口
[root@redis-1 ~]# /etc/init.d/redis_6379 start #如果服务已在运行就使用restart(restart只能在运行时使用)
[root@redis-1 ~]# ss -pantul | grep redis
tcp LISTEN 0 128 192.168.8.122:6351 : users:(("redis-server",pid=4486,fd=6))
- 连接测试(两种认证方式)
- 方式1:登录时直接携带密码
[root@redis-1 ~]# redis-cli -h 192.168.8.122 -p 6351 -a "123456"
192.168.8.122:6351> PING
PONG
192.168.8.122:6351> EXIT
- 方式2:登录后手动认证
[root@redis-1 ~]# redis-cli -h 192.168.8.122 -p 6351
192.168.8.122:6351> AUTH 123456
OK
192.168.8.122:6351> PING
PONG
192.168.8.122:6351> exit
3.3 服务管理脚本Bug处理
问题现象
修改监听地址与端口后,使用默认脚本停止服务失败:
[root@redis-1 ~]# /etc/init.d/redis_6379 stop
Stopping ...
Could not connect to Redis at 127.0.0.1:6379: Connection refused
Waiting for Redis to shutdown ...
Waiting for Redis to shutdown ...
原因:脚本默认使用 127.0.0.1:6379 连接服务执行shutdown,修改地址/端口后连接失败,无法正常停止。
解决方案
- 方案1:直接用redis-cli连接真实地址执行关闭
[root@redis-1 ~]# redis-cli -h 192.168.8.122 -p 6351 -a "123456" shutdown
- 方案2:修改服务脚本,改用pkill结束进程
[root@redis-1 ~]# vim /etc/init.d/redis_6379
# 注释原有的cli关闭命令,添加pkill命令
# $$CLIEXEC -p $$REDISPORT shutdown
pkill redis-server
修改后测试启停:
[root@redis-1 ~]# /etc/init.d/redis_6379 start
Starting Redis server...
[root@redis-1 ~]# /etc/init.d/redis_6379 stop
Stopping ...
Waiting for Redis to shutdown ...
Redis stopped
[root@redis-1 ~]# /etc/init.d/redis_6379 status
cat: /var/run/redis_6379.pid: No such file or directory
Redis is running ()
3.4 内存管理与数据淘汰策略
核心概念
当 Redis 内存使用达到 maxmemory 设置的上限时,再写入新数据,Redis 会按照 maxmemory-policy 指定的策略自动淘汰已有key,腾出内存空间。若不配置maxmemory,Redis默认无内存上限,不会触发淘汰。
配置项说明
[root@redis-1 ~]# vim /etc/redis/6379.conf
[root@redis-1 ~]# sed -rn '560p;565,572p;591p' /etc/redis/6379.conf
#将配置文件中第560行,565到572行,591行行首的#去掉
maxmemory <bytes> #配置Redis的最大可用内存,不配置默认无限占用,不会触发淘汰
volatile-lru -> Evict using approximated LRU among the keys with an expire set.
allkeys-lru -> Evict any key using approximated LRU.
volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
allkeys-lfu -> Evict any key using approximated LFU.
volatile-random -> Remove a random key among the ones with an expire set.
allkeys-random -> Remove a random key, any key.
volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
noeviction -> Don't evict anything, just return an error on write operations.
maxmemory-policy noeviction # 内存淘汰策略,默认noeviction
8种淘汰策略详解(了解)
| 策略分类 | 策略名称 | 作用范围 | 淘汰规则 |
|---|---|---|---|
| LRU(删除最近最少使用) | volatile-lru | 仅设置了过期时间的key | 淘汰最近最少使用的key |
allkeys-lru | 所有key | 淘汰最近最少使用的key | |
| LFU(删除使用频率最低) | volatile-lfu | 仅设置了过期时间的key | 淘汰使用频率最低的key |
allkeys-lfu | 所有key | 淘汰使用频率最低的key | |
| RANDOM(随机删除) | volatile-random | 仅设置了过期时间的key | 随机删除key |
allkeys-random | 所有key | 随机删除key | |
volatile-ttl | 删除即将过期的key | ||
noeviction (不淘汰) | 不删除任何key |
四、LNMP+Redis 架构部署(重点)
4.1 LNMP 基础环境搭建
需要注意的是,连接redis和数据库的都是php代码
4.1.1 部署 MySQL 服务
# 安装MySQL服务
[root@redis-1 ~]# dnf -y install mysql mysql-server
# 设置开机自启并立即启动
[root@redis-1 ~]# systemctl enable mysqld --now
# 连接数据库并修改root密码
[root@redis-1 ~]# mysql
mysql> ALTER USER root@'localhost' IDENTIFIED BY "123qqq...A";
mysql> EXIT
# 验证密码登录
[root@redis-1 ~]# mysql -uroot -p'123qqq...A'
4.1.2 部署 Nginx 服务
使用源码包 nginx-1.22.1.tar.gz 编译安装:
# 安装编译依赖
[root@redis-1 ~]# yum -y install gcc pcre-devel openssl-devel
# 解压源码包
[root@redis-1 ~]# tar -xf nginx-1.22.1.tar.gz
# 创建运行用户
[root@redis-1 ~]# useradd -s /sbin/nologin nginx
# 编译配置
[root@redis-1 ~]# cd nginx-1.22.1/
[root@redis-1 nginx-1.22.1]# ./configure --prefix=/usr/local/nginx \
> --user=nginx --group=nginx --with-http_ssl_module
# 编译并安装
[root@redis-1 nginx-1.22.1]# make
[root@redis-1 nginx-1.22.1]# make install
[root@redis-1 nginx-1.22.1]# ls /usr/local/nginx/
conf html logs sbin
[root@redis-1 nginx-1.22.1]# cd
启动服务并测试:
# 启动Nginx
[root@redis-1 ~]# /usr/local/nginx/sbin/nginx
# 验证80端口监听
[root@redis-1 ~]# ss -pantu | grep 80
tcp LISTEN 0 128 *:80 : users:(("nginx",pid=7523,fd=6),("nginx",pid=7522,fd=6))
# 创建自定义首页
[root@redis-1 ~]# echo "nginx" > /usr/local/nginx/html/index.html
# 访问测试
[root@redis-1 ~]# curl http://localhost/
nginx
4.1.3 部署 PHP 与动静分离
- 安装PHP与扩展
[root@redis-1 ~]# yum -y install php php-fpm php-mysqlnd
说明:
php-mysqlnd是PHP的MySQL原生驱动扩展,提供PHP连接MySQL数据库的能力。
- 修改PHP-FPM配置
[root@redis-1 ~]# vim /etc/php-fpm.d/www.conf
# 修改为TCP端口监听,注释默认的sock文件
listen = 127.0.0.1:9000
;listen = /run/php-fpm/www.sock
- 启动PHP-FPM并验证端口
[root@redis-1 ~]# systemctl enable php-fpm --now
[root@redis-1 ~]# ss -pantul | grep 9000
tcp LISTEN 0 128 127.0.0.1:9000 : users:(("php-fpm",pid=7618,fd=0),("php-fpm",pid=7617,fd=0),("php-fpm",pid=7616,fd=0),("php-fpm",pid=7615,fd=0),("php-fpm",pid=7614,fd=0),("php-fpm",pid=7613,fd=6))
- 配置Nginx动静分离
[root@redis-1 ~]# vim /usr/local/nginx/conf/nginx.conf
# 找到PHP配置段,修改为如下内容
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
# 重载Nginx配置
[root@redis-1 ~]# /usr/local/nginx/sbin/nginx -s reload
- PHP功能测试
# 编写测试文件
[root@redis-1 ~]# vim /usr/local/nginx/html/test.php
<?PHP
echo "hello\n";
?>
# 命令行验证语法
[root@redis-1 ~]# php /usr/local/nginx/html/test.php
hello
# 网页访问测试
[root@redis-1 ~]# curl http://localhost/test.php
hello
4.1.4 LNMP 连通性测试
编写PHP页面连接MySQL并查询数据:
[root@redis-1 ~]# cp /root/mysql.php /usr/local/nginx/html/
[root@redis-1 ~]# vim /usr/local/nginx/html/mysql.php
<?php
$mysqli = new mysqli('localhost','root','123qqq...A','mysql');
if (mysqli_connect_errno()){
die('Unable to connect!'). mysqli_connect_error();
}
$sql = "select * from user";
$result = $mysqli->query($sql);
while($row = $result->fetch_array()){
printf("Host:%s",$row[0]);
printf("</br>");
printf("Name:%s",$row[1]);
printf("</br>");
}
?>
访问测试:
[root@redis-1 ~]# curl http://localhost/mysql.php
Host:localhost</br>Name:mysql.infoschema</br>Host:localhost</br>Name:mysql.session</br>Host:localhost</br>Name:mysql.sys</br>Host:localhost</br>Name:root</br>
4.2 PHP Redis 扩展安装
4.2.1 扩展编译安装
使用 redis-6.0.0.tgz 源码包编译PHP扩展:
# 安装PHP开发依赖
[root@redis-1 ~]# dnf -y install php-devel php-json
# 解压扩展包
[root@redis-1 ~]# tar -xf redis-6.0.0.tgz
[root@redis-1 ~]# cd redis-6.0.0/
# 使用phpize文件生成configure配置文件
[root@redis-1 redis-6.0.0]# phpize
Configuring for:
PHP Api Version: 20200930
Zend Module Api No: 20200930
Zend Extension Api No: 420200930
configure.ac:18: warning: $as_echo is obsolete; use AS_ECHO(["message"]) instead
build/php.m4:2072: PHP_CONFIG_NICE is expanded from...
configure.ac:18: the top level
configure.ac:161: warning: The macro `AC_PROG_LIBTOOL' is obsolete.
You should run autoupdate.
build/libtool.m4:100: AC_PROG_LIBTOOL is expanded from...
configure.ac:161: the top level
# 编译配置,关联当前PHP环境
[root@redis-1 redis-6.0.0]# ./configure --with-php-config=/usr/bin/php-config
# 编译并安装
[root@redis-1 redis-6.0.0]# make
[root@redis-1 redis-6.0.0]# make install
# 验证扩展文件生成
[root@redis-1 redis-6.0.0]# cd
[root@redis-1 ~]# ls /usr/lib64/php/modules/redis.so
/usr/lib64/php/modules/redis.so
4.2.2 启用 Redis 扩展
- 配置模块加载路径
[root@redis-1 ~]# cp /etc/php.ini /opt/ #备份文件
[root@redis-1 ~]# vim /etc/php.ini #修改php配置文件
# 添加扩展目录配置,#指定模块路径
737 extension_dir = "/usr/lib64/php/modules/"
- 创建扩展配置文件
注意:Redis扩展依赖json扩展,需确保json扩展先加载(先加载json再加载redis),因此命名为99-redis.ini保证加载顺序。
[root@redis-1 ~]# vim /etc/php.d/99-redis.ini
extension = redis.so #指定模块名
- 重启PHP-FPM并验证扩展
[root@redis-1 ~]# systemctl restart php-fpm
[root@redis-1 ~]# php -m | grep redis #检查php已支持redis
redis
4.3 PHP 操作 Redis 功能测试
4.3.1 基础读写测试
编写测试页面验证PHP连接Redis、读写数据:
[root@redis-1 ~]# cat /usr/local/nginx/html/redis.php
<?php
#实例化连接Redis对象
$redis = new redis();
#给实例传递参数
$redis->connect("192.168.8.122",6351);
$redis->auth("123456");
#调用set方法存变量
$redis->set("school","hopeschool");
echo "save ok\n";
#调用get方法取变量
echo $redis->get("school");
echo "\n";
?>
访问测试与数据验证:
# 网页访问测试
[root@redis-1 ~]# curl http://localhost/redis.php
save ok
hopeschool
# 登录Redis验证数据
[root@redis-1 ~]# redis-cli -h 192.168.8.122 -p 6351 -a "123456"
192.168.8.122:6351> KEYS *
"school"
192.168.8.122:6351> GET school
"hopeschool"
4.3.2 缓存联动测试(MySQL+Redis)
实现逻辑:php先查询Redis缓存,缓存存在则直接返回;缓存不存在,php直接查询MySQL,将结果写入Redis并设置5秒过期。
[root@redis-1 ~]# vim /usr/local/nginx/html/time.php
<?PHP
#实例化Redis连接对象,修改为自己的IP地址!
$redis = new Redis();
$redis->connect('192.168.8.122',6351);
$redis->auth("123456");
#调用查询方法查询Redis中是否有个time变量
$time = $redis->get('time');
#判断查询结果,如果为空则进入MySQL查询,如果不空则直接返回结果
if(empty($time)){
echo "Query From \033[31mMySQL\033[0m:\t";
#实例化MySQL连接对象
$mysqli = new mysqli('127.0.0.1','root','123qqq...A','mysql');
if (mysqli_connect_errno()){
die('Unable to connect!'). mysqli_connect_error();
}
$sql = "SELECT time(now())";
$result = $mysqli->query($sql);
$rs = $result->fetch_array();
$r=$rs[0];
#将结果存入Redis并设置该变量生命周期为5s
$redis->set("time",$r);
$redis->expire("time",5);
echo "$r";
echo "\n";
}else{
echo "Query From \033[32mRedis\033[0m:\t";
echo $time;
echo "\n";
}
?>
访问测试效果:
# 第一次访问,缓存未命中,查询MySQL
[root@redis-1 ~]# curl 192.168.8.122/time.php
Query From MySQL: 19:14:54
# 5秒内访问,缓存命中,查询Redis
[root@redis-1 ~]# curl 192.168.8.122/time.php
Query From Redis: 19:14:54
[root@redis-1 ~]# curl 192.168.8.122/time.php
Query From Redis: 19:14:54
# 5秒后缓存过期,重新查询MySQL
[root@redis-1 ~]# curl 192.168.8.122/time.php
Query From MySQL: 19:15:00
我们会发现命中缓存时,时间是不变的
五、缓存核心概念与面试考点
5.1 缓存击穿
定义
热点Key过期失效,同一时间大量并发请求无法命中缓存,瞬间全部直接访问后端数据库,导致数据库压力骤增甚至宕机。
典型场景
电商秒杀活动中,热门商品的详情缓存设置了5秒过期,过期瞬间成千上万的请求无法命中缓存,全部打到MySQL数据库。
解决方案
-
互斥锁方案
缓存失效时,只放行1个请求去数据库查询并更新缓存,其余请求等待重试,避免大量并发同时打数据库。
逻辑:查缓存为空 → 尝试获取分布式锁 → 拿到锁的请求查库并更新缓存 → 未拿到锁的请求循环重试读缓存。 -
热点Key永不过期
对高频访问的热点数据不设置过期时间,由后台定时任务主动异步更新缓存,从根源上避免热点Key过期导致的击穿问题。
5.2 缓存雪崩
定义
大量缓存Key在同一时间集体过期失效,或者Redis服务整体宕机不可用,导致海量请求同时直接访问后端数据库,引发数据库压力过载甚至崩溃。
典型场景
商品系统批量设置所有商品缓存的过期时间为10分钟,第10分钟时所有缓存同时失效,全量商品查询请求瞬间涌入MySQL。
解决方案
-
过期时间打散
给缓存的过期时间增加随机偏移量(如基础10分钟 + 随机0-300秒),让不同Key的过期时间错开,避免同一时间大量Key集体失效。 -
Redis高可用集群
搭建Redis主从集群、哨兵或集群模式,避免单节点故障导致整个缓存服务不可用,保障缓存服务的高可用性。
学习总结
- 掌握Redis内存数据库的存储特点与核心应用场景
- 掌握Redis常用数据类型的基础操作命令
- 掌握LNMP环境的部署方法,以及PHP加载Redis扩展的流程
- 掌握LNMP与Redis联动实现缓存的架构逻辑与实现方式
- 理解缓存击穿、缓存雪崩的场景与解决方案
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)