Redis挂了,怎么补救?谈谈如何实现redis的高可用!

Redis实现高可用主要有三种部署模式:主从模式、哨兵模式和集群模式

分区

分区(Partitioning)是一种最为简单的拓展方式。

  • 在我们面临单机的存储空间瓶颈时,第一点就能想到像传统的关系型数据库一样,进行数据分区。

  • 或者假设手中有N台机器可以作为Redis服务器,所有机器内存总和有256G, 而客户端正好也需要一个大内存的存储空间。

  • 我们除了可以把内存条都拆下来焊到一个机器上,也可以选择分区使用,这样又拓展了计算能力。

  • 单指分区来讲,即将全部数据分散在多个Redis实例中,每个实例不需要关联,可以是完全独立的。

使用方式
  • 客户端处理和传统的数据库分库分表一样,可以从key入手,先进行计算,找到对应数据存储的实例在进行操作。范围角度,比如orderId:1orderId:1000放入实例1,orderId:1001orderId:2000放入实例2...哈希计算,就像我们hashmap一样,用hash函数加上位运算或者取模,高级玩法还有一致性Hash等操作,找到对应的实例进行操作

  • 使用代理中间件 我们可以开发独立的代理中间件,屏蔽掉处理数据分片的逻辑,独立运行。当然也有他人已经造好的轮子,Redis也有优秀的代理中间件,譬如Twemproxy或者codis,可以结合场景选择是否使用。

缺点
  • 无缘多key操作,key都不一定在一个实例上,那么多key操作或者多key事务自然是不支持。

  • 维护成本,由于每个实例在物理和逻辑上,都属于单独的一个节点,缺乏统一管理。

  • 灵活性有限,范围分片还好,比如hash+MOD这种方式,如果想动态调整Redis实例的数量,就要考虑大量数据迁移,这就非常麻烦了。

同为开发者,深知我们虽然总能“曲线救国”的完成一些当前环境不支持的功能,但是总归要麻烦一些。

一,主从模式

同上面的分区一样,也是Redis高可用架构的基础,新手可能会误以为这类基础模式即是“高可用”,这并不是十分正确的。

分区暂时能解决单点无法容纳的数据量问题,但是一个Key还是只在一个实例上,在大流量时代显得不那么可靠。

主从就是另一个纬度的拓展,节点将数据同步到从节点,就像将实例“分身”了一样,可靠性又提高了不少。

主从模式中,Redis部署了多台机器,由主节点负责读写操作,而从节点只负责读操作;

从节点的数据来自于主节点,其背后的原理就是主从复制机制

主从机制包括全量复制增量复制两种方式。

1、全量复制

一般当slave第一次启动连接master的时候,或者被认为是第一次连接,就采用全量复制

1.slave发送sync命令到master。
2.master接收到SYNC命令后,执行bgsave命令,生成RDB全量文件。
3.master使用缓冲区,记录RDB快照生成期间的所有写命令。
4.master执行完bgsave后,向所有slave发送RDB快照文件。
5.slave收到RDB快照文件后,载入、解析收到的快照。
6.master使用缓冲区,记录RDB同步期间生成的所有写的命令。
7.master快照发送完毕后,开始向slave发送缓冲区中的写命令;
8.salve接受命令请求,并执行来自master缓冲区的写命令

redis在2.8版本之后,就是用psync来代替sync请求,因为sync命令非常消耗系统资源,psync的效率更高。

2、增量复制
  • 在slave和master全量同步之后,master上的数据,如果再次发生更新,就会触发增量复制

  • 当master节点发生数据增减时,就会触发replicationFeedSalves()函数,接下来在 Master节点上调用的每一个命令会使用replicationFeedSlaves()来同步到Slave节点。

  • 执行此函数之前呢,master节点会判断用户执行的命令是否有数据更新,如果有数据更新的话,并且slave节点不为空,就会执行此函数。

  • 这个函数作用就是:把用户执行的命令发送到所有的slave节点,让slave节点执行。

流程如下:

使用方式:
  • 作为主节点的Redis实例,并不要求配置任何参数,只需要正常启动

  • 作为从节点的实例,使用配置文件或命令方式REPLICAOF 主节点Host主节点port即可完成主从配置

