redis
一、安装
1. 源码安装
# 下载源码包(若链接失效,替换为官网最新地址)
wget https://download.redis.io/releases/redis-7.2.4.tar.gz
# 解压源码包
tar -zxvf redis-7.2.4.tar.gz
# 进入解压目录
cd redis-7.2.4
# 编译(需等待几分钟,依赖 gcc 环境)
make
# 安装(默认安装到 /usr/local/bin 目录)
make install PREFIX=/usr/local/redis # PREFIX 指定安装路径,可选
# 创建配置文件目录
mkdir -p /usr/local/redis/conf
# 复制源码中的默认配置文件到安装目录
cp redis.conf /usr/local/redis/conf/
# 修改配置文件
# 修改内容:bind 127.0.0.1(或0.0.0.0)、protected-mode no、daemonize yes、requirepass 密码
vim /usr/local/redis/conf/redis.conf
# 设置开机启动
vim /usr/lib/systemd/system/redis.service
# 写入以下内容 -- begin---
[Unit]
Description=Redis Server
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf
ExecStop=/usr/local/redis/bin/redis-cli -a 你的密码 shutdown
Restart=always
[Install]
WantedBy=multi-user.target
# 写入以下内容 -- end ---
# 刷新 systemd 配置
systemctl daemon-reload
# 启动 Redis
systemctl start redis
# 开机自启
systemctl enable redis
# 查看状态
systemctl status redis
# 创建软链接
ln -s /usr/local/redis/bin/redis-cli /usr/bin/redis-cli
2. docker安装
# 创建Redis数据存储目录(宿主机)
mkdir -p /opt/redis/data
# 启动Redis容器(核心命令)
docker run -d \
--name redis-server \ # 容器名称
--restart always \ # 开机自启
-p 6379:6379 \ # 端口映射(宿主机:容器)
-v /opt/redis/data:/data \ # 数据卷挂载(持久化)
-e REDIS_PASSWORD=yourpassword \ # Redis密码
redis:latest \ # Redis镜像版本
redis-server --appendonly yes # 开启AOF持久化
3. docker-compose安装
version: '3.8'
services:
redis:
image: redis:latest # Redis镜像
container_name: redis-server # 容器名称
restart: always # 开机自启
ports:
- "6379:6379" # 端口映射
environment:
- REDIS_PASSWORD=yourpassword # Redis密码
- REDIS_PORT=6379 # Redis端口
volumes:
- ./data:/data # 数据持久化(相对路径,宿主机./data映射容器/data)
# 可选:挂载自定义redis.conf配置文件
# - ./redis.conf:/etc/redis/redis.conf
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
networks:
- redis-network # 自定义网络(隔离性更好)
# 自定义网络(可选,增强容器网络隔离)
networks:
redis-network:
driver: bridge
二、 连接
- 连接
redis-cli -h host -p port -a 'password' - 切换数据库
select 2 - 当前库key数量
dbsize - 清空当前库
flushdb - 清空所有库
flushall
三、 数据类型
1. 键Key
| 命令 | 描述 | 示例 |
|---|---|---|
| EXISTS | 检查给定 key 是否存在 | |
| EXPIRE | 为给定 key 设置过期时间,单位秒 | EXPIRE key 1000 |
| EXPIREAT | 用于为 key 设置过期时间,接受的时间参数是 UNIX 时间戳,即时间戳时间到期 | EXPIREAT key timestamp |
| PEXPIRE | 设置 key 的过期时间,以毫秒计 | |
| PEXPIREAT | 设置 key 过期时间的时间戳(unix timestamp),以毫秒计 | |
| DEL | 用于删除 key | |
| KEYS | 查找所有符合给定模式的 key | KEYS * / KEYS kk** |
| MOVE | 将当前数据库的 key 移动到给定的数据库中 | |
| PERSIST | 移除 key 的过期时间,key 将持久保持 | |
| PTTL | 以毫秒为单位返回 key 的剩余的过期时间 | |
| TTL | 以秒为单位,返回给定 key 的剩余生存时间 | |
| RENAME | 修改 key 的名称 | |
| RENAMENX | 仅当 newkey 不存在时,将 key 改名为 newkey | |
| TYPE | 返回 key 所储存的值的类型 |
2. 字符串 String
- 常用命令
# 添加键值对,key已存在时,会覆盖
set mykey somevalue
# 只有在key不存在时,设置key的值,已存在key时,无法设置
setnx kk vv1sdsds
# 查询对应键值
get mykey
# 将给定的<value> 追加到原值的末尾
append kk hahaha999
# 获得值的长度
strlen kk
# 同时添加多个键值对
mset k1 v1 k2 v2 k3 v3
# 同时获取多个键值
mget k1 k2
# 同时添加多个键值对,当其中某个KEY存在时,则都不会添加
msetnx k4 v4 k3 vv3
# 获得值的范围,从0开始,包含开始结束位置
getrange k1 0 2
# 从1位置开始覆盖k1的值为zxcv
setrange k1 1 zxcv
# 设置k1的值,并设置10秒后过期
setex k1 10 vv2
# 获取k1原来的值,并设置新的值为vvv1
getset k1 vvv1
- 原子操作incr/decr
# +1
incr inkey
# -1
decr dekey
# +10
incrby inkey 10
# -100
decrby dekey 100
3. 列表 List
# 向list集合头部添加元素1
lpush list 1
# 向list集合尾部添加元素2
rpush list 2
# 移除list第一个元素并返回
lpop list
# 移除list最后一个元素并返回
rpop list
# 移除list最后一个元素并放入list1的第一位置
rpoplpush list list1
# 查看list0-3位置的元素
lrange list 0 3
# 获取list 0索引位置的元素
lindex list 0
# 查看list长度
llen list
# 在list的v3元素后添加v4
linsert list after v3 v4
# 从尾到头开始,移除1个v1
lrem list -1 v1
# 替换0位置的元素为v0
lset list 0 v0
4. 哈希 Hash
# 添加一个hash对象,并添加name和age
hset hashkey name zhangsan age 18
# 查看hash对象的name字段对应的值
hget hashkey name
# 添加一个user对象,并添加相关属性
hmset user name lisi age 18 sex 男
# 查看user对象是否有score属性
hexists user score
# 查看user所有属性
hkeys user
# 查看user所有属性值
hvals user
# 给user的age属性值+3
hincrby user age 3
# 给user添加score为90
hsetnx user score 90
四、 发布订阅
# 订阅频道
127.0.0.1:6379> subscribe demo-channel
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "demo-channel"
3) (integer) 1
# 开启另外一个客户端,发送信息
127.0.0.1:6379> publish demo-channel hello
(integer) 1
# 订阅的客户端会接收到消息
1) "message"
2) "demo-channel"
3) "hello"
五、 LUA脚本
- 函数定义
optional_function_scope function function_name( argument1, argument2, argument3..., argumentn) function_body return result_params_comma_separated end - 示例
- 设置key为foo的值为bar
eval "return redis.call('set',KEYS[1],'bar')" 1 foo- 脚本
-- checkandset.lua -- 获取一个Key的值 local current = redis.call('GET', KEYS[1]) -- 如果这个值等于传入的第一个参数 if current == ARGV[1] -- 设置这个Key的值为第二个参数 then redis.call('SET', KEYS[1], ARGV[2]) return true end -- 如果这个值不等于传入的第一个参数,直接返回false return false
六、 Redis常见问题
-
缓存穿透
- 一些恶意的请求会故意大量查询不存在的key,就会对数据库造成很大的压力。这就叫做缓存穿透。
- null值缓存、接口校验、访问限制、布隆过滤器
-
缓存雪崩
- 缓存雪崩是指由于缓存服务宕机,导致大量请求直接访问数据库,导致数据库压力过大甚至宕机。
- 高可用缓存、限流降级、预热缓存、过期时间均匀分布
-
缓存击穿
- 缓存击穿是指一个热点key突然失效,导致大量请求直接访问数据库。
- 热点数据永远不过期、互斥锁
七、 锁
秒杀逻辑
redis Pipeline
Feed流
重名 推送 统计