Redis之(六)配置详解

时间:2023-03-08 15:39:58
Redis之(六)配置详解

进入Redis的安装包,里面的“redis.conf”就是默认的配置文件,启动Redis Server的时候,可以指定加载某个路径下的配置文件“redis-server [path of configuration file]”。

默认的配置文件中,首先约定了存储单位:

1k => 1000 bytes

1kb => 1024 bytes

1m => 1000000 bytes

1mb => 1024*1024 bytes

1g => 1000000000 bytes

1gb => 1024*1024*1024 bytes

Redis配置中对单位的大小写不敏感,1GB、1Gb和1gB都是相同的。由此也说明,Redis只支持bytes,不支持bit单位。

Redis支持以“includes”的方式引入其他配置文件,比如:

include/path/to/local.conf

include/path/to/other.conf

需要注意的是,假如多个一个配置项在不同配置文件中都有定义,则以最后一行读入的为准,就是说后面的配置项会覆盖前面的配置项

7.1通用配置

默认情况下,Redis并不是以daemon形式来运行的。通过daemonize配置项可以控制Redis的运行形式,如果改为yes,那么Redis就会以daemon形式运行:

daemonize no

当以daemon形式运行时,Redis会生成一个pid文件,默认会生成在/var/run/Redis.pid。当然,可以通过pidfile来指定pid文件生成的位置,比如:

pidfile /path/to/Redis.pid

默认情况下,Redis会响应本机所有可用网卡的连接请求。当然,Redis允许通过bind配置项来指定要绑定的IP,比如:

bind 192.168.1.2 10.8.4.2

Redis的默认服务端口是6379,可以通过port配置项来修改。如果端口设置为0的话,Redis便不会监听端口了。

port 6379

可是,如果Redis不监听端口,还怎么与外界通信呢?其实Redis还支持通过unix socket方式来接收请求。可以通过unix socket配置项来指定unix socket文件的路径,并通过unix socket perm来指定文件的权限。

unixsocket /tmp/Redis.sock

unixsocketperm 700

在高QPS的环境下需要提高backlog的值来避免TCP的慢连接问题。想要提高backlog的值,除了需要设置Redis的tcp-backlog,还要同时提高更改Linux的配置,否则,Linux内核会默认将其截取为/proc/sys/net/core/somaxconn的大小。

tcp-backlog 511

当一个Redis-client一直没有请求发向server端,那么server端有权主动关闭这个连接,可以通过timeout来设置“空闲超时时限”,0表示永不关闭。

timeout 0

TCP连接保活策略,可以通过tcp-keepalive配置项来进行设置,单位为秒,假如设置为60秒,则server端会每60秒向连接空闲的客户端发起一次ACK请求,以检查客户端是否已经挂掉,对于无响应的客户端则会关闭其连接。所以关闭一个连接最长需要120秒的时间。如果设置为0,则不会进行保活检测。

tcp-keepalive 0

Redis支持通过loglevel配置项设置日志等级,共分四级,即debug、verbose、notice、warning。

loglevel notice

Redis也支持通过logfile配置项来设置日志文件的生成位置。如果设置为空字符串,则Redis会将日志输出到标准输出。假如在daemon情况下将日志设置为输出到标准输出,则日志会被写到/dev/null中。

logfile ""

如果希望日志打印到syslog中,也很容易,通过syslog-enabled来控制。另外,syslog-ident还可以指定syslog里的日志标志,比如:

syslog-ident Redis

而且还支持指定syslog设备,值可以是USER或LOCAL0-LOCAL7。具体可以参考syslog服务本身的用法。

syslog-facility local0

对于Redis来说,可以设置其数据库的总数量,假如希望一个Redis包含16个数据库,那么设置如下:

databases 16

这16个数据库的编号将是0到15。默认的数据库是编号为0的数据库。用户可以使用select <DBid>来选择相应的数据库。

7.2快照配置

快照,主要涉及的是Redis的RDB持久化相关的配置。

可以用如下的指令来让数据保存到磁盘上,即控制RDB快照功能:

