redis运维维护
【运维】
【0】操作系统优化
#【1】调整 vm.overcommit_memory #vi /etc/sysctl.conf echo "vm.overcommit_memory=1" >> /etc/sysctl.conf #改参数关注的是内存分配策略 #0,标识内核将检查是否有足够的可用内存供应用进程使用;如果有则申请允许,否则内存申请失败,并返回错误给应用进程。 #1,标识内核允许分配所有的物理内存,而不管当前的内存状态如何。 #2,标识内核允许分配超过所有物理内存和交换空间(swap)的内存 #【2】调整 Transparent Huge Pages(THP) #解决:redis 做 rdb 时会有部分请求超时的情况 echo never > /sys/kernel/mm/transparent_hugepage/enabled echo "never > /sys/kernel/mm/transparent_hugepage/enabled" >> /etc/rc.local #【3】TCP backlog设置(详情见后续redis配置参数) echo 2048 > /proc/sys/net/core/somaxconn echo "net.core.somaxconn=2048" >> /etc/sysctl.conf #动态加载 sysctl -p #此参数确定了TCP连接中已完成队列(完成三次握手之后)的长度 #此值必须不大于linux系统定义的 /proc/sys/net/core/somaxconn的值,默认511 #而 linux 默认参数值是128,当系统并发量大并且客户端缓慢时,可以将这2个参数一起参考设置。
【1】持久化
(1)主库开启持久化或主库不设置开启自启
当主库没有开启持久化时,注意不要设置开机自启。
因为主库如果宕机重启后数据为空,这个时候如果重启了,那么主库数据为空,从库会重新同步新的空白数据 导致从库被清空。
(2)stop-writes-on-bgsave-error 参数设置为 no
当RDB持久化出现错误后,是否依然进行继续进行工作。
yes:不能进行工作
no:可以继续进行工作
可以通过info中的rdb_last_bgsave_status了解RDB持久化是否有错误,如果设置成了YES则RDP文件如果持久化失败则整个实例宕机无法写入
(3)AOF参数:no-appendfsync-on-rewrite 参数设置为 no/yes
当执行bgrewriteaof 对aof文件重写时,不做预设的自动追加同步操作到aof文件上去。但默认会按30秒一次批量同步操作到aof文件中去。
该操作是为了避免大量磁盘操作导致系统卡顿
yes:当做 rewrite 操作时,不使用预设频率对新操作持久化同步到 aof 文件中去,而是用默认的30S同步一次; 该选项可能在极端情况下导致丢失30秒数据
no:当做 rewrite 操作时,继续维持原有的预设同步频率同步redis操作到 aof 文件中去。
建议HDD用 yes,SDD 用 no 。注意如果选 yes 该选项可能在极端情况下导致丢失30秒数据
【2】复制
(1)断开复制、重新连接其他主库(会清空之前数据)
切换主节点之后,从节点会清空之前的所有数据,线上操作的时候需要注意
(2)repl-backlog-size 5mb
复制积压缓冲区大小,为了避免网络闪断而缓冲区大小不够导致主从无法进行psync部分同步而重新进行全量复制同步,根据数据量来判断
复制积压缓冲区的最小大小可以根据公式 second*write_size_per_second 来估算:
- 其中second为从服务器断线后重新连接上主服务器所需的平均时间(以秒计算);
- 而 write_size_per_second 则是主服务器平均每秒产生的写命令数据量(协议格式的写命令的长度总和);
例如,如果主服务器平均每秒产生1 MB的写数据,而从服务器断线之后平均要3秒才能重新连接上主服务器,那么复制积压缓冲区的大小就不能低于3MB。
【常用命令】
【2.1】基本数据库信息命令
redis 127.0.0.1:6380> dbsize // 当前数据库的key的数量 redis 127.0.0.1:6380> select 2 //切换数据库 BGREWRITEAOF //后台进程重写AOF BGSAVE //后台保存rdb快照 SAVE //保存rdb快照,会阻塞,建议使用BGSAVE LASTSAVE //上次保存时间Slaveof master-Host port //把当前实例设为master的slave Flushall //清空所有库所有键 Flushdb //清空当前库所有键 Showdown [save/nosave] //关闭,然后持久化保存/不持久化保存 //注: 如果不小心运行了flushall, 立即 shutdown nosave ,关闭服务器 //然后 手工编辑aof文件, 去掉文件中的 "flushall" 相关行, 然后开启服务器,就可以导入回原来数据. //如果,flushall之后,系统恰好bgrewriteaof了,那么aof就清空了,数据丢失
config get * //获取所有配置参数值
config set item value //设置某个 item的值 为 value
config rewrite //把做了 config set 修改的参数配置值 写入到配置文件中去。
【2.2】监控相关信息
Info [Replication/CPU/Memory..]
查看redis服务器的信息
Config get 配置项
Config set 配置项 值 (特殊的选项,不允许用此命令设置,如slave-of, 需要用单独的slaveof命令来设置)
Redis运维时需要注意的参数
1: 内存 info Memory
used_memory:5297393328 //redis 数据结构的占用空间
used_memory_rss:6213394432 // 操作系统层面实占空间
mem_fragmentation_ratio:1.89 // used_memory_rss/used_memory 1.N 为佳
// 如果该值 > 1时,则说明 used_memory_rss - used_memory_rss 多出的内存部分并没用于存储数据,而是被内存随便所消耗,如果很大则碎片严重,建议重新导出导入
// 如果该值 < 1时,则说明 redis 使用的内存,比操作系统分配给它的还要多,那么多半是使用了 swap 交换内存。这种情况要格外注意
2: 主从复制 info replication
role:slave
master_host:192.168.1.128
master_port:6379
master_link_status:up
3:持久化 info Persistence
rdb_changes_since_last_save:0
rdb_last_save_time:1375224063
4: fork耗时 info Stats
latest_fork_usec:936 上次导出rdb快照,持久化花费微秒
注意: 如果某实例有10G内容,导出需要2分钟,
每分钟写入10000次,导致不断的rdb导出,磁盘始处于高IO状态.
5: 慢日志
config get/set slowlog-log-slower-than //配置慢查询阀值
CONFIG get/SET slowlog-max-len //配置慢日志最大记录数
slowlog get N //获取慢日志
slowlog len //获取慢日志记录条数
Slowlog 显示慢查询
注:多慢才叫慢?
答: 由slowlog-log-slower-than 10000 ,来指定,(单位是微秒)
服务器储存多少条慢查询的记录?
答: 由 slowlog-max-len 128 ,来做限制
【2.3】redis-cli 查看信息
1: --stat 输出当前 redis 服务节点状态
命令:redis-cli -h host -p port --stat
输出:
连续输出,默认interval 1s
键数 | 内存 | 客户端数 | 阻塞数 | 累积请求(增加请求) | 连接数
2: --bigkeys 扫描大key
命令:redis-cli -h host -p port --bigkeys
输出:
执行 scan 操作,单次100。不影响服务器实时性能。
3: --scan 查看key
结合linux命令 more 查看
命令:redis-cli -h host -p port --scan | more
匹配:--pattern '*hello*'
命令:redis-cli -h 10.10.52.100 -p 10119 --scan --pattern '*hello*'
输出:
统计:| wc -l
命令:redis-cli -h 10.10.52.100 -p 10119 --scan --pattern '*hello*' | wc -l
4: --latency 延迟统计
命令:redis-cli -h host -p port --latency
输出:
历史延迟统计:间隔15s输出统计结果
命令:redis-cli -h host -p port --latency-history
输出:
更直观的命令输出:--latency-dist,
命令:redis-cli -h host -p port --latency-dist
输出:
5: --rdb 备份镜像
命令:redis-cli -h host -p port --rdb
输出:
6: --lru-test 测试Redis的LRU实现的质量
模拟使用80-20%幂律分布来执行对GET和SET操作的模拟。
命令:redis-cli -h host -p port --lru-test 测试键数
输出:
7: -r 连续重复执行
命令:redis-cli -h host -p port -r 10 incr AB
输出:
【开发技巧】
使用 INCR,而不是 x=x+1
- 客户端A读取计数为10。
- 客户端B读取的计数为10。
- 客户A增加11,并将计数设置为11。
- 客户端B增加11,并将计数设置为11。
我们希望该值为12,但实际上为11!这是因为以这种方式增加值不是原子操作。在Redis中调用 INCR命令可以防止这种情况的发生,因为它是原子操作
由单个命令实现的所有Redis操作都是原子的,包括对更复杂的数据结构进行操作的操作。因此,当您使用修改某些值的Redis命令时,无需考虑并发访问。
使用setnx,而不是 set
- 原子性,可以用于实现分布式事务
- 更安全,不存在则创建
使用 mget/mset,而不是 get/set
同理,其他数据类型也一样。
1000次 get 和 1次 mget 对比表
操作 | 时间 |
---|---|
1000次get | 1000*1+1000*0.1=1100毫秒=1.1秒 |
1次mget(组装了100个键值对) | 1*1+1000*0.1=101毫秒=0.101秒 |
使用 scan/hscan 等系列,而不是 keys/getall/smembers/zrange
优势:
- scan 是渐进式遍历,不会一下子遍历所有key,它的时间复杂度是O(1)
- scan 因为是渐进式遍历不会阻塞,不会像keys那样在有大量key时比较容易造成阻塞
问题:
- scan 渐进式遍历可以有效解决keys 命令可能产生的阻塞问题,但是 scan也有自己的问题。
- 在scan的过程中如果有key有增删改变化,那么遍历的效果可能不尽人意
- 新增的键可能没有遍历到
- 遍历出现了重复的键
也就是说,scan 可能无法遍历检索出所有的key,这是我们需要考虑的。
【需要注意的点】
- persist 命令会删除任意类型键的过期时间
- set系列 命令也会删除字符串等类型的过期时间
【参考文件】
阿里云redis开发规范:https://developer.aliyun.com/article/531067