美文网首页
Redis持久化、虚拟内存、哨兵模式

Redis持久化、虚拟内存、哨兵模式

作者: ands999 | 来源:发表于2019-09-28 17:19 被阅读0次
持久化

父子进程、aof的日志重写、异步方式写入磁盘

redis支持两种方式的持久化:RDB快照方式,将内存中的数据周期性写入磁盘;AOF日志方式,记录每次更新的日志。

  • Snapshotting快照
    快照就是将内存中的数据以快照的方式写入二进制文件中,默认的文件名为dump.rdb。可以配置redis在n秒内如果超过m个key被修改就自动做快照。
    快照保存过程:
    1)redis调用fork,现在有了子进程和父进程。
    2)父进程继续处理client请求,子进程负责将内存内容写入到临时文件。由于os的写时复制机制(copy on write)父子进程会共享相同的物理页面,当父进程处理写请求时,os会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程的地址空间内的数据是fork时刻整个数据库的一个快照。
    3)当子进程将快照写入临时文件后,用临时文件替换原来的快照文件,然后子进程退出。
    client也可以使用save或者bgsave命令通知redis做持久化快照。save操作是在主线程中保存快照的,这种方式会阻塞所有client请求。所以不推荐使用。
    快照持久化是将内存数据完整写入到磁盘一次,并不是增量的只同步脏数据。如果写操作比较多,会引起大量的磁盘io操作,可能会严重影响性能。
    由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。

  • Append-only file日志
    aof 比快照方式有更好的持久化性,在使用aof持久化方式时,redis会将写命令通过write函数追加到文件中(默认是 appendonly.aof)。当redis重启时会通过重新执行文件中的写命令,在内存中重建整个数据库的内容。由于os会在内核中缓存write做的修改,所以可能不是立即写到磁盘上。这样aof方式的持久化也还是有可能会丢失部分修改。不过可以通过配置文件告诉redis通过fsync函数强制os写入到磁盘的时机。有三种方式如下:

  • appendfsync always //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用

  • appendfsync everysec //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中(默认)。

  • appendfsync no //完全依赖os,性能最好,持久化没保证

aof 方式带来了另一个问题。持久化文件会变的很大。为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。收到此命令redis将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,最后替换原来的文件。具体过程如下:
1)redis调用fork ,现在有父子两个进程
2)子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令
3)父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题。
4)当子进程把快照内容以命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。
5)现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。

  重写aof文件的操作并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。

虚拟内存

VM特性突破了物理内存的限制。
redis的虚拟内存与os的虚拟内存不是同一个事,但是思路和目的都是相同的,就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出内存空间用于其他需要访问的数据。
redis没有使用os提供的虚拟内存机制而是自己在用户态实现了自己的虚拟内存机制,redis作者给出两个理由:

  • os的虚拟内存是以4k页面为最小单位进行交换的。而redis的大多数对象都远小于4k。另外,redis的集合对象类型如list,set可能存在于多个os页面上。最终可能造成只有10%key被经常访问,但是所有os页面都会被os认为是活跃的,这样只有内存真正耗尽时os才会交换页面。

  • 相比于os的交换方式。redis可以将被交换到磁盘的对象进行压缩,保存到磁盘的对象可以去除指针和对象元数据信息。一般压缩后的对象会比内存中的对象小10倍。这样redis的vm会比os vm能少做很多io操作。

    redis的vm在设计上为了保证key的查找速度,只会将value交换到swap文件中。所以如果内存问题是由于太多value很小的key造成的,那么vm并不能解决。和os一样redis也是按页面来交换对象的。redis规定同一个页面只能保存一个对象。但是一个对象可以保存在多个页面中。 在redis使用的内存没超过vm-max-memory之前是不会交换任何value的。当超过最大内存限制后,redis会选择较老的对象。如果两个对象一样老会优先交换比较大的对象。 对于vm-page-size的设置应该根据设置为可以容纳应用中大多数对象的大小。太大了会浪费磁盘空间,太小了会造成交换文件出现碎片。对于交换文件中的每个页面,redis会在内存中对应一个1bit值来记录页面的空闲状态。vm-max-threads表示用做交换任务的线程数量。如果大于0推荐设为服务器的cpu core的数量。如果是0则交换过程在主线程进行。

