澳门皇冠金沙网站▎在线官网
做最好的网站

Redis-集群与高可用

2020-01-09 作者:网络服务   |   浏览(82)

1.Redis

1- 水平分区 VS 垂直分区

分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集。有两种分区方式:水平分区、垂直分区。

丰富的数据结构

1.1 分区的优势与不足
  1. 优势

通过利用多台计算机内存的和值,允许我们构造更大的数据库。
通过多核和多台计算机,允许我们扩展计算能力;通过多台计算机和网络适配器,允许我们扩展网络带宽

  1. 不足

涉及多个key的操作通常是不被支持的:

  • 当两个set映射到不同的redis实例上时,你就不能对这两个set执行交集操作。
  • 涉及多个key的redis事务不能使用。
  • 当使用分区时,数据处理较为复杂,比如你需要处理多个rdb/aof文件,并且从多个实例和主机备份持久化文件。
  • 增加或删除容量也比较复杂。redis集群大多数支持在运行时增加、删除节点的透明数据平衡的能力,但是类似于客户端分区、代理等其他系统则不支持这项特性。

字符串

1.2 水平分区

水平分区是根据一些规则把同一业务单元的Key拆分到不同的Redis实例上。

  1. 按Range水平分区

最简单的分区方式是按范围分区,就是映射一定范围的对象到特定的Redis实例
比如,ID从0到10000的用户会保存到实例R0,ID从10001到 20000的用户会保存到R1,以此类推
。这种方式是可行的,并且在实际中使用,不足就是要有一个区间范围到实例的映射表。这个表要被管理,同时还需要各种对象的映射表,通常对Redis来说并非是好的方法。优点:规则简单、数据均衡性较好、比较容易扩展;缺点:请求的负载不一定均衡,一般来说,新注册的用户会比老用户更活跃,大range的服务请求压力会更大。

  1. 对Key哈希水平切分

按照Key进行Hash,支持任意类型的Key,然后对得到的Hash值进行取模运算,分配到不同Redis实例上。优点:规则简单、数据均衡性较好、请求均匀性较好;缺点是:不容易扩展,扩展一个数据服务,hash方法改变时候,可能需要进行数据迁移。

Redis字符串能包含任意类型的数据;;

1.3 垂直分区

垂直分区就是把一个Redis实例上的不同业务单元的Key拆分到不同的Redis实例上。

一个字符串类型的值最多能存储512M字节的内容;

2- 持久化

Redis持久化方案主要有RDB和AOF,两者毫无关系,完全独立运行。

利用INCR命令簇来把字符串当作原子计数器使用;

2.1 RDB文件

RDB是整个内存数据的压缩过的某一时刻的Snapshot快照,可以配置复合的触发RDB写的条件,默认是1分钟内改了1万次,或5分钟内改了10次,或15分钟内改了1次。

  1. RDB写入时,会连内存一起Fork出一个新进程,遍历新进程内存中的数据写文件,这样就解决了些Snapshot过程中又有新的写入请求进来的问题。

  2. RDB会先写到临时文件,完了再Rename,这样外部程序对RDB文件的备份和传输过程是安全的。而且即使写新快照的过程中Server被强制关掉了,旧的RDB文件还在。

  3. 可配置是否进行压缩,压缩方法是字符串的LZF算法,以及将string形式的数字变回int形式存储。

  4. 停止RDB保存规则的方法:redis-cli config set save “”

使用APPEND命令在字符串后添加内容。

2.2 AOF文件

操作日志,记录所有有效的写操作,等于mysql的binlog,格式就是明文的Redis协议的纯文本文件。

  1. 一般配置成每秒调用一次fdatasync将kernel的文件缓存刷到磁盘。当操作系统非正常关机时,文件可能会丢失不超过2秒的数据。 如果设为fsync always,性能很低,只剩几百TPS。如果设为no,靠操作系统自己的sync同步,Linux系统一般30秒一次。

  2. AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件,最后再rename), 遍历新进程的内存中数据,每条记录的Set语句。默认配置是当AOF文件大小是上次rewrite后大小的一倍,且文件大于64M时触发。

  3. Redis协议,如set mykey hello, 将持久化成*3 $3 set $5 mykey $5 hello, 第一个数字代表这条语句有多少元,其他的数字代表后面字符串的长度。这样的设计,使得即使在写文件过程中突然关机导致文件不完整,也能自我修复,执行redis-check-aof即可。