save <seconds> <changes>

举例来说:

save 9001 //表示每15分钟且至少有1个key改变,就触发一次持久化

save 30010 //表示每5分钟且至少有10个key改变,就触发一次持久化

save 6010000 //表示每60秒至少有10000个key改变,就触发一次持久化

如果想禁用RDB持久化的策略,只要不设置任何save指令就可以,或者给save传入一个空字符串参数也可以达到相同效果,就像这样:

save""

如果用户开启了RDB快照功能,那么在Redis持久化数据到磁盘时如果出现失败,默认情况下,Redis会停止接受所有的写请求。这样做的好处在于可以让用户很明确的知道内存中的数据和磁盘上的数据已经存在不一致了。如果Redis不顾这种不一致,一意孤行的继续接收写请求,就可能会引起一些灾难性的后果。

如果下一次RDB持久化成功,Redis会自动恢复接受写请求。

当然,如果不在乎这种数据不一致或者有其他的手段发现和控制这种不一致的话完全可以关闭这个功能,以便在快照写入失败时,也能确保Redis继续接受新的写请求。配置项如下:

stop-writes-on-bgsave-error yes

对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,Redis会采用LZF算法进行压缩。如果不想消耗CPU来进行压缩的话,可以设置为关闭此功能,但是存储在磁盘上的快照会比较大。

rdbcompression yes

在存储快照后,我们还可以让Redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。

rdbchecksum yes

我们还可以设置快照文件的名称,默认是这样配置的:

dbfilename dump.rdb

还可以设置这个快照文件存放的路径。比如默认设置就是:

dir ./db/


7.3主从配置

Redis提供了主从同步功能。

通过slaveof配置项可以控制某一个Redis作为另一个Redis的从服务器,通过指定IP和端口来定位到主Redis的位置。一般情况下建议用户为从Redis设置一个不同频率的快照持久化的周期,或者为从Redis配置一个不同的服务端口等等。

slaveof <masterip> <masterport>

如果主Redis设置了验证密码的话(使用requirepass来设置),则在从Redis的配置中要使用masterauth来设置校验密码,否则的话,主Redis会拒绝从Redis的访问请求。

masterauth <master-password>

当从Redis失去了与主Redis的连接,或者主从同步正在进行中时,Redis该如何处理外部发来的访问请求呢?这里,从Redis可以有两种选择:

第一种选择:如果slave-serve-stale-data设置为yes(默认),则从Redis仍会继续响应客户端的读写请求。

第二种选择:如果slave-serve-stale-data设置为no,则从Redis会对客户端的请求返回“SYNC with master inprogress”,当然也有例外,当客户端发来INFO请求和SLAVEOF请求,从Redis还是会进行处理。

可以控制一个从Redis是否可以接受写请求。将数据直接写入从Redis,一般只适用于那些生命周期非常短的数据,因为在主从同步时,这些临时数据就会被清理掉。自从Redis2.6版本之后,默认从Redis为只读。

slave-read-only yes

只读的从Redis并不适合直接暴露给不可信的客户端。为了尽量降低风险,可以使用rename-command指令来将一些可能有破坏力的命令重命名,避免外部直接调用。比如:

rename-command CONFIG b8c02d524045429941cc15f59e41cb7be6c52

从Redis会周期性的向主Redis发出PING包。可以通过repl_ping_slave_period指令来控制其周期。默认是10秒。

repl-ping-slave-period 10

在主从同步时,可能在这些情况下会有超时发生:

(1)以从Redis的角度来看,当有大规模IO传输时。

(2)以从Redis的角度来看,当数据传输或PING时,主Redis超时

(3)以主Redis的角度来看,在回复从Redis的PING时,从Redis超时

用户可以设置上述超时的时限,不过要确保这个时限比repl-ping-slave-period的值要大,否则每次主Redis都会认为从Redis超时。

repl-timeout 60