参数配置讨论完后,简单介绍下vm是如何工作的,

  • 当vm-max-threads为0时(Blocking VM)
    换出:
    主线程定期检查发现内存超出最大上限后,会直接以阻塞的方式,将选中的对象保存到swap文件中,并释放对象占用的内存,此过程会一直重复直到下面条件满足

    1. 内存使用降到最大限制以下
    2. swap文件满了
    3. 几乎全部的对象都被交换到磁盘了
      换入:
      当有client请求value被换出的key时。主线程会以阻塞的方式从文件中加载对应的value对象,加载时此时会阻塞所以client。然后处理client的请求。
  • 当vm-max-threads大于0(Threaded VM)
    换出:
    当主线程检测到使用内存超过最大上限,会将选中的要交换的对象信息放到一个队列中交由工作线程后台处理,主线程会继续处理client请求。
    换入:
    如果有client请求的key被换出了,主线程先阻塞发出命令的client,然后将加载对象的信息放到一个队列中,让工作线程去加载。加载完毕后工作线程通知主线程。主线程再执行client的命令。这种方式只阻塞请求value被换出key的client。
    总的来说blocking vm的方式总的性能会好一些,因为不需要线程同步,创建线程和恢复被阻塞的client等开销。但是也相应的牺牲了响应性。threaded vm的方式主线程不会阻塞在磁盘io上,所以响应性更好。如果我们的应用不太经常发生换入换出,而且也不太在意有点延迟的话则推荐使用blocking vm的方式。

哨兵

Redis的高可用方案被分成了几块来实现:主从复制、主从切换以及虚拟IP或客户端方案。

Sentinel机制是一个分布式架构。每个sentinel节点都会对数据节点和其他sentinel节点进行监控。当发现节点不可用时,自动进行处理,无须人工介入,从而实现redis的高可用。

主从切换

Redis 2.8版开始提供名为Sentinel的主从切换方案,Sentinel用于管理多个Redis服务器实例,主要负责三个方面:
1. 监控(Monitoring): Sentinel 会不断地检查主服务器和从服务器是否运作正常。
2. 提醒(Notification): 当服务器出现问题时, Sentinel可以通过 API 向管理员或者其他应用程序发送通知。
3. 自动故障迁移(Automatic failover): 当主服务器不能正常工作时, Sentinel 会开始自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器。

Redis Sentinel 是一个分布式系统,可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。

使用--sentinel参数启动Sentinel,并必须指定一个对应的配置文件,系统会使用配置文件来保存 Sentinel 的当前状态, 并在 Sentinel 重启时通过载入配置文件来进行状态还原。
配置Sentinel:
1. 主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。
2. 客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的服务器下线判断。
SDOWN适合于master和slave,但是ODOWN只适用于master。

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

Sentinel API
有两种方式可以与Sentinel进行通讯:Sentinel指令、发布与订阅。

相关文章

  • Redis持久化、虚拟内存、哨兵模式

    持久化 父子进程、aof的日志重写、异步方式写入磁盘 redis支持两种方式的持久化:RDB快照方式,将内存中的数...

  • Redis

    什么是Redis Redis的五种数据类型 常见Redis问题 淘汰策略 持久化 主从复制,哨兵模式https:/...

  • 深入学习Redis:主从复制

    在Redis的持久化中曾提到,Redis高可用的方案包括持久化、主从复制(及读写分离)、哨兵和集群。其中持久化侧重...

  • redis真的是单线程么?

    redis服务启动配置 redis-server服务受配置文件控制,配置文件可以控制数据持久化,集群,哨兵模式等都...

  • Redis内容整理(2021-06-29)

    Redis内容整理 目录 基础数据结构 持久化 主从架构 哨兵模式 集群配置 面试整理[https://www.j...

  • 8.Redis复制、哨兵、集群

    Redis复制、哨兵、集群 Redis实现高可用相关的技术,它们包括:持久化、复制、哨兵和集群,其主要作用和解决的...

  • redis持久化机制

    redis持久化机制的原理 一、两种实现redis持久化的机制,RDB模式和AOF模式 ①RDB模式 ②AOF模式...

  • 实现Nginx负载均衡、Session共享、Redis集群(二)

    感谢博主:spring整合redis(哨兵模式)Redis高可用集群-哨兵模式(Redis-Sentinel)搭建...

  • 3.Redis的持久化

    0.redis持久化1.RDB模式2.AOF模式 0.redis 持久化 redis 虽然是一个内存级别的缓存程序...

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

    一、序言 Redis高可用有两种模式:哨兵模式和集群模式,本文基于哨兵模式搭建一主两从三哨兵Redis高可用服务。...

网友评论

      本文标题:Redis持久化、虚拟内存、哨兵模式

      本文链接:https://www.haomeiwen.com/subject/hqruyctx.html