Redis 实战之主从复制、高可用、分布式
目录
- 简介
- 持久化
- 主从复制
- 高可用 Redis-Sentinel
- .NET Core开发
- 分布式 Redis-Cluster
- 配置说明
- 常见问题
简介
本节内容基于 CentOS 7.4.1708,Redis 3.2.12 环境实验。
Redis 是一个开源的高性能键值对数据库。
安装:yum install -y redis
特性:
- 高性能 Key-Value 服务器
- 多种数据结构
- 丰富功能
- 缓存(get|set)
- 计数器(incre)
- 消息队列(publish|subcrib)
- 高可用(v2.8 redis-sentinel)
- 分布式(v3.0 redis-cluster)
可执行文件:
- redis-server:服务端
- redis-cli:客户端
- redis-benchmark:性能测试工具
- redis-check-aof:aof修复工具
- redis-check-dump:rdb修复工具
- redis-sentinel:sentinel服务端
启动方式:
- 最简启动:默认配置直接启动redis-server
- 动态参数启动:命令行指定配置启动redis-server
- 配置文件启动(推荐):指定配置文件启动redis-server
启动验证:
ps -ef|grep redisredis-cli -h locahost -p 6379 ping
由于 redis 是单线程的,推荐在一台多核CPU机器上部署多个 redis 实例充分发挥。
持久化
redis 持久化支持2种:
- RDB:快照方式,相当于 MySQL 中的 dump
- AOF:写日志方式,相当于 MySQL 中的 binlog,推荐使用
注意:
- 当同时开启 RDB 和 AOF 的时候,redis启动的时候会读取 AOF 还原数据。
- 推荐:关闭 RDB 持久化机制,开启 AOF
RDB
RDB是什么:
- RDB方式的持久化是通过快照(snapshortting)完成的,当符合一定条件时Redis会自动将内存中所有数据完整的压缩存储到硬盘上。
- RDB开启条件由2个参数 时间 和 改动次数构成。如:save 900 1
- RDB文件由2个参数 dir 和 dbfilename 分别指定目录 和 文件名
- RDB方式是Redis默认的持久化方式。
触发命令:
- save 命令(阻塞)
- bgsave 命令(fork过程阻塞)
主要触发方式:
- 自动触发规则(内部调用bgsave,不推荐开启)
- 全量复制(内部调用bgsave)
过程:
- 执行 save 或 bgsave 命令
- 生成新的 rdb 文件,如:temp-36985.rdb
- 覆盖 rdb 文件,如:dump-6379.rdb
优点:
- 启动速度快
- 占用空间小
缺点:
- 容易丢失数据
- 时间复杂度O(n)
关闭RDB方式:
redis-cli config set save ""
注意:
RDB并不能真正的关闭,在主从复制时主从都会生成RDB文件
AOF
AOF是什么:
- AOF是纯文本文件,会记录 Redis 的每次改动命令(不记录查询)。
- AOF开启条件:appendonly yes
- AOF文件由2个参数 dir 和 appendfilename 分别指定目录 和 文件名
- AOF方式 默认情况下Redis并没有开启。
由于每次改动都会记录,产生2个问题:
- 每次改动都写入硬盘,普通硬盘只能承受几百次qps。通过写入策略来调整
- 对同1个key执行几次操作就记录几次,冗余量特别大。通过 aof 文件重写来调整
AOF文件有3种写入策略:
- always(每次写入都会fsync同步到硬盘)
- everysec(默认,1s写1次)
- no(并非不写,交给系统控制预计30s写1次)
AOF重写:
- 重写方式
- 手动执行 bgrewriteaof 命令
- 自动触发规则(通过指定最小aof文件和aof增长率来自动内部调用 bgrewriteaof)
- 过程
- fork 出子进程
- 子进程执行 bgrewriteaof 命令
- 父进程将新接收的命令,同时写到 aof 文件和 aof_rewrite_buffer文件中。(在 aof 重写时,可配置关闭aof写入)
- 子进程将 aof_rewrite_buffer 文件追加到新 aof 文件中。
- 覆盖旧的 aof 文件
注意:
- 采用 everysec 方式,最多可能丢失 2s 的数据。
主从复制
为什么需要主从复制:
通过持久化保证 Redis 在服务器重启的情况下数据也不会丢失。但数据在一台服务器上,如果服务器的硬盘坏了,也会导致数据丢失。为了避免单点故障,Redis 提供了主从复制高可用方案。
主从复制结构:
- 1个 master 可以有多个 slave
- 1个 slave 只能有1个 master
- 数据流向单向 master -> slave
开启复制:
- 命令:
--slaveof ip port - 配置:
slaveof ip port(默认配置都是master)
关闭复制:
slaveof no one
复制类型:
- 全量复制(首次 或者 网络断开时间比较长)
- 部分复制(在网络抖动一定范围的情况下,v2.8以上可配置复制缓存区repl-backlog-size)
全量复制过程:
- slave 节点 发起 psync runid offset:
psync ? -1 - master 节点 返回 fullresync runid offset
- master 节点 bgsave 保存当前数据到 rdb
- master 节点 在此期间接收到新的数据存储到 buffer 中
- master 节点 send RDB、send buffer
- slave 节点 flush old data
- slave 节点 load RDB、load buffer
在master重启(master 的run_id更新)和slave重启(slave 的run_id丢失)时都会发生全量复制,通过 info server 可以查看run_id。
部分复制过程:
- slave 节点 发起 psync runid offset
- master 节点 确认 runid 和 offset没问题后,发送增量数据
- slave 节点 接收同步数据。
当全量复制完成 或 网络抖动一定范围 时,master 相当于 slave 的 client 进行增量更新数据。
Redis Sentinel
Redis-Sentinel是什么?
- Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案
- Redis-Sentinel本身也是一个独立运行的进程,它能监控多个 master-slave 集群,发现 master宕机 后能进行自动故障转移。
sentinel工作原理:
- 准备多个Redis Sentinel节点(建议至少3个节点,避免单点故障)
- 多个 Sentinel 节点发现并确认 master 主观下线
- 超过 quorum 个 sentinel 判定确认 客观下线
- 选出 1个 sentinel 节点作为领导
- 选出 1个 slave 节点作为 master
- 切换 slave 节点的 master 为新的 master
- 通知 client 主从变化
- 等待故障的 master 复活成为新的 slave
- Client 不直接连接 Redis 节点,应该连接 Sentinel 节点获取 Redis Info
2种下线判定:
- sdown(subjectively down,主观下线):每个 sentinel 判定 redis 节点下线。
- odown(objectively down,客观下线):超过 quorum 个 sentinel 判定 redis 节点下线。
启动方式:
redis-sentinel /path/to/sentinel.confredis-server /path/to/sentinel.conf --sentinel
三个定时任务:
- 每个 Sentinel 节点每秒通过 redis 的
__sentinel__:hello发布一条消息,宣布自己的存在。同时也订阅来确定其他的 Sentinel 节点。 - 每个 Sentinel 节点每秒对其他 redis 节点执行 ping。确定是否下线。
- 每个 Sentinel 节点每10秒 对 master 和 slave 执行 info,确定 slaves。
配置模拟:
- 配置 Redis 开启主从复制
- 配置 Sentinel 监控主节点
常用的channel:
- +switch-master:切换主节点
- +convert-to-slave:切换从节点
- +sdown:主观下线
.NET Core环境开发:
dotnet add package StackExchange.Redis
注意:
- 所有Sentinel和Redis不能在同一个节点
Redis Cluster
实际上大部分场景下,Redis Sentinel已经足够好。请根据实际情况采用 Redis Cluster。
Redis Cluster 采用虚拟槽分区方式(16384个虚拟槽)。
原因:
- 需要更高的qps(超过 10w/s)
- 需要更高的数据量(超过 500G)
- 需要更高的带宽(超过 1000M)
常用命令:
redis-cli -h localhost -p 6382 cluster info:查看集群基本信息redis-cli -h localhost -p 6382 cluster slots:查看集群slot信息redis-cli -h localhost -p 6382 cluster nodes:查看集群node信息redis-cli -c:move自动跳转执行yum install -y redis-trib:官方提供了基于 ruby 的工具方便部署
搭建 Cluster 过程:
- 配置
cluster-enabled:yescluster-node-timeout 15000cluster-require-full-coverage nocluster-config-file node-${port}.conf - meet
redis-cli cluster meet ip port - 分配槽(0-16383)
redis-cli cluster addslots {0....5461} - 分配主从(node-id)
redis-cli cluster replicate {nodeid}
redis-cli 搭建:
redis-trib搭建:
- 准备节点
- 使用redis-trib搭建
redis-trib create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
redis-trib create 会自动meet、addslots、replicate。
配置
查看去除注释的配置:cat /etc/redis.conf | grep -v '^#' | grep -v '^$'
设置配置:config set key value
查询所有配置:config get *
基础配置
| 配置项 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
| daemonize | no | yes(docker环境例外) | 是否以守护进程方式启动 |
| port | 6379 | - | redis服务监听端口 |
| pidfile | /var/run/redis.pid | /var/run/redis-{port}.pid | pid文件 |
| logfile | /var/log/redis/redis.log | /var/log/redis/redis-{port}.log | 日志文件名:redis工作时产生的日志。 |
| dir | /var/lib/redis | - | rdb文件和aof文件目录。推荐使用大文件目录。(不指定则为当前目录) |
| protected-mode | yes | - | 限制为127.0.0.1访问。启用条件:没有bindIP 和 没有设置密码 |
RDB配置
| 配置项 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
| dbfilename | dump.rdb | dump-{port}.rdb | rdb文件名 |
| rdbcompression | yes | yes | 压缩格式 |
| stop-writes-on-bgsave-error | yes | yes | 出现错误时,停止新的写入 |
| rdbchecksum | yes | yes | 数据完整性校验 |
AOF配置
| 配置项 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
| appendonly | no | yes | 是否开启 aof 模式 |
| appendfilename | "appendonly.aof" | "appendonly-{port}.aof" | aof文件名 |
| appendfsync | everysec | everysec | fsync方式 |
| no-appendfsync-on-rewrite | no(安全) | yes(高性能) | 在 aof 重写时,是否停止fsync |
| auto-aof-rewrite-min-size | 64mb | - | aof文件重写的最小大小 |
| auto-aof-rewrite-percentage | 100 | - | aof文件增长率 |
| aof-load-truncated | yes | yes | 当 aof 文件不完整的时候,将完整的部分加载 |
主从复制配置
| 配置项 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
| slowlog-max-len | 128 | 1000 | 慢查询队列长度 |
| slowlog-log-slow-than | 10000 | 1000(qps1w) | 慢查询阈值(单位:微秒) |
| slaveof | ip port | - | 主从复制配置 |
| slave-read-only | yes | yes | 从节点只读 |
| repl-backlog-size | 1048576 | 10M | 复制缓存区,可以再原有基础上稍微增加 |
Sentinel配置
| 配置项 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
| daemonize | no | yes | 是否以守护进程方式启动 |
| port | 26379 | {port} | sentinel监听端口 |
| dir | /tmp | - | 工作目录 |
| sentinel monitor | mymaster 127.0.0.1 6379 2 | - | odown(objectively down,客观下线)规则:masterName ip port quorum |
| sentinel down-after-milliseconds | mymaster 30000 | - | sdown(subjectively down,主观下线)规则:masterName timeout(单位:毫秒) |
| sentinel parallel-syncs | mymaster 1 | - | 并发同步数量 |
| sentinel failover-timeout | mymaster 180000 | - | 多长时间内不再故障转移(单位:毫秒) |
| logfile | /var/log/redis/sentinel.log | /var/log/redis/sentinel-{port}.log | 日志文件 |
Cluster配置
| 配置项 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
| cluster-enabled | no | yes | 开启cluster模式 |
| cluster-node-timeout | 15000 | - | 故障转移时间,主观下线超时时间 |
| cluster-config-file | nodes-{port}.conf | cluster配置 | |
| cluster-require-full-coverage | yes | no | cluster 所有节点全部在线才提供服务 |
常见问题
redis是单线程吗?为什么这么快?
redis其实不是单线程(fsync,bgsave),一次只能执行一条命令。
慢查询
查询慢查询队列:slowlog get
客户端请求的生命周期:
- 发送命令
- 排队
- 执行命令
- 返回结果
慢查询发送在第三个阶段(执行命令),客户端超时不一定是慢查询。
fork
- fork本身是同步操作
- 内存越大耗时越长
- info:latest_fork_usec
规避全量复制
- 首次全量复制:不可避免
- runid 不匹配:故障转移
- 复制缓冲区不足:配置
repl_backlog_size调整大
常用命令
- KEYS pattern :查询keys
- DBSIZE :查询所有键的数量
- EXISTS key :查询指定key是否存在
- TYPE key :查询key的类型
- DEL key :删除指定key
- INFO :查看server 信息如:INFO memory
INFO 信息:
- used_memory redis 当前使用的内存总量
- used_memory_rss redis 当前使用的内存总量(包含内存碎片)
- used_memory_peak redis 使用的内存总量峰值
- 个人公众号谢谢各位老铁支持

