Redis¶
Markdown
Redis提供了不同范围的持久性选项:
RDB(Redis数据库):RDB持久性按指定的时间间隔执行数据集的时间点快照。
AOF(仅附加文件):AOF持久性记录服务器接收的每个写入操作,这些操作将在服务器启动时再次播放,以重建原始数据集。使用与Redis协议本身相同的格式记录命令,并且采用仅追加方式。当日志太大时,Redis可以在后台重写日志。
无持久性:如果希望,只要服务器正在运行,数据就一直存在,则可以完全禁用持久性。
RDB + AOF:可以在同一实例中同时合并AOF和RDB。请注意,在这种情况下,当Redis重新启动时,AOF文件将用于重建原始数据集,因为它可以保证是最完整的
redis sentinel哨兵模式主从复制机制
1.一个 master 实例和一个 slave 实例连接正常时, master 会发送一连串的命令流来保持对 slave 的更新,以便于将自身数据集的改变复制给 slave , :包括客户端的写入、key 的过期或被逐出等等
2.master 和 slave 之间的连接断开之后,因为网络问题、或者是主从意识到连接超时, slave 重新连接上 master 并会尝试进行部分重同步:这意味着它会尝试只获取在断开连接期间内丢失的命令流
3.无法进行部分重同步时, slave 会请求进行全量重同步。这会涉及到一个更复杂的过程,例如 master 需要创建所有数据的快照,将之发送给 slave ,之后在数据集更改时持续发送命令流到 slave
RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.
AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.
如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.
你也可以同时开启两种持久化方式, 在这种情况下, 当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整
RDB的优点
RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集.
RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复.
RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.
RDB的缺点
如果你希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合你.虽然你可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),是Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,你可能会丢失几分钟的数据.
RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度.
AOF 优点
使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.
AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.
Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。
AOF 缺点
对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)
优化
使用以下 redis.conf 指令调整特殊编码类型的最大元素数和最大元素大小
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
set-max-intset-entries 512
确保添加vm.overcommit_memory = 1到/etc/sysctl.conf
fs.file-max=100000
确保Redis不会受到Linux内核透明大页面特性的影响,否则会对内存使用和延迟产生负面影响。
通过以下命令完成的:echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
如果您使用复制,请确保您的 master 启用了持久性,或者它不会在崩溃时自动重新启动:副本将尝试成为 master 的精确副本,因此如果 master 以空数据集重新启动,副本也会被抹掉
驱逐政策
当maxmemory达到限制时,Redis 的确切行为是使用maxmemory-policy配置指令配置的。
可以使用以下政策:
noeviction:当达到内存限制并且客户端尝试执行可能导致使用更多内存的命令时返回错误(大多数写命令,但DEL和一些例外)。
allkeys-lru:通过首先尝试删除最近较少使用的 (LRU) 键来驱逐键,以便为添加的新数据腾出空间。
volatile-lru:通过首先尝试删除最近使用的 (LRU) 键来驱逐键,但仅限于设置了过期时间的键,以便为添加的新数据腾出空间。
allkeys-random:随机驱逐密钥以便为添加的新数据腾出空间。
volatile-random:随机驱逐密钥以便为添加的新数据腾出空间,但仅驱逐具有过期设置的密钥。
volatile-ttl:驱逐设置了过期时间的键,并尝试首先驱逐具有较短生存时间(TTL)的键,以便为添加的新数据腾出空间
Redis LRU 算法的重要之处在于,您可以通过更改样本数量来调整算法的精度,以检查每次驱逐。此参数由以下配置指令控制:
maxmemory-samples 5
DISCARD可用于中止事务。在这种情况下,不执行任何命令,连接状态恢复正常
客户端缓存的Redis实现
Redis 客户端缓存支持称为Tracking,有两种模式:
在默认模式下,服务器记住给定客户端访问了哪些键,并在修改相同键时发送无效消息。这会消耗服务器端的内存,但只会为客户端可能在内存中拥有的一组密钥发送失效消息。
相反,在广播模式下,服务器不会尝试记住给定客户端访问了哪些键,因此这种模式在服务器端根本不消耗任何内存。相反,客户端订阅诸如object:或 之类的键前缀user:,并且每次触摸匹配此类前缀的键时都会收到通知消息
redis-cli实用程序支持一种称为管道模式的新模式,该模式旨在执行批量插入,redis-cli 实用程序还将确保仅将从 Redis 实例收到的错误重定向到标准输出
(data.txt内容如:
set key0 value0
......
set keyN value)
命令:cat data.txt | redis-cli --pipe
Redis 中的分区有两个主要目标:
它允许使用多台计算机内存的总和来创建更大的数据库。如果不进行分区,您将受到单个计算机可以支持的内存量的限制。
它允许将计算能力扩展到多核和多台计算机,并将网络带宽扩展到多台计算机和网络适配器
分区方法:范围分区和散列分区
尽管 Redis 中的分区在概念上是相同的,无论是将 Redis 用作数据存储还是缓存,但将其用作数据存储时存在重大限制。当 Redis 用作数据存储时,给定的键必须始终映射到同一个 Redis 实例。当Redis用作缓存时,如果给定节点不可用,使用不同的节点也不是大问题,改变key-instance映射,因为我们希望提高系统的可用性(即提高系统可用性的能力)系统回复我们的查询)。
如果给定键的首选节点不可用,则一致的散列实现通常能够切换到其他节点。同样,如果添加新节点,部分新密钥将开始存储在新节点上。
这里的主要概念如下:
如果将 Redis 用作缓存,则使用一致散列扩展和缩减是很容易的。
如果使用Redis作为存储,则使用固定的key-to-nodes映射,因此节点数必须是固定的,不能变化。否则,需要一个能够在添加或删除节点时在节点之间重新平衡键的系统,目前只有 Redis Cluster 能够做到这一点
为什么 Redis 与其他键值存储不同?
有两个主要原因。
Redis 是键值数据库中不同的进化路径,其中值可以包含更复杂的数据类型,并在这些数据类型上定义原子操作。Redis 数据类型与基本数据结构密切相关,因此向程序员公开,无需额外的抽象层。
Redis 是一个内存中但持久化在磁盘上的数据库,因此它代表了一种不同的权衡,在无法大于内存的数据集的限制下实现了非常高的写入和读取速度。内存数据库的另一个优点是,与磁盘上的相同数据结构相比,复杂数据结构的内存表示更易于操作,因此 Redis 可以做很多事情,而内部复杂性很小。同时这两种磁盘存储格式(RDB 和 AOF)不需要适合随机访问,所以它们很紧凑并且总是以 append-only 的方式生成(即使 AOF 日志轮换也是一个 append-唯一的操作,因为新版本是从内存中的数据副本生成的)。然而,与传统的磁盘存储相比,这种设计也涉及不同的挑战。作为内存上的主要数据表示,Redis 操作必须小心处理,以确保磁盘上始终有数据集的更新版本
可以在不停止和重新启动服务的情况下动态重新配置 Redis,或者使用特殊命令CONFIG SET和 CONFIG GET 以编程方式查询当前配置
并非所有配置指令都以这种方式支持,但大多数都按预期支持,此修改对redis.conf文件没影响,重启恢复旧配置,CONFIG REWRITE命令可以修改redis.conf文件配置
复制
在 Redis 复制的基础上(不包括由 Redis Cluster 或 Redis Sentinel 作为附加层提供的高可用性功能),有一个非常易于使用和配置的领导者跟随者(主从)复制:它允许副本 Redis 实例精确主实例的副本。每次链接断开时,副本都会自动重新连接到主服务器,并且无论主服务器发生什么情况,都将尝试成为它的精确副本。
该系统使用三种主要机制工作:
当主实例和副本实例连接良好时,主实例通过向副本发送命令流来保持副本更新,以复制由于以下原因在主端发生的对数据集的影响:客户端写入、密钥过期或驱逐,任何其他更改主数据集的操作。
当 master 和副本之间的链接断开时,由于网络问题或因为在 master 或副本中检测到超时,副本将重新连接并尝试进行部分重新同步:这意味着它将尝试仅获取部分它在断开连接期间错过的命令流。
当部分重新同步不可能时,副本将要求完全重新同步。这将涉及一个更复杂的过程,其中主节点需要为其所有数据创建快照,将其发送到副本,然后随着数据集的变化继续发送命令流
Redis 复制的一些非常重要的事实:
Redis 使用异步复制,异步复制到主节点确认处理的数据量。
一个主节点可以有多个副本。
副本能够接受来自其他副本的连接。除了将多个副本连接到同一个主节点之外,副本还可以以类似级联的结构连接到其他副本。从 Redis 4.0 开始,所有子副本都将从主副本接收完全相同的复制流。
Redis 复制在主端是非阻塞的。这意味着当一个或多个副本执行初始同步或部分重新同步时,主节点将继续处理查询。
复制在副本端也很大程度上是非阻塞的。当副本执行初始同步时,它可以使用旧版本的数据集处理查询,假设您在 redis.conf 中将 Redis 配置为这样做。否则,您可以将 Redis 副本配置为在复制流关闭时向客户端返回错误。但是,在初始同步后,必须删除旧数据集并加载新数据集。副本将在此短暂窗口期间阻止传入连接(对于非常大的数据集可能长达数秒)。从 Redis 4.0 开始,可以配置 Redis 使旧数据集的删除发生在不同的线程中,但是加载新的初始数据集仍将发生在主线程中并阻塞副本。
复制既可以用于可扩展性,以便为只读查询提供多个副本(例如,可以将慢速O(N)操作卸载到副本),也可以仅用于提高数据安全性和高可用性。
可以使用复制来避免让 master 将完整数据集写入磁盘的成本:一个典型的技术包括配置你的 masterredis.conf来完全避免持久化到磁盘,然后连接一个配置为不时保存的副本,或者使用启用 AOF。但是,必须小心处理此设置,因为重新启动的主服务器将从一个空数据集开始:如果副本尝试与其同步,副本也将被清空
Redis 复制的工作原理
每个 Redis 主节点都有一个复制 ID:它是一个大型伪随机字符串,用于标记数据集的给定故事。每个 master 还采用一个偏移量,该偏移量随着它生成的复制流的每个字节而增加以发送到副本,以便使用修改数据集的新更改来更新副本的状态。即使实际上没有连接副本,复制偏移也会增加,所以基本上每个给定的对:
Replication ID, offset
标识主数据集的确切版本。
当副本连接到主节点时,它们使用PSYNC命令来发送它们的旧主副本 ID 和它们到目前为止处理的偏移量。通过这种方式,master 可以只发送所需的增量部分。但是,如果主缓冲区中没有足够的积压,或者如果副本引用不再已知的历史记录(复制 ID),则会发生完全重新同步:在这种情况下,副本将获得数据集的完整副本,从头开始。
这是完整同步的详细工作方式:
主机启动后台保存过程以生成 RDB 文件。同时,它开始缓冲从客户端接收到的所有新写命令。当后台保存完成后,master 将数据库文件传输到副本,副本将其保存在磁盘上,然后将其加载到内存中。主服务器然后将所有缓冲的命令发送到副本。这是作为命令流完成的,并且与 Redis 协议本身的格式相同。
您可以通过 telnet 自己尝试。当服务器正在做一些工作时连接到 Redis 端口并发出SYNC命令。您将看到批量传输,然后主机收到的每个命令都将在 telnet 会话中重新发出。实际上SYNC是一个旧协议,不再被较新的 Redis 实例使用,但为了向后兼容,它仍然存在:它不允许部分重新同步,所以现在使用PSYNC。
如前所述,当主副本链接由于某种原因出现故障时,副本能够自动重新连接。如果 master 收到多个并发副本同步请求,它会执行单个后台保存以服务所有这些请求
配置基本的 Redis 复制很简单:只需在副本配置文件中添加以下行:
replicaof 192.168.1.1 6379
副本支持默认启用的只读模式。此行为由redis.conf文件中的replica-read-only选项控制,可以在运行时使用CONFIG SET启用和禁用
如果您的主服务器通过 设置了密码requirepass,那么将副本配置为在所有同步操作中使用该密码就很简单了。
要在正在运行的实例上执行此操作,请使用redis-cli并键入:
config set masterauth <password>
要永久设置它,请将其添加到您的配置文件中:
masterauth <password>
Redis 过期允许密钥具有有限的生存时间 (TTL)。这样的功能取决于实例计算时间的能力,但是 Redis 副本会正确复制过期的键,即使使用 Lua 脚本更改了这些键。
为了实现这样的特性,Redis 不能依赖主从同步时钟的能力,因为这是一个无法解决的问题,会导致竞争条件和数据集发散,因此 Redis 使用了三种主要技术来实现使过期密钥的复制能够工作:
副本不会使密钥过期,而是等待主服务器使密钥过期。当 master 使密钥过期(或由于 LRU 将其驱逐)时,它会合成一个DEL命令,并将其传输到所有副本。
然而,由于 master-driven expire,有时副本可能仍然在内存中存在逻辑上已经过期的键,因为 master 无法及时提供DEL命令。为了解决这个问题,副本使用其逻辑时钟来报告密钥不存在,仅用于不违反数据集一致性的读取操作(因为来自主服务器的新命令将到达)。通过这种方式,副本避免报告逻辑上过期的键仍然存在。实际上,使用副本进行缩放的 HTML 片段缓存将避免返回已经比预期生存时间早的项目。
在 Lua 脚本执行期间,不会执行密钥到期。当 Lua 脚本运行时,从概念上讲,master 中的时间是冻结的,因此在脚本运行的所有时间里,给定的键要么存在要么不存在。这可以防止密钥在脚本中间过期,并且需要以保证在数据集中具有相同效果的方式将相同的脚本发送到副本。
一旦一个副本被提升为一个主节点,它就会开始独立地使密钥过期,并且不需要旧主节点的任何帮助
appendonly的持久性如何
可以配置 Redis 将 fsync数据存储在磁盘上的次数。共有三个选项:
appendfsync always:fsync每次将新命令附加到 AOF 时。非常非常缓慢,非常安全。请注意,在执行来自多个客户端或管道的一批命令之后,这些命令会附加到 AOF,因此这意味着单个写入和单个 fsync(在发送回复之前)
appendfsync everysec:fsync每一秒。足够快(在 2.4 中可能和快照一样快),如果发生灾难,您可能会丢失 1 秒的数据。
appendfsync no:永远不要fsync,只需将您的数据交到操作系统的手中。更快、更不安全的方法。通常 Linux 会使用这种配置每 30 秒刷新一次数据,但这取决于内核的精确调整。
建议(和默认)策略是fsync每秒。它既非常快又非常安全。该always策略在实践中很慢,但它支持组提交,因此如果有多个并行写入,Redis 会尝试执行单个fsync操作
AOF文件被截断,尝试redis-check-aof --fix修复,文件损坏,尝试redis-check-aof命令了解问题或手动修复
日志重写使用已用于快照的相同的写时复制技巧。这是它的工作原理:
Redis fork,所以现在我们有一个子进程和一个父进程。
孩子开始在临时文件中写入新的 AOF。
父级在内存缓冲区中累积所有新更改(但同时它将新更改写入旧的仅附加文件中,因此如果重写失败,我们是安全的)。
当子进程完成重写文件时,父进程收到一个信号,并将内存缓冲区附加到子进程生成的文件的末尾。
现在 Redis 原子地将旧文件重命名为新文件,并开始将新数据附加到新文件中
安全
从 3.2.0 版本开始,当 Redis 使用默认配置(绑定所有接口)并且没有任何密码访问它时,它会进入一种称为保护模式的特殊 模式。在这种模式下,Redis 只回复来自环回接口的查询,并回复从其他地址连接的其他客户端有错误,但是系统管理员仍然可以忽略 Redis 给出的错误,只需禁用保护模式或手动绑定所有接口即可
1、配置requirepass
2、添加tls认证(安装openssl开发库,需要编译时make BUILD_TLS=yes,TLS 目前不支持 I/O 线程)
使用 Redis Cluster 时,用于tls-cluster yes为集群总线和跨节点连接启用 TLS
Sentinel主从模式时,连接到主服务器时,Sentinel 将使用该tls-replication 指令来确定是否需要 TLS 或非 TLS 连接
* 运行./utils/gen-test-certs.sh以生成根 CA 和服务器证书。
* 运行./runtest --tls或./runtest-cluster --tls在 TLS 模式下运行 Redis 和 Redis 集群测试
3、禁用特定命令
例如重命名CONFIG命令:rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
禁用CONFIG命令:rename-command CONFIG ""
访问控制
Redis AUTH命令在 Redis 6 中得到了扩展,所以现在可以以两个参数的形式使用它:
AUTH <username> <password>
按旧形式使用时,即:
AUTH <password>
ACL规则
以下是有效 ACL 规则的列表。某些规则只是单个单词,用于激活或删除标志,或对用户 ACL 执行给定的更改。其他规则是与命令或类别名称或键模式等连接的字符前缀
启用和禁用用户:
on:启用用户:可以作为该用户进行身份验证。
off: 禁用用户:不再可以使用此用户进行身份验证,但是已经过身份验证的连接仍然有效。请注意,如果默认用户被标记为off,则新连接将不通过身份验证启动,并且将要求用户发送带有 AUTH 选项的AUTH或HELLO以便以某种方式进行身份验证,无论默认用户配置如何。
允许和禁止命令:
+<command>:将命令添加到用户可以调用的命令列表中。
-<command>:将命令移到用户可以调用的命令列表中。
+@<category>:添加该类别中所有用户调用的命令,有效类别如@admin、@set、@sortedset、...等,通过调用ACL CAT命令查看完整列表。特殊类别@all 表示所有命令,包括当前存在于服务器中的命令,以及将来通过模块加载的命令。
-@<category>: 喜欢+@<category>但从客户端可以调用的命令列表中删除命令。
+<command>|subcommand:允许其他禁用命令的特定子命令。请注意,这种形式不允许像 一样否定-DEBUG|SEGFAULT,而只能以“+”开头。如果该命令作为一个整体已经处于活动状态,则此 ACL 将导致错误。
allcommands: +@all 的别名。请注意,它意味着能够执行通过模块系统加载的所有未来命令。
nocommands: -@all 的别名。
允许和禁止某些键:
~<pattern>:添加可以作为命令的一部分提及的键模式。例如~*允许所有键。该模式是一种类似于KEYS的全局样式模式。可以指定多个模式。
allkeys: 别名~*。
resetkeys:刷新允许的键模式列表。例如 ACL ~foo:* ~bar:* resetkeys ~objects:*,将导致客户端只能访问匹配模式的密钥objects:*。
允许和禁止发布/订阅频道:
&<pattern>:添加可供用户访问的 Pub/Sub 频道的 glob 样式模式。可以指定多个通道模式。请注意,模式匹配仅针对PUBLISH和SUBSCRIBE提到的频道进行,而PSUBSCRIBE需要其频道模式与用户允许的频道模式之间的文字匹配。
allchannels:别名&*允许用户访问所有发布/订阅频道。
resetchannels:如果用户的 Pub/Sub 客户端不再能够访问其各自的频道和/或频道模式,则刷新允许的频道模式列表并断开它们的连接。
为用户配置有效密码:
><password>:将此密码添加到用户的有效密码列表中。例如,>mypass将“mypass”添加到有效密码列表中。该指令清除nopass标志(见下文)。每个用户可以有任意数量的密码。
<<password>:从有效密码列表中删除此密码。如果您尝试删除的密码实际上未设置,则会发出错误。
#<hash>:将此 SHA-256 哈希值添加到用户的有效密码列表中。该散列值将与为 ACL 用户输入的密码的散列进行比较。这允许用户在acl.conf文件中存储哈希值,而不是存储明文密码。只接受 SHA-256 哈希值,因为密码哈希必须是 64 个字符,并且只能是容器小写十六进制字符。
!<hash>:从有效密码列表中删除此哈希值。当您不知道哈希值指定的密码但想要从用户中删除密码时,这很有用。
nopass:用户设置的所有密码都被删除,并且用户被标记为不需要密码:这意味着每个密码都将对该用户起作用。如果此指令用于默认用户,则每个新连接将立即使用默认用户进行身份验证,而无需任何明确的 AUTH 命令。请注意,resetpass指令将清除此条件。
resetpass:刷新允许的密码列表。此外,还删除了nopass状态。在resetpass之后,用户没有关联的密码,如果不添加一些密码(或稍后将其设置为nopass),就无法进行身份验证。
注意:没有用 nopass 标记并且没有有效密码列表的使用实际上是不可能使用的,因为将无法以这样的用户身份登录。
重置用户:
reset执行以下操作:resetpass、resetkeys、resetchannels、off、-@all。用户在创建后立即返回到相同的状态
可以通过两种主要方式创建和修改用户:
使用 ACL 命令及其ACL SETUSER子命令。
修改服务器配置,在那里可以定义用户,并重新启动服务器,或者如果我们使用外部 ACL 文件,只需发出ACL LOAD
定义用户(用户名是区分大小写的),使其处于活动状态,具有密码,并且可以仅使用GET命令访问以字符串“cached:”开头的键名:
ACL SETUSER alice on >p1pp0 ~cached:* +get
ACL GENPASS使用系统加密伪随机生成器生成密码
两种方法存储用户在redis配置中。
1. user <username> ... acl rules ...
例如:
user worker +@list +@connection ~jobs:* on >ffa9203c493aa99
2. 使用外部 ACL 文件时,如下所示:
aclfile /etc/redis/users.acl
哨兵和副本的 ACL 规则
如果您不想提供 Redis 副本和 Redis Sentinel 实例对您的 Redis 实例的完全访问权限,以下是必须允许的一组命令,以便一切正常工作
对于 Sentinel,允许用户在主实例和副本实例中访问以下命令:
AUTH、CLIENT、SUBSCRIBE、SCRIPT、PUBLISH、PING、INFO、MULTI、SLAVEOF、CONFIG、CLIENT、EXEC。
Sentinel 不需要访问数据库中的任何键,但会使用 Pub/Sub,因此 ACL 规则如下(注意:AUTH 不需要,因为总是允许的):
ACL SETUSER sentinel-user on >somepassword allchannels +multi +slaveof +ping +exec +subscribe +config|rewrite +role +publish +info +client|setname +client|kill +script|kill
Redis 副本需要在主实例上将以下命令列入白名单:
PSYNC、REPLCONF、PING
不需要访问密钥,因此这转化为以下规则:
ACL setuser replica-user on >somepassword +psync +replconf +ping
Redis Sentinel
Sentinel功能的完整列表:
监控。Sentinel 会不断检查您的主实例和副本实例是否按预期工作。
通知。Sentinel 可以通过 API 通知系统管理员或其他计算机程序,其中一个受监控的 Redis 实例出现问题。
自动故障转移。如果 master 没有按预期工作,Sentinel 可以启动一个故障转移过程,其中一个副本被提升为 master,其他额外的副本被重新配置为使用新的 master,并且使用 Redis 服务器的应用程序会被告知要使用的新地址连接时。
配置提供程序。Sentinel 充当客户端服务发现的权威来源:客户端连接到 Sentinel 以请求负责给定服务的当前 Redis 主节点的地址。如果发生故障转移,Sentinels 将报告新地址
Sentinel 本身旨在运行在多个 Sentinel 进程协同工作的配置中。多个 Sentinel 进程协作的优势如下:
当多个 Sentinel 同意给定主服务器不再可用的事实时,将执行故障检测。这降低了误报的可能性。
即使并非所有 Sentinel 进程都在工作,Sentinel 也能正常工作,从而使系统能够抵御故障
Sentinel 的基本知识
您至少需要三个 Sentinel 实例才能进行稳健的部署。
应该将三个 Sentinel 实例放置在被认为以独立方式发生故障的计算机或虚拟机中。例如,在不同的可用区域上执行的不同物理服务器或虚拟机。
Sentinel + Redis 分布式系统不保证在故障期间保留已确认的写入,因为 Redis 使用异步复制。然而,有一些方法可以部署 Sentinel,使丢失写入的窗口限于某些时刻,而还有其他不太安全的部署方法。
您的客户需要 Sentinel 支持。流行的客户端库有 Sentinel 支持,但不是全部。
如果您不在开发环境中不时进行测试,则没有安全的 HA 设置,或者如果可以的话,在生产环境中,如果它们可以工作,则更好。您可能有一个错误配置,只有在为时已晚(在您的主人停止工作的凌晨 3 点)时才会变得明显。
Sentinel、Docker 或其他形式的网络地址转换或端口映射应小心混合:Docker 执行端口重新映射,破坏其他 Sentinel 进程的 Sentinel 自动发现以及主服务器的副本列表。查看本文档后面有关 Sentinel 和 Docker 的部分以获取更多信息
典型的最小配置文件sentinel.conf如下所示:
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
逐行检查配置选项的含义:
第一行用于告诉 Redis 监视名为mymaster的主节点,该主节点位于地址 127.0.0.1 和端口 6379,仲裁为 2。一切都很明显,但仲裁参数:
该仲裁是需要同意的事实主人是不可达的,这样才能真正纪念主为失败,并在可能最终开始故障转移过程哨兵的数量。
然而,仲裁仅用于检测故障。为了实际执行故障转移,其中一个哨兵需要被选为故障转移的领导者并被授权继续。这只发生在大多数 Sentinel 进程的投票中。
因此,例如,如果您有 5 个 Sentinel 进程,并且给定 master 的仲裁设置为值 2,则会发生以下情况:
如果两个 Sentinel 同时同意 master 无法访问,则两者之一将尝试启动故障转移。
如果总共至少有三个 Sentinel 可访问,则故障转移将被授权并实际开始。
实际上,这意味着在故障期间,如果大多数 Sentinel 进程无法通信(也就是少数分区中没有故障转移),则Sentinel 永远不会启动故障转移
down-after-milliseconds 是 Sentinel 开始认为它已关闭的实例不应该可达的时间(以毫秒为单位)(要么不回复我们的 PING,要么回复错误)。
parallel-syncs设置可以在故障转移后同时重新配置为使用新主服务器的副本数。数字越小,完成故障转移过程所需的时间就越长,但是如果将副本配置为提供旧数据,您可能不希望所有副本同时与主服务器重新同步。虽然复制过程对于副本来说大多是非阻塞的,但有时它会停止从主服务器加载批量数据。您可能希望通过将此选项设置为值 1 来确保一次只能访问一个副本
可以在运行时修改配置参数:
使用SENTINEL SET
全局配置参数使用SENTINEL CONFIG SET
将新 Sentinel 添加到您的部署中是一个简单的过程。您需要做的就是启动配置为监视当前活动主站的新 Sentinel。在 10 秒内,Sentinel 将获取其他 Sentinel 的列表以及附加到 master 的副本集
移除 Sentinel 有点复杂:Sentinels 永远不会忘记已经见过的 Sentinels,即使它们很长时间无法访问,因为我们不想动态更改授权故障转移和创建新配置所需的多数数字。因此,为了删除 Sentinel,应在没有网络分区的情况下执行以下步骤:
停止要删除的 Sentinel 的 Sentinel 进程。
SENTINEL RESET *向所有其他 Sentinel 实例发送命令(*如果您只想重置一个主服务器,则可以使用确切的主服务器名称)。一个接一个,实例之间至少等待 30 秒。
通过检查SENTINEL MASTER mastername每个 Sentinel的输出,检查所有 Sentinel 是否同意当前活动的 Sentinel 数量
删除旧的 master 或无法访问的副本
Sentinel 永远不会忘记给定 master 的副本,即使它们很长一段时间都无法访问。这很有用,因为哨兵应该能够在网络分区或故障事件后正确地重新配置返回的副本。
此外,在故障转移之后,故障转移的主服务器实际上被添加为新主服务器的副本,这样一旦新主服务器再次可用,它将被重新配置为与新主服务器进行复制。
但是,有时您希望从 Sentinels 监控的副本列表中永远删除一个副本(可能是旧的 master)。
为此,您需要向SENTINEL RESET mastername所有 Sentinel发送一个命令:它们将在接下来的 10 秒内刷新副本列表,只添加从当前主INFO输出中列为正确复制的副本
Redis 实例有一个名为replica-priority. 此信息由 Redis 副本实例在其INFO输出中公开,Sentinel 使用它从可用于故障转移主服务器的副本中选择一个副本:
如果副本优先级设置为 0,则副本永远不会提升为主服务器。
Sentinel 首选具有较低优先级编号的副本
从 Redis 6 开始,用户身份验证和权限由访问控制列表 (ACL) 管理。
为了让 Sentinel 在配置了 ACL 时连接到 Redis 服务器实例,Sentinel 配置必须包含以下指令:
sentinel auth-user <master-group-name> <username>
sentinel auth-pass <master-group-name> <password>
启用延迟监控,记录所有阻塞服务器的时间等于或大于 100 毫秒的事件
CONFIG SET latency-monitor-threshold 100
LATENCY LATEST - 返回所有事件的最新延迟样本。
LATENCY HISTORY - 返回给定事件的延迟时间序列。
LATENCY RESET - 重置一个或多个事件的延迟时间序列数据。
LATENCY GRAPH - 呈现事件延迟样本的 ASCII 艺术图。
LATENCY DOCTOR - 回复人类可读的延迟分析报告
Redis Cluster
Redis Cluster数据 在多个 Redis 节点之间自动分片,当部分节点出现故障或无法与集群的其余部分通信时继续操作的能力
Redis Cluster 不支持像 Redis 的独立版本那样支持多个数据库。只有数据库 0 并且不允许使用SELECT命令
为了使 Docker 兼容 Redis Cluster,需要使用Docker的主机组网方式
Redis Cluster 不使用一致性散列,而是一种不同形式的分片,其中每个键在概念上都是我们所谓的散列槽的一部分,集群中有 16384 个哈希槽
Redis Cluster在redis.conf文件中引入的配置参数
cluster-enabled<yes/no>:如果是,则在特定 Redis 实例中启用 Redis Cluster 支持。否则,该实例像往常一样作为独立实例启动。
cluster-config-file<filename>:注意,尽管这个选项的名称,这不是一个用户可编辑的配置文件,而是一个Redis Cluster节点在每次有变化时自动持久化集群配置(状态,基本上)的文件,以便能够在启动时重新读取它。该文件列出了集群中的其他节点、它们的状态、持久变量等内容。由于某些消息接收,此文件通常会被重写并刷新到磁盘上。
cluster-node-timeout<milliseconds>:Redis 集群节点不可用的最长时间,而不被视为失败。如果主节点在指定的时间内无法访问,它将由其从属节点进行故障转移。该参数控制Redis Cluster中其他重要的事情。值得注意的是,在指定的时间内无法访问大多数主节点的每个节点都将停止接受查询。
cluster-slave-validity-factor<factor>:如果设置为零,则从站将始终认为自己有效,因此将始终尝试对主站进行故障转移,无论主站和从站之间的链接保持断开连接的时间长短。如果值为正,则计算最大断开时间为节点超时值乘以此选项提供的因子,如果节点是从节点,如果主链接断开的时间超过指定的时间,它将不会尝试启动故障转移。例如,如果节点超时设置为 5 秒,并且有效性因子设置为 10,则从站与主站断开连接超过 50 秒的从站将不会尝试对其主站进行故障转移。请注意,如果没有能够对其进行故障转移的从属服务器,则任何非零值都可能导致 Redis 集群在主服务器故障后不可用。在这种情况下,只有当原始主节点重新加入集群时,集群才会恢复可用。
cluster-migration-barrier<count>:一个主站将保持连接的最小从站数量,以便另一个从站迁移到不再被任何从站覆盖的主站。有关更多信息,请参阅本教程中有关副本迁移的相应部分。
cluster-require-full-coverage<yes/no>:如果将其设置为 yes,默认情况下,如果任何节点未覆盖一定百分比的密钥空间,则集群将停止接受写入。如果该选项设置为 no,即使只能处理有关密钥子集的请求,集群仍将提供查询服务。
cluster-allow-reads-when-down<yes/no>:如果设置为 no,默认情况下,当集群被标记为失败时,Redis 集群中的节点将停止为所有流量提供服务,或者当节点无法访问时达到法定人数或未达到完全覆盖时。这可以防止从不知道集群变化的节点读取潜在的不一致数据。可以将此选项设置为 yes 以允许在失败状态期间从节点读取,这对于希望优先考虑读取可用性但仍希望防止不一致写入的应用程序非常有用。它也可以用于使用只有一个或两个分片的 Redis Cluster 时,因为它允许节点在主节点发生故障但无法自动故障转移时继续提供写入服务
快速方法可使用 create-cluster 脚本创建 Redis 集群
只需键入以下命令
1、create-cluster start
2、create-cluster create
完成后,使用以下命令停止集群:
create-cluster stop
以下手动创建集群简单示例
最小的Redis集群配置文件:
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
启用集群模式的只是cluster-enabled 指令。每个实例还包含存储此节点配置的文件的路径,默认情况下为nodes.conf. 这个文件永远不会被人类触及;它只是在 Redis 集群实例启动时生成,并在每次需要时更新
按预期工作的最小集群需要包含至少三个主节点。对于您的第一次测试,强烈建议启动一个具有三个主节点和三个从节点的六节点集群
要为 Redis 5版本创建集群,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-trib.rb用于Redis的4或3版本:
./redis-trib.rb 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 Cluster 使用CLUSTER FAILOVER 命令支持手动故障转移,该命令必须在要进行故障转移的主站的从站之一中执行
使用redis-cli将节点添加到现有集群中
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
添加新节点作为副本
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000 --cluster-slave
此处的命令行与我们用于添加新主服务器的命令行完全相同,因此我们没有指定要将副本添加到哪个主服务器。在这种情况下,redis-cli 会在副本较少的主节点中添加新节点作为随机主节点的副本。
但是,您可以使用以下命令行准确指定要使用新副本定位的主服务器
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000 --cluster-slave --cluster-master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
将副本添加到特定主节点的更手动方法是将新节点添加为空主节点,然后使用CLUSTER REPLICATE命令将其转换为副本
redis 127.0.0.1:7006> cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
删除节点
redis-cli --cluster del-node 127.0.0.1:7000 `<node-id>`
升级Redis集群中的节点
升级从节点很容易,因为您只需要停止节点并使用更新版本的 Redis 重新启动它。如果有客户端使用从节点扩展读取,如果给定的从节点不可用,它们应该能够重新连接到不同的从节点。
升级masters有点复杂,建议的程序是:
使用 CLUSTER FAILOVER 触发主从手动故障转移到其从属之一(请参阅本文档的“手动故障转移”部分)。
等待主人变成奴隶。
最后像升级从节点一样升级节点。
如果您希望 master 成为您刚刚升级的节点,请触发新的手动故障转移,以便将升级后的节点恢复为 master