1.redis开发运维中的陷阱
1.密码机制
redis的密码机制:
redis提供了 requirepass 配置为redis提供了密码功能,如果添加这个配置
客户端不能通过redis-cli -h {ip} -p {port} 直接登录。
redis提供了两种方式访问配置了密码的redis:
redis-cli -a ,写入密码,并且防止将密码写入命令行,而是写入提示符号中。
第二种方法是,先登录,然后使用 auth 命令认证。
redis-cli
127.0.0.1:6379>auth "mypasswd"
注意设置较为复杂的密码。同时从库加入配置 masterauth "mypasswd",主库的密码。
2.危险命令的使用
redis中的危险命令:
keys :如果键值较多,存在阻塞Redis的可能性。
flushall/flushdb:数据全部被清除。
save:如果键值较多,存在阻塞redis可能性。
debug:例如:debug reload 会重启redis
config:config应该交由管理员使用。
shutdown:停止redis;
3.linux 参数配置
vm.overcommit_memory=1
vm.overcommit_memory 三个可选的值及说明。
0:表示内核将检查是否有足够的可用内存。如果有足够的可用内存,内存申请通过,
否则内存申请失败,并把错误返回给应用程序。
1:表示内核允许超量使用内存直到用完为止。
2:表示内核决不过量使用内存,即系统整个内存地址空间不能超过swap+50%的RAM 值,
50%是 overcommit_ratio 默认值,此参数也支持修改。
修改
cat /proc/sys/vm/overcommit_memory
0
echo "vm.overcommit_memory=1" >>/etc/sysctl.conf
sysctl vm.overcommit_memory=1
Redis设置合理的maxmemory,保证机器有20%-30%的闲置内存。
设置 vm.overcommit_memory=1,防止极端情况下造成fork 失败。
swapiness:
swap空间由硬盘提供,对于需要高并发,高吞吐的应用来说,磁盘IO通常会成为
系统瓶颈,系统参数 swapiness 会决定操作系统使用swap 的倾向程度。
swapiness 取值范围 0-100,swapiness 值越大,说明操作系统可能使用
swap的概率越高,swapiness 值越大,表示操作系统更加倾向于使用物理内存。
swapiness 重要值策略说明
0 :Linux3.5 及以上:宁愿用OMM killer也不会使用swap
0 :Linux3.4 及更早:宁愿用swap 也不用 OOM killer
1 :Linux3.5 以及以上:宁愿用 swap也不用 OOM killer
60 :默认值
100 :操作系统主动使用swap
OOM(Out Of Memory) killer 机制是指Linux操作系统发现可用内存不足时,强制
杀死一些用户进程(非内核进程),来保证系统有足够的可用内存进行分配。
设置swapiness的方法
echo 1 > /proc/sys/vm/swapiness
立即生效:
echo vm.swapiness=1 >>/etc/sysctl.conf
sysctl -p
如果Linux>3.5 设置:vm.swapiness=1
如果Linux<3.5 设置:vm.swapiness=0
物理内存充足的时候,使redis足够快。
物理内存不足的时候,避免redis死掉。
THP:
linux kernel 在2.6.38 内核增加了THP特性,支持大内存页(2M)分配,默认开启。
当开启时可以加快fork子进程的速度,但fork操作之后,每个内存页从原来4KB
变为2MB,会大幅增加重写期间父进程内存消耗。同时每次写命令引起的复制内存页单位放大
了512倍,会拖慢操作的执行时间,导致大量写操作慢查询。
禁用方法:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
OOM Killer;
OOM Killer 进程会为每个用户进程设置一个权值,这个权值越高,被 "下手"
的概率越高,反之概率越低。
对于redis所在服务器来说,可以将所有redis的oom_adj 设置为最低值
或者稍小的值,降低被OOM Killer杀掉的概率。
for redis_pid in $(pgrep -f "redis-server")
do
echo -17 > /proc/${redis_pid}/oom_adj
done
NTP
机器需要通过NTP通过公司的时钟服务器的时间,或者自定义使用服务器。
让Redis集群节点的时钟保持一致。例如每小时同步一次公司的时钟服务器。
0 * * * * /usr/sbin/ntpdate ntp.xx.com >/dev/null 2>&1
ulimit:
在linux中,可以通过ulimit查看和设置系统当前用户进程的资源数。其中
ulimit -a 命令包含的 open files 参数,是单个用户同时打开的最大文件描述符个数。
redis 允许同时有多个客户端通过网络进行连接,可以通过配置 maxclients 来限制
最大客户端连接数。对linux操作系统来说,这些网络连接都是文件句柄。
maxclients+32 ,openfiles 两个的较小值决定单个用户打开最大文件描述符的最大值。
ulimit -a 查看 openfiles;
设置 openfiles;
ulimit -Sn 65536
TCP backlog;
设置 TCP backlog 与 redis的backlog 相同。
redis的默认的tcp-backlog值为511,可以通过修改配置 tcp-backlog进行调整,
如果linux的tcp-backlog小于redis设置的 tcp-backlog,redis会有警告。
linux默认的tcp-backlog是128,修改Linux的tcp-backlog;
echo 511 > /proc/sys/net/core/somaxconn
一、误操作flushallo/flushdb 如何进行恢复
1.恢复前提条件
(1)appendonly=yes 参数设置。
(2)或者有最近备份的RDB文件
2.紧急操作
(1)调大 AOF重写参数 auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size,
让 redis不能产生AOF自动重写。
(2)拒绝手动执行 bgrewriteoaf
--主从节点都修改。
config set auto-aof-rewrite-percentage=1000
config set auto-aof-rewrite-min-size=100000000000
3.恢复
如果 appendonly=no,则没有可供恢复的AOF文件。所以生产环境建议设置:appendonly=yes
如果 appendonly=yes,只不过是在AOF文件中追加了一条记录。
AOF文件中的flush操作记录如下:
*1
$8
flushall
由于AOF是可编辑文件,可以删除上面的三行,使用 redis-check-aof 这个工具验证和修复一下AOF文件。
确保AOF文件格式正确,保证数据恢复正常。
重启redis主节点服务器恢复数据。
注意:如果 AOF 文件被重写,redis遍历所有数据库生成新的AOF,则无法使用AOF恢复。之前的数据丢失。
如果:appendonly=no,则需要查看redis是否开启 RDB的自动策略。
如果配置文件中有:
save 900 1
save 300 10
save 60 10000
RDB文件会被清除,则无法恢复。
如果配置文件中没有上述配置,且未执行过 save,bgsave 等命令,RDB 文件可以用于恢复。
但是数据一致性不高。
4.自动化处理flushall/flushdb的情况。
前提开启:appendonly=yes
--主库。
redis-cli -h {host} -p {port} config set auto-aof-rewrite-percentage=1000
redis-cli -h {host} -p {port} config set auto-aof-rewrite-min-size=100000000000
--从库。
redis-cli -h {host} -p {port} config set auto-aof-rewrite-percentage=1000
redis-cli -h {host} -p {port} config set auto-aof-rewrite-min-size=100000000000
删除:AOF文件中如下三行:
*1
$8
flushall
--验证文件
redis-check-aof redis.aof
--重启redis;
一、误操作flushallo/flushdb 如何进行恢复
1.恢复前提条件
(1)appendonly=yes 参数设置。
(2)或者有最近备份的RDB文件
2.紧急操作
(1)调大 AOF重写参数 auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size,
让 redis不能产生AOF自动重写。
(2)拒绝手动执行 bgrewriteoaf
--主从节点都修改。
config set auto-aof-rewrite-percentage=1000
config set auto-aof-rewrite-min-size=100000000000
3.恢复
如果 appendonly=no,则没有可供恢复的AOF文件。所以生产环境建议设置:appendonly=yes
如果 appendonly=yes,只不过是在AOF文件中追加了一条记录。
AOF文件中的flush操作记录如下:
*1
$8
flushall
由于AOF是可编辑文件,可以删除上面的三行,使用 redis-check-aof 这个工具验证和修复一下AOF文件。
确保AOF文件格式正确,保证数据恢复正常。
重启redis主节点服务器恢复数据。
注意:如果 AOF 文件被重写,redis遍历所有数据库生成新的AOF,则无法使用AOF恢复。之前的数据丢失。
如果:appendonly=no,则需要查看redis是否开启 RDB的自动策略。
如果配置文件中有:
save 900 1
save 300 10
save 60 10000
RDB文件会被清除,则无法恢复。
如果配置文件中没有上述配置,且未执行过 save,bgsave 等命令,RDB 文件可以用于恢复。
但是数据一致性不高。
4.自动化处理flushall/flushdb的情况。
前提开启:appendonly=yes
--主库。
redis-cli -h {host} -p {port} config set auto-aof-rewrite-percentage=1000
redis-cli -h {host} -p {port} config set auto-aof-rewrite-min-size=100000000000
--从库。
redis-cli -h {host} -p {port} config set auto-aof-rewrite-percentage=1000
redis-cli -h {host} -p {port} config set auto-aof-rewrite-min-size=100000000000
删除:AOF文件中如下三行:
*1
$8
flushall
--验证文件
redis-check-aof redis.aof
--重启redis;
一、误操作flushallo/flushdb 如何进行恢复
1.恢复前提条件
(1)appendonly=yes 参数设置。
(2)或者有最近备份的RDB文件
2.紧急操作
(1)调大 AOF重写参数 auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size,
让 redis不能产生AOF自动重写。
(2)拒绝手动执行 bgrewriteoaf
--主从节点都修改。
config set auto-aof-rewrite-percentage=1000
config set auto-aof-rewrite-min-size=100000000000
3.恢复
如果 appendonly=no,则没有可供恢复的AOF文件。所以生产环境建议设置:appendonly=yes
如果 appendonly=yes,只不过是在AOF文件中追加了一条记录。
AOF文件中的flush操作记录如下:
*1
$8
flushall
由于AOF是可编辑文件,可以删除上面的三行,使用 redis-check-aof 这个工具验证和修复一下AOF文件。
确保AOF文件格式正确,保证数据恢复正常。
重启redis主节点服务器恢复数据。
注意:如果 AOF 文件被重写,redis遍历所有数据库生成新的AOF,则无法使用AOF恢复。之前的数据丢失。
如果:appendonly=no,则需要查看redis是否开启 RDB的自动策略。
如果配置文件中有:
save 900 1
save 300 10
save 60 10000
RDB文件会被清除,则无法恢复。
如果配置文件中没有上述配置,且未执行过 save,bgsave 等命令,RDB 文件可以用于恢复。
但是数据一致性不高。
4.自动化处理flushall/flushdb的情况。
前提开启:appendonly=yes
--主库。
redis-cli -h {host} -p {port} config set auto-aof-rewrite-percentage=1000
redis-cli -h {host} -p {port} config set auto-aof-rewrite-min-size=100000000000
--从库。
redis-cli -h {host} -p {port} config set auto-aof-rewrite-percentage=1000
redis-cli -h {host} -p {port} config set auto-aof-rewrite-min-size=100000000000
删除:AOF文件中如下三行:
*1
$8
flushall
--验证文件
redis-check-aof redis.aof
--重启redis;
Redis的安全。
2015年11月,全球数万个redis节点遭受了攻击,所有数据都被清除了,只有一个叫
crackit 的键存在。
被攻击的机器有如下特点:
redis所在的机器有外网IP;
redis以默认端口6379为启动端口,并且是对外网开放的。
redis是以root用户启动的。
redis没有设置密码。
redis的bind 设置为 0.0.0.0 或者 ""
--防火墙。
可以使用防火墙限制输入和输出的IP或者IP范围,端口或者端口范围,在比较成熟的公司
都会对外网IP的服务器做一些端口限制,例如只允许80端口对外开放。防火墙是限制
外网访问redis的必杀技。
bind:
bind 参数指定的是redis和哪个网卡进行绑定,和客户端是什么网段没有关系。
--定期备份
虽然redis有持久化机制,还是建议定期备份redis的RDB或者AOF文件。
--不适用默认端口。
redis的默认端口是6379,不使用默认端口从一定程度上可降低被入侵者发现的可能性。
MySQL的默认端口是3306,Memcache的默认端口是11211,Jetty的默认端口是8080,
这些默认端口都是容易被攻击的。所以需要设置非默认端口。
--非root用户启动。
建议使用非root用户启动。防止入侵者获取到root权限造成致命伤害。
Resin,Jetty,HBase,Hadoop都建议使用非root启动。
--处理bigkey
bigkey 是指key对应的value所占的内存空间比较大,例如一个字符串类型的value
最大可以存512M,一个列表类型最多可以存储2^32-1 个元素。
字符串类型:一般认为超过10Kb就是bigkey;
非字符串类型:哈希,列表,集合,有序集合,体现在元素个数过多。
bigkey造成的危害:
内存空间不均匀
超时阻塞。
网络拥堵。
bigkey 在高并发的场景下,会造成网络拥堵,应该尽可能减少bigkey的使用。
优化bigkey;
加入一个bigkey 1M,每秒访问1000次,那么每秒产生1000M的流量。
对于普通的千兆网卡的服务器就是灭顶之灾。
发现bigkey;
redis-cli --bigkeys
另外,判断一个key是否为bigkey,只需要执行debug object key 查看serializedlength
属性即可,它表示key对应的value序列化之后的字节数。
127.0.0.1:6379>debug object key
字符串可以使用:
127.0.0.1:6379>strlen key 查看字符串的大小。
--热点key;
热点key需要通过开发程序去记录。DBA无工具几乎无法捕获。
热门新闻事件或商品通常会给系统代理巨大的流量,对存储这类信息的redis来说
是一个巨大的挑战。以redis cluster为例,它会造成整体流量的不均衡,个别节点
出现OPS过大的情况,极端情况下热点key设置会超过redis本身能够承受的OPS;
寻找热点key可以使用monitor,但是此命令仅可以短时间使用,长时间使用造成系统阻塞。
处理热点key的三种方案:
1)拆分复杂数据结构:如果当前key的类型是一个二级数据结构,例如哈希类型。
如果该哈希元素个数较多,可以考虑将当前hash进行拆分,这样热点key可以
拆分为若干个新的key分布到不同redis节点上,从而减轻压力。
2)迁移热点key:以redis cluster为例,可以将热点key所在的slot单独迁移到
一个新的redis节点上,单词操作会增加运维成本。
3)本地缓存通知机制:可以将热点key放在业务端的本地缓存中,因为是在业务端
的本地内存中,处理能力要高出redis数十倍,但是当数据更新时,此种模式会
造成各个业务端和redis数据不一致,通常会使用发布订阅机制来解决类似的问题。