前言
最近,我们在对接口进行压测优化,发现有些接口的TPS太不正常了,这里面多数接口都是直接从redis里面取数据的,针对反常的压测结果,我们决定从接口和redis集群两方面进行优化。针对于redis集群优化方面,主要是根据当前业务情况,适当调整一些配置参数,如果有必要的话,还需要进行集群扩容等。其中,关于配置文件,我在网上搜索了很多答案,有csdn、博客园等很多文章,发现都大同小异~也就阿里云的redis配置手册要专业很多。因此,想借助本次机会,自己把redis的配置文件好好的梳理解读一遍,一方面是加深自己的理解,另一方面是将汇成本篇1万2千多字纯手打的记录总结,供大家参考讨论。如有不对之处,请不吝赐教!
Redis的配置文件
在redis中,配置文件主要有普通配置文件、sentinel配置文件和cluster-node配置文件。我们重点关注普通配置文件。
普通配置文件
配置模块 | 说明 |
---|---|
INCLUDES | 主要用于引入额外的配置文件 |
NETWORK | 网络连接相关的配置模块 |
GENERAL | 通用的配置模块 |
SNAPSHOTTING | rdb持久化配置模块 |
REPLICATION | 主从配置模块 |
SECURITY | 安全配置模块 |
LIMITS | 内存限制等配置模块 |
APPEND ONLY MODE | aof持久化配置模块 |
LUA SCRIPTING | lua脚本配置模块 |
REDIS CLUSTER | cluster集群模式配置模块 |
SLOW LOG | 慢日志配置模块 |
LATENCY MONITOR | 延迟监控配置模块 |
ADVANCED CONFIG | 高级配置模块 |
INCLUDES
配置名称:include
作用:引入额外的配置文件。
使用示例:include \etc\redis\conf\shared.conf
说明:如果在一台服务器上有多台redis实例,则可以将一些公共的配置抽取出来,在具体的redis实例的配置文件是使用include引入即可让这些配置生效。
注意:redis支持配置更新,比如在client端通过CONFIG REWRITE或者sentinel模式下来修改配置。但是无论用哪一种方式都无法对include配置进行覆盖。比如在client端执行:config rewrite include .\new_shared.conf,server端会抛出异常提示。
NETWORK
配置名称:bind
作用:绑定指定IP来访问redis server。默认值:bind 127.0.0.1
说明:通过bind配置,能够确保redis server在没有任何保护措施的情况下,避免外网的恶意连接。
配置名称:protected-mode
作用:保护模式是redis的一个安全策略。默认为yes,即开启保护模式。
说明:在开启的情况下,对于内网而言,此配置没有任何影响。对于外网而言,如果外网想要连接redis server,则必须通过bind 绑定该外网ip或者通过访问密码才能连接。
配置名称:port
作用:redis server的监听端口,默认为6379
说明:如果port设置为0,则redis server将不会监听任何字端口。
配置名称:tcp-backlog
作用:设置TCP的已连接队列大小,默认为511.
说明:Linux内核为每个TCP服务程序维护了两条backlog,1条是TCP层的未连接队列,1条是应用层的已连接队列。分别对应net.ipv4.tcp_max_syn_backlog和net.core.somaxconn两个内核参数。
1个客户端连接在完成TCP 3次握手之前首先会进入到未连接队列,完成握手正式建立连接之后会进入到已连接队列,交付给应用程序处理。应用程序调用accept()函数从已连接队列中获取连接进行处理。应用层在调用listen()函数时指定的backlog参数就是已连接队列的大小。如果大于somaxconn,则取somaxconn的值。
已连接队列满了的话,会导致未连接队列中的连接经过3次握手之后无法进入到已连接队列,如果情况不容乐观的话,最终也会导致未连接队列堆满。对于客户端而言,客户端连接将会一直处于SYNC_SENT状态,最终导致连接超时。
对于redis而言,如果在超高并发或者长阻塞连接较多的场景下,很可能会因为已连接队列满导致connection timeout,遇到这种情况,可以适当调大该值。
配置名称:timeout
作用:客户端空闲N秒后连接将变成空闲连接,0表示禁用此配置。
说明:timeout仅是server端判断客户端是否变成空闲连接,而不是直接断开该连接。我们可以通过 client list来查看server端的连接信息,其中的idle值就表示空闲时长。
配置名称:tcp-keepalive
作用:server端每N秒判断连接列表中是否存在空闲连接,如果存在,则server端主动关闭这个连接。可以看到,该配置和timeout配置是有一定的依赖关系。默认为0,即不判断,redis官方建议设置为60s。
说明:当server端主动断开连接之后,客户端会收到该通知。此时,客户端会依据自己的连接池策略来做出相应的处理。以spring-redis为例,当监听到连接断开事件时,触发策略。我们假设min-idel-conn=1,如果server端将所有空闲连接都断开了,而client端又要求必须最少有一个空闲连接,那么此时client端就会重新创建一个新的连接。
在实际项目中,至少要保证server端和client端有一方设置里连接管理策略,通常我们更倾向于将在client端设置。如果两端都没有配置的话,那么通过连接激增之后,server端会拥有大量的连接,这里面有很多连接实际上已经无用了,如果不及时清除,会导致客户端无法创建新的连接从而导致客户端连接异常。
GENERAL
配置名称:loglevel
作用:配置redis server端的日志级别。有debug/verbose/notice/warning四个级别。默认为notice
说明:如果想要获取更详细的信息,可以将其设置为debug或者verbose。但是在生产环境中,选择默认级别或者warning即可。
配置名称:logfile
作用:redis server的日志文件,如果没有配置的话,则是控制台输出。默认没有配置。
配置名称:syslog-enabled 作用:是否将日志记录到系统日志中,如需要,则设置为yes,默认为no 说明:无论是记录到logfile还是syslog中,都受到loglevel的控制。
配置名称:syslog-ident
作用:设置redis在syslog中的identity,默认值为redis。
配置名称:databases
作用:redis中数据库的数量,默认为16. db0~db15。
说明:注意,redis默认使用db0数据库,如果要切换数据库,则可以使用select [db_number]进行切换。另外,只有在单机版中才能切换数据库,如果在集群模式下,则只能使用db0.
SNAPSHOTTING [快照]
SNAPSHOTTING模块的配置主要针对redis rdb持久化方式的设置。
配置名称:save
作用:save [seconds] [changes],即配置rdb生成快照的条件。比如:【save 1 10】则为,在1s以内,如果更新操作超过了10次,则触发生成rdb快照文件。
说明:save可以配置多个,每个配置都会生效。如果想关闭rdb快照功能,则配置为【save ""】 即可。
配置名称:stop-writes-on-bgsave-error
作用:当bgsave执行失败时,是否禁止增删改操作,默认为yes。
说明:redis通过bgsave来fork一个子进程生成快照,这样可以不阻塞主线程,主线程依然可以接收增删改查等命令。当bgsave失败时,将依据此配置来决定主线程是否能继续接收增删改命令。通常bgsave失败的情况有:文件没有读写权限、内存空间不够(rdb持久化时,内存消耗几乎翻倍)。
配置名称:rdbcompression
作用:是否启动rdb文件压缩,默认值是yes。
说明:启动压缩会节省空间,但是在生成快照期间会消耗更多的CPU。
配置名称:dbfilename
作用:rdb持久化存储的文件名。默认为dump.rdb
配置名称:dir
作用:工作目录,默认为redis的安装目录。
说明:当配置了dir之后,如果其他和路径相关的配置不是绝对路径的话,则默认路径为dir,比如dbfilename配置为dump.rdb,则绝对路径就为dir/dump.rdb
REPLICATION
REPLICATION模块是集群模式下,master-slave主从复制相关的配置。
配置名称:slaveof
作用:slaveof [master_ip] [master_port]。 即当前节点复制master_ip:master:port所在的节点,理所当然地当前节点就作为从节点。
配置名称:masterauth
作用:配置master节点的server密码,即在master配置文件中的requirepass配置。
说明:如果master配置了auth,则从节点必须配置masterauth,否则master将拒绝slave服务器的请求。
配置名称:slave-serve-stale-data
作用:当slave失去了与master的连接或者slave正在同步数据时,slave将根据此配置决定如何回应client端。如果是【yes】,则slave仍然可以正常响应client的请求,但此时client端获取的数据有可能是脏数据(毕竟断开了连接无法同步数据或者同步数据未完成)。如果是【no】则slave会回复一个异常信息给客户端。默认配置为【no】
配置名称:slave-read-only
作用:slave服务器是否只读。如果为yes,则只读,如果为no,则接受写命令。默认值为yes。
说明:在master-slave模式下,建议开启此配置,以尽可能保障数据一致性。
配置名称:repl-diskless-sync
作用:master和slave同步数据是否借助磁盘。如果为yes则借助磁盘,如果为no,则直接通过socket传输。默认值为no。
说明:如果借助磁盘,master会将rdb文件先写到磁盘,再传给slave;如果不借助磁盘,则master会直接在内存中生成rdb文件然后通过socket传输给slave,这种方式适用于磁盘读写速度慢且网络带宽高的情况。目前,diskless-sync尚处于试验阶段,因此默认值为yes。
配置名称:repl-diskless-sync-delay
作用:如果开启了diskless-sync配置的话,那么master在同步之前先等待延迟指定时间,默认为5s
说明:这一点很有用。因为master一旦启动了socket传输,将不能再为这之后而来的slave传输数据,必须等到下一次了。如果开启等待延迟的话,那么master会延迟N秒,目的是尽可能的汇集更多的slave同步请求
配置名称:repl-ping-slave-period
作用:slave给master发送ping的时间间隔,默认为 10s
说明:可以理解为alave和master之间的心跳检测间隔时长。
配置名称:repl-timeout
作用:slave与master之间的超时时间。 默认为60s
说明:slave会每隔repl-ping-slave-period配置的时间ping一次master,如果连续在repl-timeout时间内都没有ping通master,slave将认为master挂了。repl-timeout的值建议要设置的比repl-ping-slave-period值大,否则只要有1次没有ping通就认为master挂了。
配置名称:repl-disable-tcp-nodelay
作用:在slave与master同步(sync/psync)之后,后续的同步是否开启tcp-nodelay? 默认值为 no
说明:如果开启,则master会合并小的tcp包从而节省宽带,但是会增加同步延迟。对于redis而言,内存和宽带是最主要的资源。所以如果宽带确实吃紧并能够接受一定的同步延迟,则可以开启此配置。
配置名称:repl-backlog-size
作用:积压缓冲区大小,默认为1mb
说明:当slave重连之后,为了保证数据一致性,需要重新复制master的rdb文件。redis采用积压缓冲区的方式在一定程度上避免全量复制rdb:在失联期间,master将失联时产生的增量数据写入到挤压缓冲区,待salve重连之后,只需要将挤压缓冲区的数据同步给salve即可。如果数据量超过了积压缓冲区,则还是需要全量复制。
配置名称:repl-backlog-ttl
作用:积压缓冲区有效时长,默认为3600s
说明:当salve与master断开连接之后,master会将增量数据写入到积压缓冲区,但是如果失联时间超过了repl-backlog-ttl的话,那么master会清除缓冲区的数据,如果salve在这之后重新连接上,则仍然需要全量复制。
配置名称:slave-priority
作用:slave的优先级,值越低,优先级越高。默认值为100
说明:在sentinel或者cluster模式下,如果master挂掉了,则需要在从节点中选举一个master出来。优先级高的将优先被选中。需要注意的是并不是优先级越高就越有可能被选中,具体能否选中还要看其他的一些条件,比如要看slave的数据是否最新等等。另外,slave-priority如果配置为0的话,则此slave将永远不会被选为master,这一点需要注意。
配置名称:min-slaves-to-write 和 min-slaves-max-lag
作用:对于master而言,如果slave数量小于min-slaves-to-write 或者 任意一个slave的延迟大于min-slaves-max-lag的话,master都将不接收写操作。二者分别的默认值为:3 和 10
说明:在实际项目中,如果在意高可用,则可以将min-slaves-to-write设置为0,min-slaves-max-lag尽量设置大,如果更追求一致性,则相反。
SECURITY
配置名称:requirepass
作用:redis server的密码,在连接时需要进行验证。
说明:通常情况下,bind、requirepass、protected-mode这三个配置虽然作用不同,但都对于rediser server的安全性很重要。
配置名称:rename-command
作用:对命令进行更名,比如 rename-command CONFIG "dfadfdasgdsfas"
说明:在生产环境中,将一些敏感的、危险的命令进行重新命名,以防止被误执行,同时一定程度上提升了rediser server的安全性。
LIMITS
配置名称:maxclients
作用:redis server能够接受的client连接数最大值,默认为10000
配置名称:persistence-available
作用:开启或者关闭持久化功能,默认[yes]即开启,如果要关闭持久化则配置成 [no]。
说明:如果存在slave,则就算关闭了持久化功能,依然会生成rdb文件并同步给salve。这一点要注意区别。
配置名称:maxmemory
作用:redis所管理的最大内存值。默认没有配置。
说明:如果配置了该值,那么当内存满了后,将根据对应的内存淘汰策略进行处理。
配置名称:maxmemory-policy
作用:内存淘汰策略,默认为noevication
说明:目前redis的内存淘汰策略有以下几种:
名称 | 解释 |
---|---|
noevication | 不接受任何写命令,能接受get等读命令以及del命令,该策略是默认策略 |
volatile-lru | 在设置了过期时间的key中,删除最近最少使用的key |
volatile-ttl | 在设置了过期时间的key中,删除最接近过期时间的key |
vaolatile-random | 在设置了过期时间的,随机删除key |
allkeys-lru | 在所有key中,删除最近最少使用的key |
allkeys-random | 在所有key中,随机删除key |
配置名称:maxmemory-samples
作用:当使用的淘汰策略是基于lru或者ttl时,redis将随机选出指定的key出来作为一组数据判断。默认值为5.
说明:基于lru或者ttl时,redis并不是在所有符合条件的key中的执行淘汰策略,而是随机选出一批数据出来基于lru或者ttl策略进行淘汰。redis之所以没有使用真正的lru或者ttl算法来执行,是为了节省内存使用,在效果上他们几乎是等价的。这个值配置的越大,那么内存淘汰的精度就越高,但是会更消耗内存和CPU,这个值配置的越小,那么速度就越快,相应的会牺牲一定的精度。
APPEND ONLY MODE
配置名称:appendonly
作用:是否开启aof持久化 默认为yes
说明:redis目前同时支持rdb和aof这两种持久化方式,并且这二者是可以并存的。当二者并存的时候,redis重启时会优先使用aof文件,因为一般情况下aof文件比rdb文件的数据更精准。并且在redis4.0之后,redis持久化策略支持aof和rdb混合模式。
配置名称:appendfilename
作用:aof文件名,默认为appendonly.aof
配置名称:appendfsync
作用:aof持久化策略。有三种模式可选。always:每执行一次写操作,redis就执行1次fsync;everysec:每秒执行一次;no:redis不主动执行,有系统本身决定。默认值为everysec
说明:always最安全,但开销最大;no开销最小,但最不安全。everysec是折中方案。
配置名称:no-appendfsync-on-rewrite
作用:bgrewriteaof和fsync同时执行时,appendfsync的策略是否相当于no?默认的配置为no,即appendfsync策略不变。
说明:之所以有这个配置,是因为bgrewriteaof 和fsync都要操作磁盘,但bgrewriteaof相比fsync而言,会更大量的进行磁盘IO,因此势必会阻塞主进程的fsync,从而阻塞整个主进程,这个时候no-appendfsync-on-rewrite配置就登场了。当该配置为yes时,就是说在进行bgrewriteaof时,fsync的策略临时为no,即临时由系统本身决定什么时候执行fsync。
配置名称:auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size
作用:redis会自动执行bgrewriteaof命令,但条件是必须同时满足上面两个条件:auto-aof-rewrite-percentage:当前aof文件大小超过刚启动时aof大小的百分比,默认值100%;auto-aof-rewrite-min-size:当前aof文件要大于该配置的值,该配置的值默认为64mb。
配置名称:aof-load-truncated
作用:redis加载aof文件报错时的策略。加载时发现aof文件尾部不正确时,如果为yes:会向客户端写入错误log,并继续执行;如果为no:停止加载。
LUA SCRIPTING
配置名称:lua-time-limit
作用:lua脚本执行时长配置。默认为5000ms。
说明:如果lua脚本执行的时间超过了此配置。那么lua脚本本身会继续执行,但是其他客户端在执行命令时,redis server会响应一个错误:“Busy Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.”。此时如果要停止lua脚本的话,可以使用script kill命令来关闭正在执行的lua脚本(注意,此命令会关闭所有正在执行的脚本),另外,如果脚本已经执行过写操作了,则会无视script kill命令,继续执行。如果非要关闭lua脚本,则只有关闭redis server了。可见,lua脚本要合理使用!
REDIS CLUSTER
配置名称:cluster-enabled
作用:开启cluster模式。默认为no
说明:一个普通的redis server无法成为cluster集群的一部分,如果要让一个节点成为cluster一部分的话,则需要开启此节点。
配置名称**:cluster-config-file**
作用:集群配置文件名称。默认为nodes-6379.conf
说明:集群中每个节点都有一个集群配置文件,这个文件不需要人为编辑,它有redis自己维护,我们只需要指定其配置文件名称即可。
配置名称:cluster-node-timeout
作用:在集群中,节点故障判断时长,默认为15000ms。
说明:如果node节点在指定时间内联系不上,则认为该节点故障。
配置名称:cluster-slave-validity-factor
作用:从节点有效因子。默认为10.
说明:redis集群在进行故障转移时,除了会衡量从节点的优先级(slave-priority配置)之外会衡量从节点的数据“老旧”程度,如果某个从节点的数据太老,则它也不会被升级为主节点。判断从节点的数据老旧程度从两方面来判断:1.判断增量数据的复制偏移量,根据增量数据偏移量得出从节点的数据新旧程度。2.判断最近连接时间,如果从节点和主节点的交互太旧,则该从节点也不会参与故障转移。第1点有redis集群决定,用户无法干预;第2点则可以根据配置来进行干预。
具体干预如下:如果从节点自上次交互以来的时间 > cluster-node-timeout * cluster-slave-validity-factor + repl-ping-slave-period.那么该从节点是不会参与故障转移(即不会被选举为master的)。
配置名称:cluster-migration-barrier
作用:集群分配从节点时的“移民障碍”, 默认为1,即要保证master至少有1个slave节点。
说明:在集群中,为了尽量让从节点分配均匀,采用了“移民障碍”的方式,即只要保证master有指定个数的从节点,在满足这个条件的前提下,如果master有多余的从节点,则可以根据需要被分配到其他master下。
配置名称:cluster-require-full-coverage
作用:是否需要覆盖全slot,集群才可用。默认为yes
说明:cluster集群中总共有16384个slot,如果该配置为yes,则分片要覆盖所有的slot,否则整个集群不可用。
SLOW LOG
配置名称:slowlog-log-slower-than
作用:命令执行时长阈值,如果超过该配置,则记录到慢日志。改配置的单位为微秒,默认值为10000微秒。
配置名称:slowlog-max-len
作用:慢日志记录条数,当超过该配置时,采用FIFO的方式移除旧记录。默认值为128
ADVANCED CONFIG
配置名称:hash-max-ziplist-entries 和 hash-max-ziplist-value 作用:针对hash底层数据结构的转换。满足任意条件时,hash底层的数据结构将由ziplist将转换为dict。hash-max-ziplist-entries:ziplist最大entry个数,默认为512;hash-max-ziplist-value:entry长度的阈值,默认为64.
配置名称:list-max-ziplist-size
作用:list数据结构中ziplist的分配。默认值为-2
说明:redis的list数据类型的底层结构是quicklist,quicklist实际上是一个双向链表 + ziplist,这是一种空间和时间上的折中方案。该参数表示一个quicklist节点包含的ziplist的个数或者大小。如果该配置 > 0,则表示一个quicklist包含的ziplist的个数;如果该值 < 0,则表示ziplist的大小,取值为-1~-5,分别对应2^2 ~ 2^6 byte。
配置名称:list-compress-depth
作用:list数据结构的压缩策略。默认为0,即不压缩。
说明:在列表很长的情况下且列表两端访问频率高,中间访问频率低的情况下,可根据实际情况配置,来压缩中间的数据以进一步节省空间。加入配置为2,则quicklist头尾各2个节点不压缩,中间的开始压缩。以此类推。
配置名称:set-max-intset-entries
作用:当set数据结构保存的都是整型数据时,redis会选择intset作为set的底层数据结构。当元素个数超过该配置的值时,将会有intset转换为dict。默认值为512
配置名称:zset-max-ziplist-entries 和 zset-max-ziplist-value
作用:针对sorted set底层数据结构的转换。满足任意条件时,sorted set底层数据结构将有ziplist转换为skiplist。zset-max-ziplist-entries:ziplist的entry数量阈值,默认为512;zset-max-ziplist-value:ziplist任一entry大小阈值,默认为64
配置名称:hll-sparse-max-bytes
作用:HyperLogLog的存储策略。如果hll的基数大于该配置,则采用稠密矩阵来存放(此时一个key占用12kb),否则采用稀疏矩阵存放(此时一个key比12kb小)。默认值为3000。
说明:如果我们更在意内存资源的话,则可以将该值适当设置大一点,官方建议10000;另外,如果超过了16000,则几乎没有任何效果。因此很少有基数达到16000时redis还依然能够采用稀疏矩阵存放。
配置名称:activerehashing
作用:redis自动渐进式rehash配置。默认为yes。
说明:如果开启该配置,则redis会每100ms使用1ms的时间对hash表进行rehash(渐进式)。由于redis的hash扩容机制对内存不是特别友好,因此需要时不时的rehash来降低内存的消耗。如果一次性rehash的话,延迟会比较明显,从而造成阻塞,特别是当map entry特别多时;因此redis采用“小步快跑”的方式完成rehash,这样的话,延迟就不会特别明显了(但仍然会有延迟的,只要有rehash就有延迟)。如果我们完全不接受任何延迟的话,则可以将该选项配置为no,但这样对于系统不太友好(尤其是内存),因此作者也建议保持默认配置。
配置名称:client-output-buffer-limit
作用:对于redis而言,可以基于客户端输出缓冲区限制来断开连接。client-output-buffer-limit [class] [hard limit] [soft limit] [soft seconds]
说明:这里的客户端有且只有3种。normal:普通客户端;slave:从节点;pubsub:发布订阅模式中的订阅者。硬限制:即只要客户端输出缓冲区超过该值,立马断开连接;软限制:如果在soft seconds时间内,持续超过soft limit,则立马断开连接。
配置名称:hz
作用:redis执行后台的任务(清除过期key,检查空闲连接等)的频率。默认为10hz,即执行频率 = 1s/10 = 100ms,意思就是没100ms就执行一次后台任务。
说明:改配置值越大,执行频率越高,redis的响应也就越快,但是会消耗更多资源。该值的有效值范围为1~500,但通常超过100就不是好主意了。作者建议采用默认值即可。
配置名称:aof-rewrite-incremental-fsync
作用:在aof文件重写的时候,如果该配置为yes,则系统会每32mb执行一次fsync。默认配置为yes
总结
这次配置文件总结梳理,让我对redis的使用心得和优化又有了新的认识,尤其是redis cluster这块。学无止境,继续加油!