我们可以控制在主从同步时是否禁用TCP_NODELAY。如果开启TCP_NODELAY,那么主Redis会使用更少的TCP包和更少的带宽来向从Redis传输数据。但是这可能会增加一些同步的延迟,大概会达到40毫秒左右。如果关闭了TCP_NODELAY,那么数据同步的延迟时间会降低,但是会消耗更多的带宽。

repl-disable-tcp-nodelay no

我们还可以设置同步队列长度。队列长度(backlog)是主Redis中的一个缓冲区,在与从Redis断开连接期间,主Redis会用这个缓冲区来缓存应该发给从Redis的数据。这样的话,当从Redis重新连接上之后,就不必重新全量同步数据,只需要同步这部分增量数据即可。

repl-backlog-size 1mb

如果主Redis等了一段时间之后,还是无法连接到从Redis,那么缓冲队列中的数据将被清理掉。我们可以设置主Redis要等待的时间长度。如果设置为0,则表示永远不清理。默认是1个小时。

repl-backlog-ttl 3600

我们可以给众多的从Redis设置优先级,在主Redis持续工作不正常的情况,优先级高的从Redis将会升级为主Redis。而编号越小,优先级越高。比如一个主Redis有三个从Redis,优先级编号分别为10、100、25,那么编号为10的从Redis将会被首先选中升级为主Redis。当优先级被设置为0时,这个从Redis将永远也不会被选中。默认的优先级为100。

slave-priority 100

假如主Redis发现有超过M个从Redis的连接延时大于N秒,那么主Redis就停止接受外来的写请求。这是因为从Redis一般会每秒钟都向主Redis发出PING,而主Redis会记录每一个从Redis最近一次发来PING的时间点,所以主Redis能够了解每一个从Redis的运行情况。

min-slaves-to-write 3

min-slaves-max-lag 10

上面这个例子表示,假如有大于等于3个从Redis的连接延迟大于10秒,那么主Redis就不再接受外部的写请求。上述两个配置中有一个被置为0,则这个特性将被关闭。默认情况下min-slaves-to-write为0,而min-slaves-max-lag为10。

7.4 安全配置

我们可以要求Redis客户端在向Redis-server发送请求之前,先进行密码验证。由于Redis性能非常高,每秒钟可以完成多达15万次的密码尝试,所以最好设置一个足够复杂的密码,否则很容易被黑客破解。

requirepass chenlongfei

这里通过requirepass将密码设置成我的名字。

Redis允许我们对Redis指令进行更名,比如将一些比较危险的命令改个名字,避免被误执行。比如可以把CONFIG命令改成一个很复杂的名字,这样可以避免外部的调用,同时还可以满足内部调用的需要:

rename-command CONFIG b840fc02d5240454299c15f59e41cb7be6c89

我们甚至可以禁用掉CONFIG命令,那就是把CONFIG的名字改成一个空字符串:

rename-command CONFIG ""

但需要注意的是,如果使用AOF方式进行数据持久化,或者需要与从Redis进行通信,那么更改指令的名字可能会引起一些问题。

7.5 限制配置

我们可以设置Redis同时可以与多少个客户端进行连接。默认情况下为10000个客户端。当无法设置进程文件句柄限制时,Redis会设置为当前的文件句柄限制值减去32,因为Redis会为自身内部处理逻辑留一些句柄出来。

如果达到了此限制,Redis则会拒绝新的连接请求,并且向这些连接请求方发出“max number of clients reached”以作回应。

maxclients 10000

我们甚至可以设置Redis可以使用的内存量。一旦到达内存使用上限,Redis将会试图移除内部数据,移除规则可以通过maxmemory-policy来指定。

如果Redis无法根据移除规则来移除内存中的数据,或者我们设置了“不允许移除”,那么Redis则会针对那些需要申请内存的指令返回错误信息,比如SET、LPUSH等。但是对于无内存申请的指令,仍然会正常响应,比如GET等。

maxmemory <bytes>

需要注意的一点是,如果Redis是主Redis(说明Redis有从Redis),那么在设置内存使用上限时,需要在系统中留出一些内存空间给同步队列缓存,只有在设置的是“不移除”的情况下,才不用考虑这个因素。

