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查找所有符合给定模式的 keyKEYS * / 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流

重名 推送 统计