列表

2.3 RDB vs AOF

综上:

  1. RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。那要不要只使用AOF呢?作者建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),快速重启,而且不会有AOF可能潜在的bug,留着作为一个万一的手段。

  2. 因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。

  3. 如果Enalbe AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本简单load自己的AOF文件就可以了。代价一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上。

  4. 如果不Enable AOF ,仅靠Master-Slave Replication 实现高可用性也可以。能省掉一大笔IO也减少了rewrite时带来的系统波动。代价是如果Master/Slave同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个。

Redis列表是简单的字符串列表,按照插入顺序排序;

3- 高可用与故障切换

Master-Slave复制与Fail-Over来实现真正的高可用

你可以添加一个元素到列表的头部或者尾部;

3.1 Master-Slave复制

slave可以在配置文件、启动命令行参数、以及redis-cli执行SlaveOf指令来设置自己是奴隶,设置 Slaveof no one,slave会立马变身master;Slave只可以接收客户端的读请求,兼有负载均衡的功能

  1. 复制速度:测试表明同步延时非常小,Master指令一旦执行完毕就会立刻写AOF文件和向Slave转发,除非Slave自己被阻塞住了。

  2. 复制过程:先执行一次Master快照RDB的全同步 — slave请求Master的一个RDB Snapshot文件,slave接收完毕后,清除掉自己的旧数据,然后将RDB载入内存。**再进行增量同步 **— master作为一个普通的client连入slave,将所有写操作转发给slave,没有特殊的同步协议

详细步骤:
1) 在Slave启动并连接到Master之后,它将主动发送一个SYNC命令。
2)此后Master将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次完全同步。
3) 而Slave服务器在接收到数据库文件数据之后将其存盘并加载到内存中。
4)此后,Master继续将所有已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在依次执行这些数据修改命令,从而达到最终的数据同步。
5)如果Master和Slave之间的链接出现断连现象,Slave可以自动重连Master,但是在连接成功之后,一次完全同步将被自动执行。

  1. 特点
  • 同一个Master可以同步多个Slaves。
  • Slave同样可以接受其它Slaves的连接和同步请求,这样可以有效的分载Master的同步压力。因此我们可以将Redis的Replication架构视为图结构。
  • Master Server是以非阻塞的方式为Slaves提供服务。所以在Master-Slave同步期间,客户端仍然可以提交查询或修改请求。
  • SlaveServer同样是以非阻塞的方式完成数据同步。在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据。
  • 为了分载Master的读操作压力,Slave服务器可以为客户端提供只读操作的服务,写服务仍然必须由Master来完成。即便如此,系统的伸缩性还是得到了很大的提高。
  • Master可以将数据保存操作交给Slaves完成,从而避免了在Master中要有独立的进程来完成此操作。
  1. 潜在的问题
    Slave从库在连接Master主库时,Master会进行内存存盘生成快照,然后把整个快照文件发给Slave,也就是没有象MySQL那样有复制位置的概念,即无增量复制,这会给整个集群搭建带来非常多的问题。比如Slave由于网络或者其它原因与Master断开了连接,那么当 Slave进行重新连接时,需要重新获取整个Master的内存快照,Slave所有数据跟着全部清除,然后重新建立整个内存表,一方面Slave恢复的时间会非常慢,另一方面也会给主库带来压力。

一个列表最多可以包含232-1个元素;

3.2 Fail-Ove(sentinel)

Redis-sentinel是2.6版开始加入的另一组独立运行的节点,提供自动Fail Over的支持