对于内存移除规则来说,Redis提供了多达6种的移除规则。他们是:

(1)volatile-lru:使用LRU算法移除过期集合中的key

(2)allkeys-lru:使用LRU算法移除key

(3)volatile-random:在过期集合中移除随机的key

(4)allkeys-random:移除随机的key

(5)volatile-ttl:移除那些TTL值最小的key,即那些最近才过期的key。

(6)noeviction:不进行移除。针对写操作,只是返回错误信息。

无论使用上述哪一种移除规则,如果没有合适的key可以移除的话,Redis都会针对写请求返回错误信息。

maxmemory-policy volatile-lru

LRU算法和最小TTL算法都并非是精确的算法,而是估算值。所以可以设置样本的大小。假如Redis默认会检查三个key并选择其中LRU的那个,那么可以改变这个key样本的数量。

maxmemory-samples 3


7.6 AOF配置

默认情况下,Redis会异步的将数据持久化到磁盘。这种模式在大部分应用程序中已被验证是很有效的,但是在一些问题发生时,比如断电,则这种机制可能会导致数分钟的写请求丢失。

如上半部分中介绍的,AOF是一种更好的保持数据一致性的方式。即使当服务器断电时,也仅会有1秒钟的写请求丢失,当Redis进程出现问题且操作系统运行正常时,甚至只会丢失一条写请求。

官方建议,AOF机制和RDB机制可以同时使用,不会有任何冲突。

appendonly yes

我们还可以设置AOF文件的名称:

appendfilename "appendonly.aof"

fsync()调用,用来告诉操作系统立即将缓存的指令写入磁盘。一些操作系统会“立即”进行,而另外一些操作系统则会“尽快”进行。

Redis支持三种不同的模式:

(1)no:不调用fsync()。而是让操作系统自行决定sync的时间。这种模式下,Redis的性能会最快。

(2)always:在每次写请求后都调用fsync()。这种模式下,Redis会相对较慢,但数据最安全。

(3)everysec:每秒钟调用一次fsync()。这是性能和安全的折衷。

默认情况下为everysec。

appendfsync everysec

当fsync方式设置为always或everysec时,如果后台持久化进程需要执行一个很大的磁盘IO操作,那么Redis可能会在fsync()调用时卡住。目前尚未修复这个问题,这是因为即使我们在另一个新的线程中去执行fsync(),也会阻塞住同步写调用。

为了缓解这个问题,我们可以使用下面的配置项,这样的话,当BGSAVE或BGWRITEAOF运行时,fsync()在主进程中的调用会被阻止。这意味着当另一路进程正在对AOF文件进行重构时,Redis的持久化功能就失效了,就好像我们设置了“appendsync none”一样。如果Redis有时延问题,那么可以将下面的选项设置为yes。否则请保持no,因为这是保证数据完整性的最安全的选择。

no-appendfsync-on-rewrite no

我们允许Redis自动重写aof。当aof增长到一定规模时,Redis会隐式调用BGREWRITEAOF来重写log文件,以缩减文件体积。

Redis是这样工作的:Redis会记录上次重写时的aof大小。假如Redis自启动至今还没有进行过重写,那么启动时aof文件的大小会被作为基准值。这个基准值会和当前的aof大小进行比较。如果当前aof大小超出所设置的增长比例,则会触发重写。另外还需要设置一个最小大小,是为了防止在aof很小时就触发重写。

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

如果设置auto-aof-rewrite-percentage为0,则会关闭此重写功能。

指Redis在恢复时,会忽略最后一条可能存在问题的指令,默认值yes。即在aof写入时,可能存在指令写错的问题(突然断电,写了一半),这种情况下,yes会log并继续,而no会直接恢复失败。

aof-load-truncated yes


7.7 LUA脚本配置

lua脚本的最大运行时间是需要被严格限制的,单位是毫秒:

lua-time-limit 5000

如果此值设置为0或负数,则既不会有报错也不会有时间限制。

7.8 集群设置

平常的Redis实例不能作为集群的节点,只有作为集群节点启动的实例才可以。下面的配置可以是Redis实例作为集群节点启动:

