文章目录
-
-
- 一. Redis
-
-
- 1.1 语法回顾
- 1.2 事务
- 1.3 持久化 (重点)
-
- 1.3.1 RDB 快照存储
- 1.3.1 AOF 只追加文件
- 1.3.3 如何选择
- 1.4 分布式设计
-
- 1.4.1 哨兵 (重点)
- 1.4.2 集群
-
-
一. Redis
1.1 语法回顾
- String
- 记录字符串/整数/浮点数
- 命令
- set 添加/修改数据
- get 获取数据
- mset 添加多个数据
- mget 获取多个数据
- incr 计数加1
- decr 计数减1
- incrby 计数加n
- 键命令
- 适用于所有的类型
- 命令
- del 删除数据
- exists 判断数据是否存在
- expire 设置过期时间
- ttl 获取剩余时间
- keys 查询满足条件的键
- hash
- 类似
的结构字典
- 命令
- hset 添加字段
- hget 获取字段
- hmset 添加多个字段
- hmget 获取多个字段
- hdel 删除字段
- 类似
- list
- 是一个
双向链表
- 命令
- lpush 从左侧追加元素
- lrange 从左侧遍历元素
- rpush 从右侧追加元素
- lset 从左侧修改元素
- lpop 从左侧删除元素
- rpop 从右侧删除元素
- ltrim 裁切列表
- 是一个
- zset
-
集合, 按照分数(score)进行排序有序
- 命令
- zadd 添加/修改元素
- zrange 遍历元素(按分数从小到大)
- zrevrange 反向遍历元素(从大到小)
- zrangebyscore 遍历指定分数范围的元素
- zscore 查询元素的分数
- zrem 删除元素
- zincrby 元素的分数计数加n
-
- set
-
集合 无序+去重无序
- 命令
- sadd 添加元素
- smembers 遍历元素
- sismember 判断是否包含
- srem 删除元素
-
- redis-py
- python中独立的redis包
- 安装
pip install redis
1.2 事务
- 语法
- MULTI
- 开启事务, 后续的命令会被加入到同一个事务中
- 事务中的操作会发给服务端, 但是不会立即执行, 而是放到了该事务的对应的一个队列中, 服务端返回QUEUED
- EXEC
- 执行EXEC后, 事务中的命令才会被执行
- 事务中的命令出现错误时,
, 而是继续执行不会回滚也不会停止事务
- DISCARD
- 取消事务, 事务队列会清空, 客户端退出事务状态
- MULTI
- ACID
- 原子性
- 不支持
- 不会回滚并且继续执行
- 隔离性
- 支持
- 事务中命令顺序执行, 并且不会被其他客户端打断 (先EXEC的先执行)
- 持久性
- 不支持, redis数据易丢失
- 一致性
- 不支持
- 强一致性要求 通过乐观锁(watch)来实现
- 原子性
- WATCH
- redis实现的乐观锁
- 机制
- 事务开启前, 设置对数据的监听, EXEC时, 如果发现数据发生过修改, 事务会自动取消(DISCARD)
- 事务EXEC后, 无论成败, 监听会被移除
# 解决更新丢失问题
WATCH mykey # 监视mykey的值
GET mykey # 读取数据, 假设需要进行*2操作, 再将结果重新赋值 (假设取出5)
MULTI # 开启事务
SET mykey 10
EXEC # 如果mykey的值在执行exec之前发生过改变, 则该事务会取消(客户端可以在发生碰撞后不断重试)
如果只是加减操作, 建议使用 incr类
的操作, 单一操作具有原子性
- 流水线
1.3 持久化 (重点)
1.3.1 RDB 快照存储
- 将
完整的保存到硬盘中内存中的所有数据
- 机制
- fork出一个
,专门进行数据持久化, 将内存中所有数据保存到单个rdb文件中(默认为dump.rdb)子进程
- redis重启后, 会加载rdb文件中的数据到内存中
- fork出一个
- 触发方式
- 配置中设置
自动持久化策略
-
|SAVE
|BGSAVE
(前提是设置了自动持久化策略)SHUTDOWN
- 配置中设置
- 相关配置
save 60 1000 # 多久执行一次自动快照操作 60秒内如果更新了1000次, 则持久化一次
stop-writes-on-bgsave-error no # 创建快照失败后,是否继续执行写命令
rdbcompression yes # 是否对快照文件进行压缩
dbfilename dump.rdb # 如何命名快照文件
dir ./ # 快照文件保存的位置
save # 关闭RDB机制
- 优缺点
- 优点
-
: 由于保存到方便数据备份
中, 易于数据备份 (可以使用定时任务, 定时将文件发送给数据备份中心)单独的文件
-
: 子进程单独完成持久化操作, 父进程不参与IO操作, 最大化redis性能写时复制
- 恢复大量数据时, 速度优于 AOF
-
- 缺点
-
, 如果redis意外停止工作(如电源断电等), 则可能会丢失一段时间的数据不是实时保存数据
- 数据量大时, fork进程会比较慢, 持久化时使redis响应速度变慢
-
- 优点
1.3.1 AOF 只追加文件
- Append-only file 只追加文件
-
而 不是全部重新写入只追加
-
, 而不是数据追加命令
-
- 机制
- 主线程将
追加到aof_buf(缓冲区)中, 根据使用的策略不同,写命令
将缓存区的命令写入到aof文件中 (不使用子进程)子线程
- 当redis重启时, 会重新执行aof文件中的命令来恢复数据
- 如果同时开启了 RDB, 则优先使用 AOF
- 主线程将
- 文件修复
- 如果AOF出错 (磁盘满了/写入中途宕机等), 则redis重启时会拒绝使用该AOF文件
- 修复步骤
- 首先备份AOF文件
- 使用redis-check-aof工具进行修复 (一般会删除末尾无法恢复的命令)
- 重启redis服务器, 自动载入修复后的AOF文件, 进行数据恢复
$ redis-check-aof –fix # 可选操作: 使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。
- 文件重写/压缩
- AOF 提供了重写/压缩机制(优化命令), 以避免AOF文件过大
- fork子进程来完成 AOF 重写
- 相关配置
appendonly no # 是否开启AOF机制
appendfsync everysec # 多久将写入的内容同步到硬盘 每秒一次
no-appendfsync-on-rewirete no # 重写aof文件时是否执行同步操作
auto-aof-rewrite-percentage 100 # 多久执行一次aof重写, 当aof文件的体积比上一次重写后的aof文件大了一倍时
auto-aof-rewrite-min-size 64mb # 多久执行一次aof重写,当aof文件体积大于64mb时
appendfilename appendonly.aof # aof文件名
dir ./ # aof文件保存的位置(和rdb文件共享该配置)
- 优缺点
-
优点
-
更可靠
默认每秒同步一次操作, 最多丢失一秒数据
- 提供了三种策略, 还可以不同步/每次写同步
- 可以进行`文件重写`, 以避免AOF文件过大
-
缺点
- 相同数据集, AOF文件比RDB
,体积大
- 除非是不同步情况, 否则普遍要比RDB恢复速度慢
速度慢
-
1.3.3 如何选择
- 对于
可以选择使用redis进行持久化存储更新频繁, 一致性要求不是非常高的数据
- RDB or AOF
- 数据安全性要求高, 都打开
- 可以接受短时间的数据丢失, 只使用 RDB
- 即使使用 AOF, 最好也开启 RDB, 因为便于备份并且回复速度快, bug更少
- 项目中的应用
- 使用redis进行一部分数据的持久化存储
- 用户的阅读历史
- 两种持久化机制都开启了
- 使用redis进行一部分数据的持久化存储
1.4 分布式设计
1.4.1 哨兵 (重点)
- 作用
- 监控redis服务器的运行状态, 可以进行
(failover), 实现高可用自动故障转移
- 与
配合使用的机制数据库主从
- 监控redis服务器的运行状态, 可以进行
- 特点
- 独立的进程, 每台redis服务器应该至少配置一个哨兵程序
- 监控redis主服务器的运行状态
- 出现故障后可以向管理员/其他程序发出通知
- 针对故障,可以进行自动转移, 并向客户端提供新的访问地址
流言协议
- 当某个哨兵程序 发现监视的主服务器下线后(心跳检测), 会向监听该服务器的其他哨兵询问, 是否确认主服务器下线, 当 确认的哨兵数量 达到要求(配置文件中设置)后, 会确认主服务器下线(客观下线), 然后进入投票环节
投票协议
- 当确认主服务器客观下线后, 哨兵会通过 投票的方式 来授权其中一个哨兵主导故障转移处理
- 只有在 大多数哨兵都参加投票 的前提下, 才会进行授权, 比如有5个哨兵, 则需要至少3个哨兵投票才可能授权
- 目的是避免出现错误的故障迁移
建议最低配置
- 至少在3台服务器上分别启动至少一个哨兵
- 如果只有一台, 则服务器宕机后, 将无法进行故障迁移
- 如果只有两台, 一旦一个哨兵挂掉了, 则投票会失败
- 相关配置 (sentinel.conf)
bind 127.0.0.1 # 哨兵绑定的ip
port 26381 # 哨兵监听的端口号, redis客户端需要访问哨兵的ip和端口号
sentinel monitor mymaster 127.0.0.1 6380 2 # 设置哨兵 (主数据库别名 主数据库ip 主数据库端口 确认下线的最小哨兵数量)
sentinel down-after-milliseconds mymaster 60000 # 服务器断线超时时长
sentinel failover-timeout mymaster 180000 # 故障转移的超时时间
sentinel parallel-syncs mymaster 1 # 执行故障转移时,最多几个从数据库可以同步主数据库数据(数量少会增加完成转移的时长;数量多可能会影响主数据库的数据查询)
min-slaves-to-write 2 # 可执行故障转移的从数据库的最小数量(低于当数量时, 主数据库将禁止写入操作)
min-slaves-max-lag 10 # 从数据库的最大响应时长
# 以上两条连起来: 当至少有2个从数据库可以进行复制并且响应延迟都在10秒之内时, 主数据库才允许写操作
- 启动哨兵
redis-sentinel sentinel.conf
mysql官方没有提供故障转移方案, 需要用第三方的服务, 如 keepalive等
1.4.2 集群
- 多个节点共同保存数据
- 作用
- 拓展存储空间
- 提高吞吐量, 提高写能力
- 和单机的不同点
- 不再区分数据库, 只有0号库, 单机默认0-15
- 不支持事务/管道/多值操作
- 集群默认就集成了哨兵, 至少三主三从, 自动故障转移
- 安装
pip install redis-cluster
- 项目中的使用
- 主从配置了哨兵和持久化机制, 用于保存用户的阅读历史
- 集群负责实现缓存设计