[译]Redis Cookbook(4)

        在这一章,我们不再讨论应用开发或数据建模,我们将着重关注Redis服务器的运维问题。运维工作纷繁复杂,不过总会包含这些方面的内容:启动备份服务器,升级服务器,备份数据,对服务器进行分片,处理海量数据的存储问题。

配置持久化功能

问题

        Redis支持持久化,这是它比其它键值存储引擎(如memcached)更甚一筹的地方。实际上,默认配置的Redis就支持该功能。有了这个功能,可以对服务器进行不停机升级或备份,而这些操作在其它同类存储引擎上几乎不可能。

        不过不管怎样,持久化功能需要根据具体的数据状况和使用方式进行配置。

解决方案

        快照是Redis默认的持久化模式,它会把整个数据库以RDB的格式存储到磁盘上。持久化动作会按照指定的时间间隔发生,或者在指定数量的键发生变化后被触发。另一种持久化模式是AOF,如果你的数据量比较大,或者数据更新不频繁,AOF会是更好的选择。

讨论

快照

        上面已经提到,快照是Redis默认的持久化模式。它异步地把整个数据库转储到磁盘上,在转储成功后会覆盖掉之前的文件。

        你可以在配置文件里对快照进行配置,格式如下:   

save seconds keys-changed

        当配置的两个条件都满足时,快照动作就会被触发。如果你想每过几分钟就把数据保存一次,那么可以这样配置:save 600 1。它的意思是,每过十分钟,如果有任何一个键被修改,那么就保存一次快照。

        你也可以使用SAVE和BGSAVE命令来手动触发快照。BGSAVE会从Redis主进程创建出一个子进程,然后在后台把数据写入磁盘。如果配置文件里配置了SAVE命令,Redis会自动执行这个命令。SAVE命令跟BGSAVE做的事情是一样的,只是它在前台做,所以会阻塞整个服务器。

        如果你认为快照会给服务器带来太大压力,那么可以把持久化放在备份服务器上做,或者使用AOF。特别是如果你的数据量比较大,或者数据更新不频繁,那么更应该使用AOF。

AOF

        AOF持久化模式把操作数据的命令保存在单独的文件里。跟大多数现代操作系统的写操作一样,操作命令先是被放在内存的缓冲区中,然后每过几秒钟通过系统调用fsync写入磁盘。你可以在配置文件里配置appendfsync来控制AOF的同步频度,它的值可以是always,everysec,或no。

        AOF可以和快照同时使用。不过你可能会尽量避免使用快照,因为它会给服务器带来额外的压力。如果不使用快照,那么要确保AOF是写在磁盘阵列上的,或者要确保有一个备份服务器作为灾备。

启动备份服务器

问题

        有很多原因我们需要用到数据库备份服务器,或许用它们来负载均衡,或许让它们随时候命,或许为了方便维护,或者只是为了检查数据。

解决方案

        Redis原生支持主备复制,一个主服务器可以有多个备份服务器,备份服务器之间也相互连接。为了开启复制功能,可以在服务器启动之前在配置文件里配置,也可以在已经运行的服务器上使用SLAVEOF命令。

讨论

        在redis.conf里面添加配置信息来配置一个备份服务器:   

slaveof master-ip-or-hostname masterport

        配置好后启动或者重启服务器。如果主服务器启用了密码保护,需要指定密码:   

masterauth master-password

        可以使用SLAVEOF命令把一个主服务器变成备份服务器:

SLAVEOF master-ip-or-hostname [masterport]

        如果主服务器启用了密码保护,需要事先指定密码:   

CONFIG SET masterauth password

        如果服务器重启,通过命令配置的信息会丢失,所以最好把它们配置在文件里。

用Redis替代Memcache

问题

        Memcache是一个高性能分布式缓存系统,它提供了一个简单轻量的基于内存的键值存储引擎,使用十分广泛。Redis支持Memcache所有功能特性,同时提供了更多额外的功能,你完全可以在缓存基础架构里使用Redis替代Memcache。

解决方案

        我们把解决方案的焦点放在如何通过配置Redis来消除它与Memcache之间的两个主要差异上:持久化和内存使用限制。因为Memcache不支持持久化,所以我们也要在Redis里禁用这个功能,同时限制Redis的最大使用内存。