缺点:
  • slave节点都是只读的,如果写流量大的场景,就有些力不从心了。那我把slave节点只读关掉不就行了?当然不行,数据复制是由主到从,从节点独有数据同步不到主节点,数据就不一致了。

  • 故障转移不友好,主节点挂掉后,写处理就无处安放,需要手工设定新的主节点,如使用REPLICAOF(谁大腿我都不抱了) 晋升为主节点,再梳理其他slave节点的新主配置,相对来说比较麻烦。

二,哨兵模式

主从模式中,一旦主节点由于故障不能提供服务,需要人工将从节点晋升为主节点,同时还要通知应用方更新主节点地址。显然,多数业务场景都不能接受这种故障处理方式。

Redis从2.8开始正式提供了Redis Sentinel(哨兵)架构来解决这个问题。并且还能够充当配置提供者,提供主节点的信息,就算发生了故障转移,也能提供正确的地址。

1、哨兵模式

由一个或多个Sentinel实例组成的Sentinel系统,它可以监视所有的Redis主节点和从节点,并在被监视的主节点进入下线状态时,自动将下线主服务器属下的某个从节点升级为新的主节点。但是呢,一个哨兵进程对Redis节点进行监控,就可能会出现问题(单点问题),因此,可以使用多个哨兵来进行监控Redis节点,并且各个哨兵之间还会进行监控。如下图所示:



简单来说,哨兵模式就三个作用:

  1. 发送命令,等待redis服务器(包括主服务器和从服务器)返回监控其运行状态。

  2. 哨兵检测到主节点宕机,会自动将从节点切换成主节点,然后通过发布订阅模式通知其他的从节点,修改配置文件,让他们切换主机。

  3. 哨兵之间还会相互监控,从而达到高可用。

2、故障切换的过程是怎么样的呢?
  • 假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行 failover(故障切换),仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线

  • 当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行 failover 操作。

  • 故障切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线

  • 这样对于客户端而言,一切都是透明的。

哨兵的工作模式如下:

  1. 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他Sentinel实例发送一个 PING命令。
  2. 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel标记为主观下线。
  3. 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。
  4. 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线。
  5. 在一般情况下, 每个 Sentinel 会以每10秒一次的频率向它已知的所有Master,Slave发送 INFO 命令。
  6. 当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次
  7. 若没有足够数量的 Sentinel同意Master已经下线, Master的客观下线状态就会被移除;若Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。

哨兵本身也是Redis实例的一种,但不作为数据存储方使用,启动命令也是不一样的。

使用方式

Sentinel的最小配置,一行即可:

sentinel monitor <主节点别名> <主节点host> <主节点端口> <票数>

只需要配置master即可,然后用redis-sentinel <配置文件>,命令即可启用。

Redis官网提到的“最小配置”是如下所示,除了上面提到的一行,还有其它的一些配置:

sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1 sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5

正如该例所示,设置主节点别名就是为了监控多主的时候,与其额外配置项能够与其对应, 以及sentinel一些命令,如sentinel get-master-addr-by-name 就要用到别名了。

哨兵数量建议在三个以上且为奇数,在Redis官网也提到了各种情况的“布阵”方式,非常值得参考。

既然是高可用方案,并非有严格意义上的“缺点”,还需配合使用场景进行考量。
  • 故障转移期间短暂的不可用,但其实官网的例子也给出了parallel-syncs参数来指定并行的同步实例数量,以免全部实例都在同步出现整体不可用的情况,相对来说要比手工的故障转移更加方便。

  • 分区逻辑需要自定义处理,虽然解决了主从下的高可用问题,但是Sentinel并没有提供分区解决方案,还需开发者考虑如何建设。

  • 既然是还是主从,如果异常的写流量搞垮了主节点,那么自动的“故障转移”会不会变成自动“灾难传递”,即slave提升为Master之后挂掉,又进行提升又被挂掉。不过最后这点也是笔者猜测,并没有听说过出现这种案例,可不必深究。

三,集群模式

哨兵模式基于主从模式,实现读写分离,它还可以自动切换,系统可用性更高。

但是它每个节点存储的数据是一样的,浪费内存,并且不好在线扩容。