Redis 实战之主从复制、高可用、分布式的更多相关文章
- 一站式学习Redis 从入门到高可用分布式实践
1:redis 是用c语言来实现的,速度快 持久化 单线程 复杂的数据类型有bitmap和hyperloglog和geo地理信息2:高可用.分布式 v2.8开始支持Redis-Sentinel(哨兵) ...
- redis 之redis-sentinel主从复制高可用
一.redis主从复制背景问题 Redis主从复制可将主节点数据同步给从节点,从节点此时有两个作用: (1)一旦主节点宕机,从节点作为主节点的备份可以随时顶上来. (2)扩展主节点的读能力,分担主节点 ...
- 一站式学习Redis 从入门到高可用分布式实践(慕课)第六章 Redis开发运维常见问题
fork操作 1.同步操作 2.与内存量息息相关:内存越大,耗时越长(与机器类型有关) 3.info:latest_fork_usec 进程外开销 AOF追加阻塞 不知道哪个命令??? 单机多实例部署 ...
- Docker部署Redis集群(主从复制 高可用)
环境 vmware12+centos7 关于环境安装可以参考我的另一篇博客 https://www.cnblogs.com/pengboke/p/13063168.html 1.清理环境 我这里用的虚 ...
- 【中间件】Redis 实战之主从复制、高可用、分布式
目录 简介 持久化 主从复制 高可用 Redis-Sentinel .NET Core开发 分布式 Redis-Cluster 配置说明 常见问题 简介 本节内容基于 CentOS 7.4.1708, ...
- net core 实战之 redis 负载均衡和"高可用"实现
net core 实战之 redis 负载均衡和"高可用"实现 1.概述 分布式系统缓存已经变得不可或缺,本文主要阐述如何实现redis主从复制集群的负载均衡,以及 redis的& ...
- 基于nginx+xxl-job+springboot高可用分布式任务调度系统
技术.原理讲解: <分布式任务调度平台XXL-JOB--源码解析一:项目介绍> <分布式任务调度平台XXL-JOB--源码解析二:基于docker搭建admin调度中心和execut ...
- Dubbo入门到精通学习笔记(十五):Redis集群的安装(Redis3+CentOS)、Redis集群的高可用测试(含Jedis客户端的使用)、Redis集群的扩展测试
文章目录 Redis集群的安装(Redis3+CentOS) 参考文档 Redis 集群介绍.特性.规范等(可看提供的参考文档+视频解说) Redis 集群的安装(Redis3.0.3 + CentO ...
- Redis从出门到高可用--Redis复制原理与优化
Redis从出门到高可用–Redis复制原理与优化 单机有什么问题? 1.单机故障; 2.单机容量有瓶颈 3.单机有QPS瓶颈 主从复制:主机数据更新后根据配置和策略,自动同步到备机的master/s ...
随机推荐
- oracle 一张表插入另外一张表 存储过程
----创建存储过程 create or replace procedure inserttest as cursor cs is select id, name, cla, addr, phone, ...
- 阶段3 2.Spring_10.Spring中事务控制_2 作业-基于注解的AOP实现事务控制及问题分析_上
创建maven的新项目 先复制坐标的依赖. 再把代码复制进来 先改造ioc的部分 复制上面一行代码.到下面 改成context 这里也是复制的上面两行代码.到下面改成context关键字 配置扫描的包 ...
- 阶段3 2.Spring_03.Spring的 IOC 和 DI_10 构造函数注入
在AccountServiceImpl内定义三个属性 这里关注点是这几种类型.基本类型的包装类Integer 还有String类型,也包含了其他bean类型.Date 定义构造函数并赋值 重点关注在数 ...
- Dart学习笔记-循环
1.for循环 main() { // for循环 ; i < ; i++) { print(i); // 0,1,2,3,4,5,6,7,8,9 } } 2.while循环 main() { ...
- etcd单节点安装
本篇安装单个etcd,然后进行扩容etcd节点至2个,环境配置如果做了的话就跳过 实验架构 test1: 192.168.0.91 etcd test2: 192.168.0.92 无 test3: ...
- 【转帖】是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了。
是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了. 2019/01/03 http://www.ityouknow.com/springboot/2019/01/03/spr ...
- 洛谷 P1073 最优贸易 题解
题面 大家都是两遍SPFA吗?我这里就一遍dp啊: 首先判断对于一个点u,是否可以从一号点走到这里,并且可以从u走到n号点: 对于这样的点我们打上标记: 那么抛出水晶球的点一定是从打上标记的点中选出一 ...
- 同一路由带参刷新,以及params和query两种方式传参的异同
同一路由应该不叫跳转了吧,就先叫刷新好了. 需求及问题 今天做web课设有这样一个需求: 在导航栏中一项叫做教师队伍一级菜单下,有三个二级菜单,分别为教授.副教授.讲师.这三个二级菜单分别对应一个页面 ...
- KL散度的理解(GAN网络的优化)
原文地址Count Bayesie 这篇文章是博客Count Bayesie上的文章Kullback-Leibler Divergence Explained 的学习笔记,原文对 KL散度 的概念诠释 ...
- C++中如何实现split的效果?
C++中如何实现split的效果? 和Python等语言不同,C++的string类没有内置split函数,这对于实际应用中要经常分割字符串的情况非常不方便.有很多种方法来处理,这里讲一种比较方(to ...