复制
配置
在分布式系统中为了解决单点问题,通常会把数据复制多个副本部署到其他机器,满足故障恢复和负载均衡等需求。
建立复制
参与复制的 Redis 实例划分为主节点(master)和从节点(slave),默认情况下,Redis 都是主节点。每个主节点只能有一个主节点,而主节点可以同时具有多个从节点。复制的数据流是单向的,只能由主节点复制到从节点。
配置复制的方式有以下三种
- 在配置文件中加入 slaveof 项,随 Redis 启动生效
- 在 redis-server 启动命令后加入 –slaveof 生效
- 直接使用命令 slaveof 生效
slaveof 配置都是在从节点发起的,可以使用 info replication 命令查看复制相关状态。
断开复制
在从节点上执行 slaveof no one 命令断开与主节点的复制关系,从节点断开后数据会保留,只是无法再从主节点获取。
命令 slaveof 还可以进行主节点的切换,但要注意,切换主节点会清空之前所有的数据 。
拓扑
一主一从、一主多从、树状主从
原理
复制过程大致分为 6 个过程:
- 保存主节点信息
- 主从建立 socket 连接
- 发送 ping 命令
- 权限验证
- 同步数据集
- 命令持续复制
持久化
Redis 支持 RDB 和 AOF 两种持久化机制,持久化功能有效的避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化的文件即可实现数据恢复。
RDB
RDB 持久化是把当前进程数据生成快照保存到硬盘的过程,触发 RDB 持久化的过程分为手动触发和自动触发。
手动触发
bgsave 该命令会 fork 一个子进程,RDB 的持久化过程由子进程完成,而且阻塞只发生在 fork 阶段,一般时间很短。
save 命令会阻塞当前 Redis 服务,一般不采用。
RDB 文件名和文件路径由配置项在 dir 和 dbfilename 指定,若要修改,可以使用 config set 动态修改。
优缺点
优点
- RDB 是一个紧凑压缩的二进制文件,代表 Redis 在某个时间节点上的数据快照,非常适用于备份,全景复制等场景。
- Redis 加载 RDB 恢复数据远远快于 AOF 的方式。
缺点
- RDB 方式数据没法做到实时持久化 / 秒级持久化,因为 bgsave 每次运行都要执行 fork 操作创建子进程,属于重量级操作,频繁执行成本过高。
- RDB 文件使用特定的二进制格式保存,存在老版本 Redis 无法兼容新版 RDB 格式的问题。
AOF
AOF(append only file) 持久化:以独立日志的方式记录每次写命令,重启时再重新执行 AOF 文件中的命令达到恢复数据的目的。AOF 是目前 Redis 持久化的主流方式。
开启 AOF 功能需要设置配置:appendonly yes,默认不开启;AOF 文件名通过 appendfilename 配置,默认为 appendonly.aof;保存路径同样由 dir 指定。
工作流程
- 命令写入(append)
- 文件同步(sync)
- 文件重写(rewrite)
- 重启加载(load)
命令写入
AOF 命令写入会把所有的写入命令追加到 aof_buf(缓冲区),写入的内容直接是文本协议格式。
文件同步
Redis 提供了多种 AOF 缓冲区同步文件策略,由配置项 appendfsync 指定,可配置值有 always、everysec、no。eyerysec 是默认的配置值,也是建议的配置值,能做到兼顾性能和数据安全性。
重写机制
随着命令不断写入 AOF,文件会越来越大,为了解决这个问题,Redis 引入 AOF 重写机制压缩文件体积。
重写后的 AOF 文件为什么可以变小?
- 进程内已经超时的数据不再写入文件;
- 旧的 AOF 文件含有无效命令,如 del key 等,重写使用进程内数据直接生成,这样新的 AOF 文件只保留最终数据的写入命令;
- 多条写命令可以合并为一个。
AOF 的重写过程有手动触发和自动触发两种方式
- 手动触发 直接调用 bgrewriteaof 命令
- 自动触发 根据 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数确定自动触发时机
重启加载
开启了 AOF 后,Redis 在服务重启时会自动加载 AOF 文件,将数据导入内存。
附加功能
慢查询分析
慢查询日志是系统在命令执行前后计算每条命令的执行时间,当超过预设阀值,就将这条命令的相关信息(例如:发生时间,耗时,命令的详细信息)记录下来,Redis 也提供了类似的功能。
两个配置参数
- slowlog-log-slower-than 预设阀值,默认值 10000 微秒
- slowlog-max-len 允许日志存储的最大条数
slowlog-max-len 是一个列表,当列表满时,第一条日志出列;两个配置可以通过 config set 来修改,如果要将配置写入配置文件,须执行 config rewrite 。
命令
- slowlog get 获取当前 redis 的慢查询
- slowlog len 获取当前慢查询日志列表的长度
- slowlog 慢查询日志重置
Redis Shell
Redis 提供了 redis-server、redis-cli、redis-benchmark 等 Shell 工具。
redis-benchmark
redis-benchmark 可以为 Redis 做基准性能测试。
参数
- -c 指定客户端的并发数量
- -n 指定所有客户端的请求总量
- -q 仅显示 requests per second 信息
- -t 对指定命令进行基准测试
Pipeline 流水线
发送命令和返回结果所耗费的时间称为 Round Trip Time(RTT,往返时间)。Pipeline 能将一组 Redis 命令进行组装,通过一次 RTT 传输给 Redis,再将这组 Redis 命令的执行结果按顺序返回给客户端。
性能测试
- Pipeline 执行速度一般比逐条执行要快
- 客户端与服务器的网络时延越大,Pipeline 的效果越明显
原生批量命令与 Pipeline 对比
- 原生批量命令是原子的,Pipeline 是非原子的
- 原生批量命令是一个命令对应多个 key,Pipeline 支持多个命令
- 原生批量命令是 Redis 服务端支持实现的,而 Pipeline 需要服务端和客户端的共同实现
事务
为了保证多个命令组合的原子性,可以使用事务。
multi 代表事务开始,exec 代表事务结束,命令执行。
Lua 脚本
在 Redis 中使用 Lua
- eval
- evalsha
管理 Lua 脚本
- script load 将脚本加载到内存
- script exists 判断 sha1 是否加载
- script flush 清除加载的所有脚本
- script kill 杀掉正在执行的脚本
Bitmaps
Bitmaps 不是一种数据结构类型,实际上就是字符串,可以对它的位进行操作。
命令
- setbit 设置值
- getbit 获取值
- bitcount 获取 Bitmaps 指定范围为 1 的个数
- bitop and | or | not | xor Bitmaps 间的运算
- bitpos 计算 Bitmaps 中第一个值为 0 | 1 的偏移量
HyperLogLog
HyperLogLog 也不是一种新的数据结构类型(实际类型为字符串类型),而是一种基数算法,通过 HyperLogLog 可以利用极小的内存空间完成独立总数的统计,数据集可以是 IP、Email、ID 等。
- 只为了计算独立总数,不需要获取单条数据
- 可以容忍一定的误差率
命令
- pfadd 添加元素
- pfcount 计算独立用户数
- prmerge 求几个 HyperLogLog 的并集
发布订阅
Redis 提供了基于 「发布/订阅」 模式的消息机制,此种模式下,消息发布者和订阅者不进行直接通信,发布者客户端向指定的频道(channel)发布消息,订阅该频道的每个客户端都可以收到该消息。
命令
- publish 向指定频道发布一条消息
- subscribe 订阅一个或多个频道
- unsubscribe 取消对指定频道的订阅
- psubscribe punsubscribe 按照频道订阅和取消订阅
- pubsub channels | numsub | numpat 查询 活跃的频道 | 频道订阅数 | 模式订阅数
GEO
Redis 3.2 版本提供了 GEO(地理信息定位)功能,支持存储地理位置信息来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能。GEO 的数据结构类型是 ZSet。
命令
- geoadd 添加地理位置信息,包括经度、纬度、地名
- geopos 获取地理位置信息
- geodist 获取两个地理位置的距离 m 米 | km 公里 | mi 英里 | ft 英尺
- georadius georadiusbymember 获取指定位置范围内的地理信息位置集合
- geohash 获取 geohash,Redis 使用 geohash 将二维经纬度转换为一维字符串
- zrem 删除地理位置信息