因此,Cluster集群应运而生,它在Redis3.0加入的,实现了Redis的分布式存储。对数据进行分片,也就是说每台Redis节点上存储不同的内容,来解决在线扩容的问题。并且,它也提供复制和故障转移的功能。

  • 对开发者而言,“官方支持”一词是大概率非常美好的,小到issue,大到feature。自定义去解决问题,成本总是要高一些。

  • 有了官方的正式集群方案,从请求路由、故障转移、弹性伸缩几个纬度的使用上,将更为容易。

  • Cluster不同于哨兵,是支持分区的。有说法Cluster是哨兵的升级,这是不严谨的。 二者纬度不一样,如果因为Cluster也有故障转移的功能,就说它是哨兵的升级款,略显牵强。

  • Cluster在分区管理上,使用了“哈希槽”(hash slot)这么一个概念,一共有16384个槽位,每个实例负责一部分槽,通过CRC16(key)&16383,计算出来key所对应的槽位。

  • 虽然在节点和key二者中又引入了槽的概念,看起来不易理解,实际上因为颗粒度更细了,减少了节点的扩容和收缩难度,相比传统策略还是很有优势。

  • 当然,“槽”是虚拟的概念,节点自身去维护“槽”的关系,并不是要真正下载启动个“槽服务”在跑。

使用方式

Redis的各种玩法,都是从配置文件着手,集群也不例外。

cluster-enabled yes
cluster-config-file "redis-node.conf"

关键配置简洁明了,有两步

  • 开启集群

  • 指定集群配置文件

集群配置文件(cluster-config-file)为内部使用,可以不去指定,Redis会帮助创建一个。

启动还是普通的方式redis-server redis.conf

首先以集群方式启动了N台Redis实例,这当然还没完事。

接下来的步骤笔者称为“牵线搭桥分配槽”,听起来还算顺口。

“牵线搭桥分配槽”的方式也在不断升级,从直接用原始命令来处理,到使用脚本,以及现在的Redis-cli官方支持,使用哪种方式都可以。

redis-cli --cluster create 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 \
--cluster-replicas 1

上方的命令即是Redis官网给出的redis-cli的方式用法,一行命令完成“三主三从”以及自动分配槽的操作。

这样集群就搭建完成了,当然,使用官方提供的check命令检查一下,也是有必要的。

redis-cli --cluster check 127.0.0.1:7001
注意:
  • 虽然是对分区良好支持,但也有一些分区的老问题,譬如:如果不在同一个“槽”的数据,是没法使用类似mset的多键操作。

  • 在select命令页有提到, 集群模式下只能使用一个库,虽然平时一般也是这么用的,但是要了解一下。

  • 运维上也要谨慎,俗话说得好,“使用越简单底层越复杂”,启动搭建是很方便,使用时面对带宽消耗,数据倾斜等等具体问题时,还需人工介入,或者研究合适的配置参数。

