Redis 原理与实战
持久化Redis 持久化 - RDBRedis 持久化 - AOFAOF 文件重写机制Redis 高可用Redis 主从复制搭建主从复制环境全量复制和部分复制Redis 哨兵 (Sentinel)搭建哨兵集群环境Redis ClusterHash 分布配置集群 - 原生命令安装(了解)配置集群 - 官方工具安装Java 从 0 到架构师目录:【Java从0到架构师】学习记录
参考:Redis 中两种持久化机制详解
持久化
Redis 所有的数据都是保存在内存中
如果进行了持久化,对数据的更新将异步或者同步的保存到磁盘上持久化可以避免数据丢失,对数据进行备份,还可以还原指定时间的数据
持久化的方式
快照:MySQL dump、Redis RDB、Oracle dump写日志:MySQL Binlog、Redis AOF
混合持久化内容的 AOF 文件:
appendonly yes # 开启aof模式aof-use-rdb-preamble yes # 使用rdb和aof的混合模式, 高版本默认开启
Redis 持久化 - RDB
触发方式:
save
(同步):如果存在老的 rdb 文件,新的文件会替换老的文件bgsave
(异步):Redis 会调用 fork 来创建一个子进程自动配置:在配置文件中配置快照触发的条件
saev 900 1save 300 10save 60 10000
save 900 1
表示 900s 内,执行了 1次 数据库操作则自动创建快照,以此类推
触发机制
全量复制debug reloadshutdown
相关配置:
save 900 1 # 15分钟内有1个key进行修改save 300 10 # 5分钟类有10个key进行修改save 60 10000 # 1分钟内有10000个key进行修改dbfilename dump_6379.rdb # 备份文件dir /usr/local/redis-5.0.8/data # 备份目录stop-writes-on-bgsave-error yes # 在出现错误的时候终止rdb备份, 默认yesrdbcompression yes # 是否进行压缩, 默认yesrdbchecksum yes # 是否进行检查sum值校验, 默认yes
RDB 方式的不足之处:耗时,耗费 IO 性能
Redis 持久化 - AOF
AOF 的三种策略:
always:每个 redis 写命令都要同步写入硬盘,严重降低 redis 速度(慎用)
该策略不会丢失数据,但是 IO 开销很大everysec:每秒同步一次缓冲区的命令到硬盘(推荐,也是默认策略)
该策略和不使用持久化时的性能几乎无差别,即时系统奔溃也最多丢失 1 秒的数据no:由操作系统决定何时将缓冲区的命令写到硬盘(不推荐)
该策略是不可控的
AOF 文件重写机制
AOF 方式会使得持久化的文件变的越来越大,AOF 重写机制可以在一定程度下减少磁盘占用量
客户端方式执行重写:BGREWRITEAOF
服务器配置自动重写:
appendonly yes # 是否开启aof文件模式appendfilename "appendonly-6379.aof" # aof文件名称appendfsync everysec # aof策略模式dir usr/local/redis-5.0.8/data # 数据存储路径no-appendfsync-on-rewrite yes # 在重写的时候, 不要执行aof操作auto-aof-rewrite-percentage 100 # 自动重写的百分比auto-aof-rewrite-min-size 64mb # 重写的大小配置# 当AOF文件体积大于 64M,并且AOF文件的体积比上一次重写之后体积大了 100%(1倍) 时,自动触发重写
Redis 高可用
Redis 主从复制
单击的问题:机器故障引起单点故障,容量达到瓶颈、QPS 达到瓶颈
QPS (Queries Per Second):每秒查询率,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,即每秒的响应请求数,也就是最大吞吐能力
主从复制:
一个 Master 可以有多个 Slave一个 Slave 只能有一个 Master数据流向是单向的,只能从 Master 流向 Slave
只有 Master 可以进行写的操作,然后将数据复制到 Slave
主从复制的作用:
避免单点故障读写分离:Master 节点写数据,然后复制到 Slave 节点,Slave 节点读数据
(默认情况下 Slave 节点无法写数据)一主多从多副本
搭建主从复制环境
配置文件:
port 6380daemonize yespidfile /var/run/redis-6380.pidlogfile 6380.logdbfilename dump_6380.rdbdir /usr/local/redis-5.0.8/data/# bind 192.168.52.128# 局域网连接要指定 -h: redis-cli -h 192.168.52.128
目前情景:开启了两台 Redis 服务器,分别是 127.0.0.1:6379、127.0.0.1:6380,希望 6379 作为 Master 节点,6380 作为 Slave 节点,开启主从复制
方法1:客户端主动执行
# 以从服务器的身份来执行以下命令的# 直接从6379服务端口Master进行数据复制, 自身的数据清空, 然后再从Master复制数据slaveof 127.0.0.1 6379
info replication
可以查看当前服务器的角色是 master 还是 slave
# 脱离 slave 节点的身份, 但是数据会保留slaveof no one
方法2:服务器配置自动成为 slave 节点
replicaof 192.168.52.128 6379replica-read-only yes # 从节点只读,不能写
全量复制和部分复制
全量复制:
部分复制:
Redis 哨兵 (Sentinel)
主从复制在高可用中的问题:
手动故障转移:Master 节点下线后,Slave 不会自动变成 Master写能力和存储能力受限
哨兵机制集群 - 架构图:
搭建哨兵集群环境
哨兵机制架构规划:
配置开启主从节点:
# 主节点配置 redis_7000.confport 7000daemonize yespidfile /var/run/redis-7000.pidlogfile 7000.logdir /usr/local/redis-5.0.8/data/
# 从节点配置 redis_7001.confport 7001daemonize yespidfile /var/run/redis-7001.pidlogfile 7001.logdir /usr/local/redis-5.0.8/data/replicaof 127.0.0.1 7000
# redis_7002.confport 7002daemonize yespidfile /var/run/redis-7002.pidlogfile 7002.logdir /usr/local/redis-5.0.8/data/replicaof 127.0.0.1 7000
配置开启 sentinel 监控主从节点:
# sentinel_26379.confport 26379daemonize yespidfile /var/run/redis-sentinel-26379.pidlogfile "26379.log"dir /usr/local/redis-5.0.8/data/# 告诉sentinel去监听地址为ip:port的一个master, 2个sential认为一个master失效才会真正失效sentinel monitor mymaster 127.0.0.1 7000 2# sentinel判断失效的时间sentinel down-after-milliseconds mymaster 30000# 最多1个slave对master进行同步sentinel parallel-syncs mymaster 1sentinel failover-timeout mymaster 180000sentinel deny-scripts-reconfig yes
# sentinel_26380.confport 26380daemonize yespidfile /var/run/redis-sentinel-26380.pidlogfile "26380.log"dir /usr/local/redis-5.0.8/data/sentinel monitor mymaster 127.0.0.1 7000 2sentinel down-after-milliseconds mymaster 30000sentinel parallel-syncs mymaster 1sentinel failover-timeout mymaster 180000sentinel deny-scripts-reconfig yesprotected-mode no
# sentinel_26381.confport 26381daemonize yespidfile /var/run/redis-sentinel-26381.pidlogfile "26381.log"dir /usr/local/redis-5.0.8/data/sentinel monitor mymaster 127.0.0.1 7000 2sentinel down-after-milliseconds mymaster 30000sentinel parallel-syncs mymaster 1sentinel failover-timeout mymaster 180000sentinel deny-scripts-reconfig yesprotected-mode no
开启主从节点,哨兵节点:
# 启动主从节点服务器bin/redis-server conf/redis_7000.confbin/redis-server conf/redis_7001.confbin/redis-server conf/redis_7002.conf# 启动哨兵节点服务器bin/redis-sentinel conf/sentinel_26379.conf bin/redis-sentinel conf/sentinel_26380.conf bin/redis-sentinel conf/sentinel_26381.conf
通过查看日志可以看到监控信息:
然后进行一些操作,例如结束某个 redis-server:
redis-cli -p 7000 shutdown
然后查看主从节点信息:
# 在 redis-cli 执行以下操作可以查看主从节点信息info replication
通过哨兵机制,实现了服务端高可用和客户端高可用
Redis Cluster
为什么需要使用集群?
并发量:如果需要的并发量是 100w/s,单个服务的性能是 11w/s,那么就需要 10 个服务器集群同时提供服务数据量:如果需要存储更多的数据量,可以考虑使用 Redis 集群,集群中的每个服务器都存放一部分数据。如果一个服务存放的数据量是 200G,那么要存储 1T 的数据就需要 5 台服务器进行集群操作。网络流量:单台服务器的网卡流量是固定的,比如一个服务器的网卡是 1G,需要达到 10G 的网络流量速度,可以使用 10 台服务器集群。
数据分布:对于大量数据,想要存储到不同的节点,是需要按照某种规则的
顺序分区:确定好所有的数据,把数据按照顺序放到不同的服务节点中,均匀分配
特点:1. 数据容易倾斜 2. 键值分布和业务相关 3. 支持批量操作 4. 可以顺序访问
Hash 分区:确定好服务节点数量,根据每个数据的 key 计算对应的 hash 值(数字),对 hash 值进行取模操作(模的值为服务节点数量),根据取模结果把数据存放到对应的服务节点
特点:1. 数据分散度高 2. 键值分布业务无关 3. 支持批量操作 4. 无法顺序访问
Hash 分布
节点取余扩容:
一致性 Hash:
虚拟槽分配:
配置集群 - 原生命令安装(了解)
集群规划图:
集群配置:
port 7000# 设置是否以守护进程开启daemonize yesdir /usr/local/redis-5.0.8/datadbfilename dump_7000.dbflogfile 7000.log# 是否开启集群模式cluster-enabled yes# 集群节点的单独配置cluster-config-file node_7000.conf cluster-node-timeout 15000# 设置什么情况下集群对外提供服务, yes表示集群节点都正常才对外提供服务cluster-require-full-coverage nobind 192.168.52.129protected-mode no
快速根据已有文件替换字符并输出新文件:
sed 's/7000/7001/g' redis_7000.conf > redis_7001.conf#sed 命令 替换字符串 写入新文件
启动集群:
bin/redis-server conf/redis_7000.confbin/redis-server conf/redis_7001.confbin/redis-server conf/redis_7002.confbin/redis-server conf/redis_7003.confbin/redis-server conf/redis_7004.confbin/redis-server conf/redis_7005.conf# 查看服务状态ps -ef |grep redisnetstat -ntlp# 查看集群状态,没有绑定ip可以不写-h(默认连接127.0.0.1)bin/redis-cli -h 192.168.52.129 -p 7000 cluster info# 以集群模式连接客户端(-c)bin/redis-cli -c -h 192.168.52.129 -p 7000cluster info # 查看集群状态cluster nodes # 查看集群中的节点
节点通信:
# 或者以集群模式连接客户端后,直接执行 cluster meet ip port 命令bin/redis-cli -h 127.0.0.1 -p 7000 cluster meet 192.168.52.129 7001bin/redis-cli -h 127.0.0.1 -p 7000 cluster meet 192.168.52.129 7002bin/redis-cli -h 127.0.0.1 -p 7000 cluster meet 192.168.52.129 7003bin/redis-cli -h 127.0.0.1 -p 7000 cluster meet 192.168.52.129 7004bin/redis-cli -h 127.0.0.1 -p 7000 cluster meet 192.168.52.129 7005# 查看集群信息bin/redis-cli -p 7000 cluster info
分配 slot 卡槽:
# 1 编写分配卡槽脚本 addslots.sh# $1 代表第一个参数start=$1end=$2port=$3for slot in `seq ${start} ${end}`do./redis-cli -h 192.168.52.129 -p ${port} cluster addslots ${slot}done# 2 执行脚本sh addslots.sh 0 5460 7000sh addslots.sh 5461 10922 7001sh addslots.sh 10923 16383 7002
配置从节点:
# 这里需要配置一个node节点的id信息# a0502ceb7461f9b2ec99d440904cf4768a297c22redis-cli -h 192.168.52.129 -p 7003 cluster replicate node1_id# 50caaf79a5145b511eec6680ffa3355e4dbc9e73redis-cli -h 192.168.52.129 -p 7004 cluster replicate node2_id# 45713493b59ed5ed3cca4397fa13148cf6666efcredis-cli -h 192.168.52.129 -p 7005 cluster replicate node3_id
配置集群 - 官方工具安装
# 同时杀死所有 redis-server 进程ps -ef | grep redis | grep -v grep | awk '{print $2}' | xargs kill -9# 清除上次配置的集群信息: 删除配置集群生成的日志# 我配置的日志目录是 data, 因此进入 data 后执行 rm -rf *
使用官方工具安装,只需要执行集群配置和启动集群的步骤,可以省略节点通信、分配 slot 卡槽,配置从节点的步骤。
集群配置、启动集群参考上面,下面直接进行安装:
# 通过命令进行安装# --cluster-replicas 1 表示主从比例1:1, 即 一主一从# --cluster-replicas 2 表示主从比例1:2, 即 一主两从bin/redis-cli --cluster create 192.168.52.129:7000 192.168.52.129:7001 192.168.52.129:7002 192.168.52.129:7003 192.168.52.129:7004 192.168.52.129:7005 --cluster-replicas 1
如果觉得《【Java从0到架构师】Redis 进阶 - 持久化(RBD AOF) 高可用(主从复制 哨兵机制 Cluster)》对你有帮助,请点赞、收藏,并留下你的观点哦!