浅记Redis知识点
参考资料
- https://haozhang95.github.io/Python24/16Redis/index.html
- 面试题:https://redis.com.cn/redis-interview-questions.html
基础概念 & 面试要点
什么是 Redis?
Remote Dictionary Server(远程字典服务器)
Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可磁盘持久化的 Key-Value 数据库
提供多种语言的 API,属于 非关系型数据库(NoSQL)
传统关系型数据库遵循 ACID(原子性、一致性、隔离性、持久性)
NoSQL 多采用 CAP 定理(分区容错、可用性、一致性)进行权衡
Redis 支持的数据类型
Redis 可以存储键和不同类型的值之间的映射
键只能是 二进制安全的字符串(binary‑safe string)
值支持 5 大核心数据结构:String、Hash、List、Set、ZSet,以及高级结构如 HyperLogLog、Bitmap、Stream 等
| 类型 | 命令示例 | 适用场景 |
|---|---|---|
| String | SET key value、GET key、INCR key |
缓存、计数器、会话 ID |
| Hash | HSET user name Tom、HGETALL user |
对象/用户信息、字段级查询 |
| List | LPUSH list v1 v2、LRANGE list 0 -1 |
队列、任务列表、时间线 |
| Set | SADD set a b、SMEMBERS set、SINTER set1 set2 |
去重集合、共同好友、标签交叉 |
| ZSet | ZADD zset 10 a、ZRANGE zset 0 -1、ZREVRANK zset a |
排行榜、带权重的集合 |
| HyperLogLog | PFADD hll a b、PFCOUNT hll |
大基数去重统计(近似计数) |
| Pub/Sub | SUBSCRIBE ch、PUBLISH ch "msg" |
消息广播、实时推送 |
| 事务 | MULTI … EXEC、WATCH key |
原子批处理 |
什么是 Redis 持久化?
持久化就是 把内存的数据写到磁盘中去,防止服务宕机了导致内存数据丢失
Redis 提供了两种持久化方式
-
RDB(默认)
RDB 是 Redis DataBase 的缩写
优点是启动快、文件紧凑、适合灾备,但是可能丢失最近几秒数据-
功能核心函数
rdbSave 生成 RDB 文件
rdbLoad 从文件加载内存rdbSave将内存快照写入.rdb文件,rdbLoad从文件恢复
-
-
AOF
AOF 是 Append-only File 的缩写每执行写命令都会将 aof_buf 中的缓存写入到 AOF 文件,然后定期调用 fsync 或 fdatasync 函数进行持久化,将 AOF 文件保存到磁盘中
优点是数据完整性最高(几乎不丢失),但是文件会随时间增长,需要
BGREWRITEAOF重写压缩
Redis 的用途
Redis 的数据是存在内存中的,所以读写速度非常快
每秒可以处理超过 10 万次读写操作,是已知性能最快的 Key-Value 数据库
故 redis 被广泛应用于缓存
Redis 支持 主从复制和分布式部署,可以轻松扩展以支持更多的用户和更高的负载
主要有以下的应用场景:
-
缓存
将热点数据放到内存中,设置 内存的最大使用量 以及 淘汰策略(LRU/LFU) 来保证缓存的命中率
-
计数器
可以对 String 进行自增自减运算,从而实现计数器功能
Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量 -
会话缓存
可以使用 Redis 来统一存储多台应用服务器的会话信息
-
全页缓存(FPC)
除基本的会话 token 之外,Redis 还提供很简便的 FPC 平台
Magento、WordPress 插件可以使用 Redis 作为全页缓存后端,帮助你以最快速度加载你 曾浏览过的页面 -
查找表
查找表和缓存类似,也是利用了 Redis 快速的查找特性
可以用于存储 DNS 记录、商品 SKU但是查找表的内容不能失效,而 缓存的内容可以失效,因为缓存不作为可靠的数据来源
-
分布式锁实现
在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步
可以使用 Redis 自带的SET key value NX PX <ms>命令实现分布式锁 -
其它
Set 可以实现 交集、并集 等操作,从而实现 共同好友 等功能
ZSet 按分数排序、范围查询,可以实现 排行榜 等功能
配置
bind 127.0.0.1
绑定 ip:如果需要远程访问,可将此行注释掉,或绑定⼀个真实 ip
port 6379
端⼝,默认为 6379
daemonize yes
以守护进程运⾏(不会在命令⾏阻塞,类似于服务)
如果以非守护进程运⾏,则当前终端被阻塞
database 16
数据库数量,默认有 16 个,SELECT 0~15 切换
appendonly no
开启 AOF 持久化
appendfilename appendonly.aof
AOF 文件名
appendfsync everysec
AOF 刷盘频率
maxmemory
设置内存上限
maxmemory-policy noeviction
内存淘汰策略(volatile‑lrul, allkeys‑lru、…)
生产环境一般
appendonly yes、appendfsync everysec、maxmemory <size>+maxmemory-policy allkeys-lru
常用命令
服务器端
|
|
客户端
|
|
连接 redis 默认选择第一个数据库
数据操作
redis 是 key-value 的数据结构,每条数据都是⼀个键值对
键的类型是字符串
值的类型分为五种,字符串 string、哈希 hash、列表 list、集合 set、有序集合 zset
注意:键不能重复
- 数据操作行为
保存
删除
修改
获取
string
字符串类型是 Redis 中最为基础的数据存储类型
它在 Redis 中是 二进制安全 的,这便意味着该类型可以接受任何格式的数据
如 JPEG 图像数据或 Json 对象描述信息等
在 Redis 中,字符串类型的 Value 最多可以容纳的数据长度是 512M
如果设置的键不存在则为添加,如果设置的键已经存在则修改
-
设置键为 name,值为 Tom 的数据
SET name Tom -
获取键 name 的值,如果不存在此键则返回 nil
GET name -
设置键为 tmp,值为 Hello,过期时间为 3 秒的数据
SETEX tmp 3 Hello -
设置键为 a1 值为 python、键为 a2 值为 java、键为 a3 值为 c
MSET a1 python a2 java a3 c -
获取键 a1、a2、a3 的值
MGET a1 a2 a3 -
向键为 name 中追加值 cat
APPEND name cat -
删除键 a2、a3 及对应的值
DEL a2 a3 -
设置键 a1 的过期时间为 3 秒
如果没有指定过期时间则⼀直存在,直到使⽤ DEL 移除
EXPIRE a1 3 -
查看键 bb 剩余的有效时间
TTL bb -
查看键 a1 的值类型,为 redis ⽀持的五种类型中的⼀种
TYPE a1 -
查看键
-
查看所有键(生产环境慎用)
KEYS * -
查看名称中包含 a 的键
KEYS a*
-
-
判断键 a1 是否存在
EXISTS a1
hash
键存储的是对象,该对象可以包含多个属性
对应的值为 string 类型
-
设置键 user 的属性 name 为 Tom
HSET user name Tom -
设置键 user2 的属性 name 为 Jerry、属性 age 为 6、属性 date 为 2024
HMSET user2 name Jerry age 6 date 2024 -
获取键 user2 属性 name 的值
HGET user2 name -
获取键 user2 属性 name、age 的值
HMGET user2 name age -
获取键 user2 的所有属性
HKEYS user2 -
获取键 user2 所有属性的值
HVALS user2 -
删除键 user2 的属性 age
HDEL user2 age -
删除整个 hash 键及值
DEL user2
list
-
从键为 user 的列表左侧分别加⼊数据 Tom、Jerry
LPUSH user Tom Jerry1 21) "Jerry" 2) "Tom"-
右侧分别加⼊数据 Tom、Jerry
RPUSH user Tom Jerry1 21) "Tom" 2) "Jerry"
-
-
在键为 user 的列表中,元素 Tom 前加⼊ Spike
LINSERT user BEFORE Tom Spike1 2 31) "Jerry" 2) "Spike" 3) "Tom"-
元素 Tom 后面加⼊ Spike
LINSERT user AFTER Tom Spike1 2 31) "Jerry" 2) "Tom" 3) "Spike"
-
-
获取键为 user 的列表指定范围内的元素
LRANGE user 0 2
下标索引从 0 开始,用法类似于 python1 21) "Jerry" 2) "Spike"-
获取所有元素
LRANGE user 0 -1
-
-
修改键为 user 的列表中下标为 1 的元素值为 Tuffy
LSET user 1 Tuffy1 2 31) "Jerry" 2) "Tuffy" 3) "Tom" -
删除指定元素
从键为 alist 的列表左侧分别加⼊数据 a b a b a b
LPUSH alist a b a b a b1 2 3 4 5 61) "b" 2) "a" 3) "b" 4) "a" 5) "b" 6) "a"从右往左删除两个 b 元素
1 2LREM alist -2 b LRANGE alist 0 -11 2 3 41) "b" 2) "a" 3) "a" 4) "a"
set
无序集合,无法修改
键对应的元素具有唯一性,为 string 类型
集合没有修改操作
-
向键 user 的集合中添加元素 Tom、Jerry、Spike、Tuffy
SADD user Tom Jerry Spike Tuffy -
获取键 user 的集合中所有元素
SMEMBERS user -
删除键 user 的集合中元素 Tuffy
SREM user Tuffy
zset
有序集合,特性与 set 相同
不同之处在于,每一个元素会关联一个 double 类型的 score
表示权重,用于从小到大排序
-
向键 user 的集合中添加元素 Tom、Jerry、Spike、Tuffy
权重分别为 4、5、6、3
ZADD user 4 Tom 5 Jerry 6 Spike 3 Tuffy -
获取键 user 的集合中所有元素
ZRANGE user 0 -1 -
获取键 user 的集合中权限值在 5 和 6 之间的元素
ZRANGEBYSCORE user 5 6 -
获取键 user 的集合中元素 Tom 的权重
ZSCORE user Tom -
删除键 user 的集合中元素 Tuffy
ZREM user Tuffy -
删除键 user 的集合中权重在 5 和 6 之间的元素
ZREMRANGEBYSCORE user 5 6
HyperLogLog
比如数据集 {1, 3, 5, 7, 5, 7, 8}
那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为 5
基数估计就是在误差可接受的范围内,快速计算基数
|
|
发布订阅
发送者(在 Redis 术语中称为发布者)发送消息,而接收者(订阅者)接收消息
需要开启两个客户端
-
第一个作为接收者:
SUBSCRIBE mychannel -
第二个作为发布者:
PUBLISH mychannel "test"
PUBLISH mychannel "hello world"
PUBLISH mychannel "thank you"
事务
MULTI 用来组装一个事务
EXEC 用来执行一个事务
DISCARD 用来取消一个事务
WATCH 用来监视一些 key,一旦这些 key 在事务执行之前被改变,则取消事务的执行
与 Python 交互
先创建虚拟环境,然后在虚拟环境下安装依赖
|
|
|
|
增删改查 CRUD
|
|
作为任务队列 RQ
https://www.showapi.com/news/article/66d96abf4ddd79f11a0a9667
|
|
作为缓存
|
|
会话管理
|
|
允许开发者将用户的会话数据存储在服务器端,而不是在客户端的 cookie 中
这样可以减少 cookie 的大小,提高安全性
用户可以在不同的浏览器或设备上保持会话状态,因为会话数据存储在服务器端
可以通过设置 SESSION_PERMANENT 为 True 来持久化会话
SESSION_USE_SIGNER 启用签名,可以确保会话数据在传输过程中未被篡改,增强安全性
异步任务处理
|
|
搭建主从和集群
主从复制
一个 master 可以有多个 slave
一个 slave 又可以有多个 slave
这样就形成了强大的多级服务器集群架构
master 用来写数据
slave 用来读数据
下面在同一个主机上配置 master 和 slave 节点
-
配置 master
修改 redis 的配置文件,将 ip 绑定为本机的 ip
ifconfig执行
sudo vi redis.conf1 2 3# 编辑 /etc/redis/redis.conf bind 127.0.0.1 # 若需外部访问改为本机 IP 或注释 port 6379重启服务
1 2sudo service redis stop redis-server redis.conf -
配置 slave
将 master 的配置文件复制一份为 slave.conf
并配置 slave 的端口1 2sudo cp /etc/redis/redis.conf ./slave.conf sudo vi slave.conf1 2 3 4 5# 编辑 slave.conf port 6378 slaveof <master_ip> 6379 # 指定 master # 启动 redis-server ./slave.conf -
验证
查看配置结果
redis-cli -h ip地址 info Replication进入 master 的客户端并进行写数据
1 2redis-cli -h ip地址 -p 6379 set name Tom进入 slave 的客户端并进行写数据
1 2redis-cli -h ip地址 -p 6378 get name
集群概述
https://www.cnblogs.com/wuxl360/p/5920330.html
如果同一时间访问量过大,或者遇到自然灾害,主服务器出现宕机,会导致数据服务挂掉
集群是一组相互独立的、通过高速网络互联的计算机
可以进行负载均衡,提高可用性和可缩放性
Redis Cluster 通过水平分片(slot)把键划分到 16384 个槽中,每个槽分配给不同节点,实现自动路由、故障转移和线性扩容
-
适用场景:单机内存上限(数十 GB)无法满足、需要读写分担或高可用
-
部署要点
- 至少 3 主 + 3 从(保证多数派决议)
- 每节点
cluster-enabled yes、cluster-config-file nodes.conf、cluster-node-timeout 5000 - 使用
redis-cli --cluster create <ip1:6379> <ip2:6379> … --cluster-replicas 1初始化