Redis挂了,怎么补救?谈谈如何实现redis的高可用的更多相关文章

  1. Redis 高可用集群

    Redis 高可用集群 Redis 的集群主从模型是一种高可用的集群架构.本章主要内容有:高可用集群的搭建,Jedis连接集群,新增集群节点,删除集群节点,其他配置补充说明. 高可用集群搭建 集群(c ...

  2. Dubbo入门到精通学习笔记(十五):Redis集群的安装(Redis3+CentOS)、Redis集群的高可用测试(含Jedis客户端的使用)、Redis集群的扩展测试

    文章目录 Redis集群的安装(Redis3+CentOS) 参考文档 Redis 集群介绍.特性.规范等(可看提供的参考文档+视频解说) Redis 集群的安装(Redis3.0.3 + CentO ...

  3. Redis是新兴的通用存储系统-为何Redis要比Memcached好用

    GitHub版本地址: https://github.com/cncounter/translation/blob/master/tiemao_2014/Redis_beats_Memcached/R ...

  4. Redis源码阅读(二)高可用设计——复制

    Redis源码阅读(二)高可用设计-复制 复制的概念:Redis的复制简单理解就是一个Redis服务器从另一台Redis服务器复制所有的Redis数据库数据,能保持两台Redis服务器的数据库数据一致 ...

  5. Redis哨兵模式高可用解决方案

    一.序言 Redis高可用有两种模式:哨兵模式和集群模式,本文基于哨兵模式搭建一主两从三哨兵Redis高可用服务. 1.目标与收获 一主两从三哨兵Redis服务,基本能够满足中小型项目的高可用要求,使 ...

  6. Redis挂了,流量把数据库也打挂了,怎么办?

    你好呀,我是歪歪. 是这样的,前几天有个读者给我发消息,说面试的时候遇到一个场景题: 他说他当时,一时间竟然找不到回答问题的角度,感觉自己没有回答到点子上. 我仔细想了一下,确实是感到这个问题有一丝丝 ...

  7. 【Java面试】面试遇到宽泛的问题,这么回答就稳了,谈谈你对Redis的理解

    "谈谈你对Redis的理解"! 面试的时候遇到这类比较宽泛的问题,是不是很抓狂? 是不是不知道从何开始说起? 没关系,今天我用3分钟教你怎么回答. 大家好,我是Mic,一个工作了1 ...

  8. 谈谈Memcached与Redis

    1. Memcached简介 Memcached是以LiveJurnal旗下Danga Interactive公司的Bard Fitzpatric为首开发的高性能分布式内存缓存服务器.其本质上就是一个 ...

  9. 搭建高可用的Redis服务,需要注意这些方面!

    搭建高可用的Redis服务,需要注意这些方面! HorstXu 占小狼的博客 今天 ◎作者 | HorstXu www.cnblogs.com/xuning/p/8464625.html 基于内存的R ...

  10. Nginx反向代理,负载均衡,redis session共享,keepalived高可用

    相关知识自行搜索,直接上干货... 使用的资源: nginx主服务器一台,nginx备服务器一台,使用keepalived进行宕机切换. tomcat服务器两台,由nginx进行反向代理和负载均衡,此 ...

随机推荐

  1. VForm

    VForm是一款基于Vue 2/Vue 3的低代码表单,支持Element UI.iView两种UI库,定位为前端开发人员提供快速搭建表单.实现表单交互和数据收集的功能. VForm全称为Varian ...

  2. toLua中Lua调用C#中的类

    toLua中Lua调用C#: [7]Lua脚本调用C#中的class 准备工作:打算在Lua脚本中使用Debug,使用lua调用C#脚本,需要绑定LuaState和自定义添加Debug --- --- ...

  3. C语言:计算长方形面积问题

    #include <stdio.h> #include <stdlib.h> /* run this program using the console pauser or a ...

  4. ETSI GS MEC 013,UE 位置 API

    目录 文章目录 目录 版本 功能理解 Relation with OMA APIs Relation with OMA API for Zonal Presence Relation with OMA ...

  5. pageoffice6 版本在线打开word 文件,实现多用户同时编辑

    总体来说,各种Web系统中的Word文档在线处理大体可以分为以下四种流转处理方式: A用户编辑完,流转给B用户修改,再流转给C用户修改,直到最后.每个用户都是针对全文修改的,如果需要在这一篇文档中能区 ...

  6. java学习之旅(day.03)

    整数拓展: 进制 二进制:以0b开头 十进制:我们生活中的正常数 int i=10 八进制:以0开头 int i=010 十六进制:以0x开头 0~9 A~F int i=0x10 浮点数拓展: fl ...

  7. wxpython模块详解

    一.python gui(图形化)模块介绍: Tkinter :是python最简单的图形化模块,总共只有14种组建 Pyqt     :是python最复杂也是使用最广泛的图形化 Wx       ...

  8. 自研WPF插件系统(沙箱运行及热插拔)

    前言 插件化的需求主要源于对软件架构灵活性的追求,特别是在开发大型.复杂或需要不断更新的软件系统时,插件化可以提高软件系统的可扩展性.可定制性.隔离性.安全性.可维护性.模块化.易于升级和更新以及支持 ...

  9. golang 接口动态派发性能问题

    测试代码 package main type Duck interface { Quack() } type Cat struct { Name string } //go:noinline func ...

  10. 鸿蒙HarmonyOS实战-Web组件(Cookie及数据存储)

    前言 Cookie是一种存储在用户计算机上的小文本文件,用于在用户访问网站时存储和提取信息.它由网站服务器发送到用户的浏览器,并存储在用户的计算机上.每当用户访问该网站时,浏览器将发送该Cookie回 ...