讨论

        之前的章节介绍了如何配置Redis的持久化模式,但是没有说明如何禁用这个功能。其实很简单,只要把save配置语句从redis.conf移除,然后把appendfsync设置为no。持久化功能默认是打开的,所以之前如果没有对Redis做过配置,这个功能可能还是打开的,这一点要注意。

        在内存使用限制方面,Redis允许我们对使用量和清理策略进行配置,清理策略在内存使用达到上限时会触发。内存使用量的配置直接了当,比如maxmemory 1g表示最大内存使用量为1个G。清理策略maxmemory-policy决定了Redis在内存使用量达到上限时所采用的是哪一种清理动作:

  • volatile-lru  使用LRU算法移除非稳定键
  • allkeys-lru  使用LRU算法移除普通键
  • volatile-random  随机移除非稳定键
  • allkeys-random  随机移除普通键
  • volatile-ttl  移除TTL值最低的键
  • noeviction  不移除。如果内存已经达到最大使用量,针对数据库的写操作会抛出异常。

        跟Redis其它配置变量一样,这些配置都可以通过CONFIG SET这种编程方式来进行。

升级Redis

问题

        在你系统的有生之年,你可能需要对Redis进行升级。不幸的是,Redis不支持在线升级,而重启服务器意味着应用客户端在一小段时间内无法与服务器进行交互。不过,要想做到不停机升级并非不可能。况且,还有其它一些情况会导致停机,比如因为硬件升级,需要把Redis数据库迁移到另一个系统上。

解决方案

        我们的方案是这样的,我们会启动一个备份服务器,在主服务器停机的时候把客户端连接切换到备份服务器上,同时把备份服务器提升成主服务器。我们举个简单的例子,假设有一个Redis服务器,它的端口是6379。

1.在不重启现有Redis服务器的前提下安装新版本的Redis。

2.创建一个新的redis.conf文件,把Redis端口配置成6380,再配置一个不同的DB目录。

3.启动新的服务器。

4.连接到新服务器,并执行命令:   

SLAVEOF localhost 6379

    这个命令会让主服务器执行BGSAVE,完成以后新服务器会开始复制。可以在新服务器上使用INFO命令来查看复制情况。如果你看到master_link_status:up,说明复制在进行中。

5.现在新服务器已经更新到最新,可以把客户端连接迁移到新服务器上了。使用INFO命令,检查connected_clients变量,可以查看有多少个客户端连接到服务器上。

        等到所有客户端都连接到新的服务器上,还需要做两件事情:停止复制,关闭主服务器。

1.连接到新服务器上,并执行命令:

SLAVEOF NO ONE

        这个命令会停止复制,并把备份服务器提升为主服务器。

2.现在连接到旧的服务器上,并执行命令:

SHUTDOWN

        旧服务器会在执行完SAVE后关闭。

3.现在新服务器可以正常运行了,不过还是要确保所有的配置文件,初始化脚本,备份文件等都指向正确的位置,确保启动的是正确的那个服务器。这些操作很容易被遗漏,你至少要确保一旦服务器重启不会出现任何错误。

讨论

        进行在线升级需要满足一些条件:要么你有办法把客户端连接转移到另一个服务器上,比如使用代理,或者客户端内置了失效转移支持;要么直接告诉客户端,让它们自己连接到另一个服务器上。除此以外,还要求有两倍大小的内存可以使用。不过在线升级可能存在风险,要看你是从什么版本升级到什么版本。一般来说,小版本升级是安全的,但对于大版本升级就要小心翼翼。跟其它维护工作一样,在生产环境升级服务器之前要做好充分测试。

备份Redis

问题

        当人们说到NoSQL数据库,一个经常被提及的问题是数据备份问题。认为NoSQL数据库难以备份其实是个误区,那些用来备份关系型数据库的技术手段也适用于NoSQL数据库。

        抓取某一时刻的快照,这对于某些分布式数据库来说或许是个微妙的事情,但对Redis来说肯定不是。在这一章节,我们将解释如何对Redis进行备份。不过这也取决于你所使用的是何种持久化模式。我们假设Redis是运行在Linux系统上,因为需要用到一些特别的文件操作功能,尽管这些功能在其它平台上也有。

解决方案

        我们的方案十分依赖Redis的持久化模式:

  • 如果使用的是默认的快照模式,最好选择使用快照作为备份。
  • 如果使用的是AOF模式,需要对日志进行备份,这样在服务器重启的时候可以进行重放。

        使用哪一种备份方式取决于你自己。最理想的方案是这样的:至少保留几个备份,至少有一个离线的空间来存放备份,备份过程是全自动化的。我们将分别解释在不同持久化模式下如何进行备份,不过在实际进行备份的时候要确保做好测试,恢复过程也需要测试。

        要记住一点,备份会给生产环境带来额外的压力,所以备份最好是在Redis备份服务器上进行。同时运行几个备份服务器是个好主意,一旦主服务器宕机,提升一个备份服务器成为主服务器比从一个备份文件恢复服务器要快得多。

讨论