在社交网络中建立一个时间线模型,使用LPUSH去添加新的元素到用户时间线中,使用LRANGE去检索一些最近插入的条目;

3.2.1 发现 master/slave及其他sentinel
  1. master地址在sentinel.conf里, sentinel会每10秒一次向master发送INFO,知道master的slave有哪些。
  1. 如果master已经变为slave,sentinel会分析INFO的应答指向新的master。
  2. 另外,sentinel会在master上建一个pub/sub channel,名为”sentinel:hello”,通告各种信息,sentinel们也是通过接收pub/sub channel上的sentinel的信息发现彼此,因为每台sentinel每5秒会发送一次自己的host信息,宣告自己的存在。

你可以同时使用LPUSH和LTRIM去创建一个永远不会超过指定元素数目的列表并同时记住最后的N个元素;

3.2.2 监测与切换过程:
  1. Sentinel每秒钟对所有master,slave和其他sentinel执行Ping,redis-server节点要应答。
  1. 如果某一台Sentinel没有在30秒内(可配置得短一些哦)收到上述正确应答,它就会认为master处于sdown状态(主观Down),它向其他sentinel询问是否也认为该master倒了(SENTINEL is-master-down-by-addr );
  2. 如果quonum台(默认是2)sentinel在5秒钟内都这样认为,就会认为master真是odown了(客观Down)。
  3. 此时会选出一台sentinel作为Leader执行fail-over, Leader会从slave中选出一个提升为master(执行slaveof no one),然后让其他slave指向它(执行slaveof new master)。

列表可以用来当作消息传递的基元,例如,众所周知的用来创建后台任务的Resque Ruby库。

3.3 Redis高可用与故障转移架构设计

基于Sentinel + master/slave

图片 1

上面虽然在server端完成了故障转移,但是对于客户端程序来说,Master切换后client并不知道新Master的IP地址,一种办法是client在访问Server之前都要询问一下Sentinel,获取Master的最新IP。但是明显获取一次数据需要访问两次,网络资源还是比较宝贵的,有一种对client无感更经济实惠的切换方法:VIP漂移。

基于Sentinel + master/slave + VIP漂移

VIP方案是,redis系统对外始终是同一ip地址,当redis进行故障转移时,需要做的是将VIP从之前的redis服务器漂移到现在新的主redis服务器上。

图片 2

故障前

当前redis系统中主redis的ip地址是192.168.56.101,那么VIP(192.168.56.250)指向192.168.56.101,客户端程序用VIP(192.168.56.250)地址连接redis,实际上连接的就是当前主redis,这样就避免了向sentinel发送请求。

图片 3

故障后

当主redis宕机,进行故障转移时,192.168.56.102这台服务器上的redis提升为主,这时VIP(192.168.56.250)指向192.168.56.102,这样客户端程序不需要修改任何代码,连接的是192.168.56.102这台主redis。

如何实现VIP漂移?

  1. 以使用redis sentinel的一个参数client-reconfig-script,这个参数配置执行脚本,sentinel在做failover的时候会执行这个脚本。
  1. 漂移VIP也可以使用keepalived软件来实现。

集合

Redis集合是一个无序的,不允许相同成员存在的字符串合集;

支持一些服务端的命令从现有的集合出发去进行集合运算,如合并,求交(交集:intersection),差集, 找出不同元素的操作;

用集合跟踪一个独特的事。想要知道所有访问某个博客文章的独立IP?只要每次都用SADD来处理一个页面访问。那么你可以肯定重复的IP是不会插入的;

Redis集合能很好的表示关系。你可以创建一个tagging系统,然后用集合来代表单个tag。接下来你可以用SADD命令把所有拥有tag的对象的所有ID添加进集合,这样来表示这个特定的tag。如果你想要同时有3个不同tag的所有对象的所有ID,那么你需要使用SINTER。

使用SPOP或者SRANDMEMBER命令随机地获取元素。

哈希

Redis Hashes是字符串字段和字符串值之间的映射;