cluster-enabled yes

每个集群节点都有一个集群配置文件,该文件是由集群节点来创建和维护的,不能人工参与。每个集群节点需要不同的配置文件,所以需要保证同一个系统下的集群节点没有重名的配置文件,建议以端口号标记配置文件。

cluster-config-file nodes-6379.conf

当节点超时大于cluster-node-timeout的时候后,就会被认为宕机了,单位为毫秒。

cluster-node-timeout 15000

Redis集群有一种failover(故障转移)机制,即当主Redis宕机之后,会有一个最合适的从Redis充当主Redis。但是,当从Redis的数据“太老”了,与住Redis的标准数据偏差很大,为了保证数据一致性,Redis会放弃failover。判别从Redis的的数据是不是“太老”有两种方法:

(1)如果有多个从Redis可以接替主Redis的工作,则它们会交换信息,选取“最佳复制偏移”(接受了原主Redis最多的数据同步)的从Redis作为下一任主Redis。

(2)每个从Redis计算与原主Redis最后一次数据同步的时间,当最短的时间间隔大于某个临界点的时候,集群则放弃failover。

方法(2)当中的临界点可以通过配置调节,临界点的计算规则为:

(node-timeout * slave-validity-factor)+ repl-ping-slave-period

如node-timeout为30秒,slave-validity-factor为10秒,repl-ping-slave-period为10秒,当与原主Redis最后一次对话的时间间隔超过310秒的时候,集群就会放弃failover。

当slave-validity-factor太大会使一台数据“太老”的从Redis充当主Redis;而slave-validity-factor太小可能会造成找不到合适的从Redis继任。

默认的slave-validity-factor为10。

cluster-slave-validity-factor 10

考虑一种极端情况,集群有一台主Redis和四台从Redis,从Redis全部挂掉,failover机制有可能造成集群只有主Redis而无从Redis的尴尬境况。为了保证集群的名副其实,可以规定,当从Redis少于某个数量时,拒绝执行failover。

cluster-migration-barrier 1

默认情况下,当集群检测到某个哈希槽(hash slot)没有被覆盖(没有任何节点为此服务)会停止接受查询服务,如果集群部分宕机最终会导致整个集群不可用,当哈希槽重新被全覆盖的时候会自动变为可用。如果希望那些哈希槽被覆盖的集群节点继续接受查询服务,需要将cluster-require-full-coverage设置为no。

cluster-require-full-coverage yes


7.9 慢日志配置

Redis慢日志是指一个系统进行日志查询超过了指定的时长。这个时长不包括IO操作,比如与客户端的交互、发送响应内容等,而仅包括实际执行查询命令的时间。

针对慢日志可以设置两个参数,一个是执行时长,单位是微秒,另一个是慢日志的长度。当一个新的命令被写入日志时,最老的一条会从命令日志队列中被移除。单位是微秒,即1000000表示一秒。负数则会禁用慢日志功能,而0则表示强制记录每一个命令。

slowlog-log-slower-than 10000

慢日志最大长度,可以随便填写数值,没有上限,但要注意它会消耗内存。可以使用SLOWLOG RESET来重设这个值。

slowlog-max-len 128


7.10 延迟监控配置

Redis的延迟监控子系统会在运行时对不同操作取样,以此来收集与延迟相关的数据,这些信息可以通过LATENCY命令以报表的形式呈现给用户。

系统只会记录那些执行时间等于或大于atency-monitor-threshold的操作,该值默认为0,代表关闭监控,因为收集延迟数据多少会影响Redis的性能。

latency-monitor-threshold 0


7.11事件通知配置

Redis可以向客户端通知某些事件的发生。

例如,键空间(keyspace)时间通知如果开启,一个客户端对Database 0中的“foo”键执行了DEL操作,两条信息会通过Pub/Sub发布出去:

PUBLISH__keyspace@0__:foo del

PUBLISH__keyevent@0__:del foo

可以选择需要发送哪种类型的通知,每种类型用一个字母代表:

K     键空间事件,发布到“__keyspace@<db>__ prefix”频道

E     键事件, 发布到“ __keyevent@<db>__ prefix”频道

g     通用事件,比如 DEL,EXPIRE, RENAME, ...等操作都属于

$     String操作

l     List操作

s     Set操作

h     Hash操作

z     Sorted set操作

x     过期操作

e    驱逐操作(因为内存不足数据被删除)

A    代表“g$lshzxe”的组合, 所以“AKE”可以代表所有事件

notify-keyspace-events配置以上述的字母组合为参数,举例说明:

(1)notify-keyspace-events Elg

当有List操作或通用操作,发布通知到“ __keyevent@<db>__ prefix”频道

(2)notify-keyspace-events Ex

当有键的过期操作时,发布通知到“__keyevent@0__:expired”频道

默认情况下,notify-keyspace-events的参数为空字符串,代表关闭通知。

notify-keyspace-events ""


7.12 高级配置

Hash在条目数量较小的时候会使用一种高效的内存数据结构编码,当超过某个临界点就会采用另一种存储方式,该临界点由下面的两个配置决定:

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

与Hash类似,较小的List会以一种特殊的编码方式来节省空间,只要List不超过下面的上限:

list-max-ziplist-entries 512

list-max-ziplist-value 64

Set只有在满足下面的条件时才会采用特殊编码方式:Set中存储的恰好都是十进制的整数,而且长度不超过64位(有符号)。数量上限为:

set-max-intset-entries 512

同样,有序集合也会采用特殊编码来节省空间,只要不超过上限:

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

RedisHyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定并且很小的。当HyperLogLog用稀疏式表示法时所用内存超过下面的限制,就会转换成稠密式表示,为了更高的内存利用率,官方建议值为3000。

hll-sparse-max-bytes 3000

Redis 在每 100 毫秒时使用 1 毫秒的 CPU时间来对 Redis 的 hash 表进行重新 hash 。当使用场景中有非常严格的实时性需要,不能够接受 Redis 时不时的对请求有 2 毫秒的延迟的话,把这项配置为 no 。

如果没有这么严格的实时性要求,可以设置为 yes ,以便能够尽可能快的释放内存。

activerehashing yes

客户端的输出缓冲区的限制,因为某种原因客户端从服务器读取数据的速度不够快,可用于强制断开连接(一个常见的原因是一个发布 / 订阅客户端消费消息的速度无法赶上生产它们的速度)。

可以三种不同客户端的方式进行设置:

(1)normal -> 正常客户端

(2)slave -> slave 和 MONITOR 客户端

(3)pubsub -> 至少订阅了一个 pubsub channel 或 pattern 的客户端

每个client-output-buffer-limit 语法 :

client-output-buffer-limit<class> <hard limit> <soft limit> <soft seconds> 一旦达到硬限制客户端会立即断开,或者达到软限制并保持达成的指定秒数(连续)。

例如,如果硬限制为 32 兆字节和软限制为 16 兆字节 /10 秒,如果输出缓冲区的大小达到 32 兆字节,客户端将会立即断开,客户端达到 16 兆字节和连续超过了限制 10 秒,也将断开连接。

默认 normal 客户端不做限制,因为他们在一个请求后未要求时(以推的方式)不接收数据,只有异步客户端可能会出现请求数据的速度比它可以读取的速度快的场景。

把硬限制和软限制都设置为 0 来禁用该特性

client-output-buffer-limit normal 0 0 0

client-output-buffer-limit slave 256mb 64mb 60

client-output-buffer-limit pubsub 32mb 8mb 60

Redis会按照一定的频率来执行后台任务,比如关闭超时的客户端,清楚过期键等。不是所有的任务都会按照相同的频率来执行,但Redis 依照指定的“ Hz ”值来执行检查任务。

hz 10

aof rewrite过程中,是否采取增量文件同步策略,默认为“yes”。 rewrite过程中,每32M数据进行一次文件同步,这样可以减少aof大文件写入对磁盘的操作次数。

aof-rewrite-incremental-fsync yes