快照

        快照是Redis的默认持久化模式。之前已经提到,根据你实际的配置情况,如果在n秒内有m个键发生变化,Redis就会把数据写到磁盘上。在使用这个模式的时候,备份操作是很简单的。我们所要做的就是把快照拷贝到一个安全的地方。

        如果你需要最新的快照,可以使用命令:

redis-cli BGSAVE

        然后等待生成转储文件。在拷贝之前确保先对快照文件进行压缩,可以把文件压缩到十分之一大小。

        恢复一个快照文件也很简单。关闭服务器,把快照文件放到redis.conf指定的dbfilename目录,然后启动服务器。这个顺序很关键,因为Redis在关闭的时候会生成一个快照文件,把现有的文件覆盖掉。

AOF

        如果你使用的是AOF模式,最简单的备份方式仍然是使用快照,这个在之前的例子已经描述过。不过,你可能担心快照之间会丢失数据,你可能还会担心因快照给服务器带来的额外压力而避免使用快照。

        要在AOF模式下恢复数据,这个过程跟快照模式差不多,只是要把备份文件放到AOF所在的位置。Redis在启动的时候会重放那些日志。

        在AOF模式下一定要记得时不时得运行BGREWRITEAOF命令。

        在服务器宕机或写入文件时被中断,会产生不完整的AOF文件,Redis服务器在启动时会拒绝重放这样的日志,这个时候可以用redis-check-aof命令来修复AOF日志文件:

redis-check-aof --fix filename

用Sentinel实现高可用

问题

        跟其它分布式系统一样,使用Redis开发应用服务,会在系统里引入单点问题。因此,在Redis Cluster出现之前,我们依赖的是单个Redis实例,节点的失效会导致出现停机时间或者服务不可用。

解决方案

        Redis在2.6版本发布了Sentinel。Sentinel是一个分布式监控系统,它会不断检查Redis实例的状态,自动进行失效转移,客户端通过Sentinel可以重新连接到新的主服务器上。这会让你的应用更健壮,因为只要你有一个在运行的备份服务器,在主服务器宕机的时候它被提升为主服务器,并很快地恢复服务能力。

讨论

        要使用Sentinel,需要做一些配置:

sentinel monitor master-name ip redis-port quorum
sentinel down-after-milliseconds master-name milliseconds
sentinel failover-timeout master-name milliseconds
sentinel parallel-syncs master-name numslaves

        启动Sentinel:

redis-server /path/to/sentinel.conf --sentinel

        Sentinel从主服务器获取所有备份服务器的信息,然后开始监控整个集群。

        要注意,要判定一个Redis主服务器是否宕机或是否需要失效转移,需要至少quorum个Sentinel节点达成一致。所以你的集群里至少需要quorum个Sentinel节点,或者更多。

        为了便于观察,你也可以在Sentinel集群里定义更多的主服务器。更多深入的内容,可以参考Sentinel配置示例。

        为了让应用知道Sentinel的存在,并且具备失效转移的能力,需要让客户端通过Redis协议与Sentinel节点直接进行交互。使用redis-sentinel这样的客户端可以很容易地完成这个任务,它会在失效转移以后重新连接到新的主服务器上。

        使用redis-sentinel跟使用其它Redis客户端一样,不过你需要提供master-name和Sentinel节点列表,而不只是Redis主服务器的地址跟端口:
 

require 'redis-sentinel'
$r = Redis.new(master_name: "master-name",sentinels: [{host: "first-sentinel-host", port: 26379},{host: "second-sentinelhost",port: 26380}])

Redis分片

问题

        分片是经常被用到的数据库水平分区技术,它使得你可以把数据分布到几个不同的数据库实例上。这样不仅仅让你可以存储更大的数据集,还能打破CPU的使用限制问题,这个跟可以使用更大的内存一样,因为不同的实例是分布在不同的机器上。

        Redis的分片是在客户端或者应用程序里实现的。

解决方案

        当单个Redis实例无法满足数据存储需求的时候,分片是一个很有用的技术,它可以让你的应用可以横向扩展。

        对Redis来说,目前有三种分片可能性:

  • 内置分片支持的客户端
  • 基于已有客户端实现分片功能
  • 使用代理,让代理来处理分片

讨论

        如果你决定要自己实现分片,可能会用到一致性哈希。在添加或移除分片时,一致性哈希可以保证最少数量的重哈希。

        分片无法替代复制,确保你的集群有冗余,这样服务器宕机不会导致数据的丢失。

        还有一些需要注意的事情,你无法对分布在不同分片上的多个键同时进行操作。如果一定要这么做,那么需要调整哈希算法,保证那些键是分布在同一个分片上。

转载于:https://my.oschina.net/xuemingdeng/blog/741741

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值