尽管Hashes主要用来表示对象,但它们也能够存储许多元素。

有序集合

Redis有序集合和Redis集合类似,是不包含相同字符串的合集;

每个有序集合的成员都关联着一个评分,这个评分用于把有序集合中的成员按最低分到最高分排列;

使用有序集合,你可以非常快地完成添加,删除和更新元素的操作;

元素是在插入时就排好序的,所以很快地通过评分(score)或者位次(position)获得一个范围的元素;

轻易地访问任何你需要的东西: 有序的元素,快速的存在性测试,快速访问集合中间元素;

在一个巨型在线游戏中建立一个排行榜,每当有新的记录产生时,使用ZADD 来更新它。你可以用ZRANGE轻松地获取排名靠前的用户, 你也可以提供一个用户名,然后用ZRANK获取他在排行榜中的名次。 同时使用ZRANK和ZRANGE你可以获得与指定用户有相同分数的用户名单。 所有这些操作都非常迅速;

有序集合通常用来索引存储在Redis中的数据。 例如:如果你有很多的hash来表示用户,那么你可以使用一个有序集合,这个集合的年龄字段用来当作评分,用户ID当作值。用ZRANGEBYSCORE可以简单快速地检索到给定年龄段的所有用户。

复制 一个Master可以有多个Slaves能通过接口其他slave的链接,除了可以接受同一个master下面slaves的链接以外,还可以接受同一个结构图中的其他slaves的链接redis复制是在master段是非阻塞的,这就意味着master在同一个或多个slave端执行同步的时候还可以接受查询复制在slave端也是非阻塞的,假设你在redis.conf中配置redis这个功能,当slave在执行的新的同步时,它仍可以用旧的数据信息来提供查询,否则,你可以配置当redis slaves去master失去联系是,slave会给发送一个客户端错误为了有多个slaves可以做只读查询,复制可以重复2次,甚至多次,具有可扩展性他可以利用复制去避免在master端保存数据,只要对master端redis.conf进行配置,就可以避免保存,然后通过slave的链接,来实时的保存在slave端LRU过期处理 EVAL 和 EVALSHA 命令是从 Redis 2.6.0 版本开始的,使用内置的 Lua 解释器,可以对 Lua 脚本进行求值Redis 使用单个 Lua 解释器去运行所有脚本,并且, Redis 也保证脚本会以原子性(atomic)的方式执行: 当某个脚本正在运行的时候,不会有其他脚本或 Redis 命令被执行。 这和使用 MULTI / EXEC 包围的事务很类似。 在其他别的客户端看来,脚本的效果(effect)要么是不可见的(not visible),要么就是已完成的(already completed)LRU过期处理。

Redis允许为每一个key设置不同的过期时间,当它们到期时将自动从服务器上删除。

事务MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事务的基础事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断事务中的命令要么全部被执行,要么全部都不执行,EXEC 命令负责触发并执行事务中的所有命令 Redis 的 Transactions 提供的并不是严格的 ACID 的事务Transactions 还是提供了基本的命令打包执行的功能: 可以保证一连串的命令是顺序在一起执行的,中间有会有其它客户端命令插进来执行Redis 还提供了一个 Watch 功能,你可以对一个 key 进行 Watch,然后再执行 Transactions,在这过程中,如果这个 Watched 的值进行了修改,那么这个 Transactions 会发现并拒绝执行数据持久化 RDB。

特点:

RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储。

优点:

RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份;

RDB是一个紧凑的单一文件, 非常适用于灾难恢复;

RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能;

与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些。

缺点:

如果你希望在redis意外停止工作的情况下丢失的数据最少的话,那么RDB不适合,Redis要完整的保存整个数据集是一个比较繁重的工作。

RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度。

AOF

特点

AOF持久化方式记录每次对服务器写的操作;

redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。

优点

使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync;

本文由澳门皇冠金沙网站发布于网络服务,转载请注明出处:Redis-集群与高可用

关键词: