Redis的正确使用姿势
前言
说到分布式缓存,可能大多数人脑海浮现的就是redis了,为什么redis能够在竞争激烈的缓存大战中脱颖而出呢?原因无非有一下几点:性能好,丰富的特性跟数据结构,api操作简单。但是用的人多了,就会出现很多不规范或者疏忽的地方,严重的时候甚至会导致生产事故,所以我们有必要来聊聊在Redis使用过程中的一些“正确姿势“。
切忌裸奔
大家别笑... 很多初学者或者没经验的开发人员在服务器上用root用户装了redis以后,打开默认端口直接就愉快的运行起来了,开放了外网及默认端口的连接,甚至对于生产环境也这样,贪图一时的方便,这种情况比较多的出现在一些初创公司 (包括N年前的我也这么干过...)
那么会出现什么问题呢?最常见的就是Redis未授权访问漏洞。攻击者扫描到互联网开放的ip以及默认的6379端口后,直接在本地远程连接你服务器的redis,通过redis的命令将本机生成的公钥写入到服务器的authorized.keys中,这时候本机就可以ssh免密登录进来了。接下来可以写入反弹shell,提权,然后就可以为所欲为了,这就是为什么你的服务器上面会突然出现有挖矿程序的一个原因。
为了防止出现上述的风险,我们可以从以下几个地方来处理。
-
修改默认端口6379
-
绑定内网访问 bing 127.0.0.1
-
添加redis的密码验证
-
以低权限的用户运行redis
-
必要时设置防火墙策略
禁止“ key *” ,用“scan”代替
说到这个,笔者也是满满的泪,在年少无知的时候曾经在生产环境执行过这个命令,后来差点收拾背包提前下班了。为什么这个操作这么可怕呢?“key *” 操作的意思是返回数据库中所有匹配的key,它会扫一次性扫描所有的记录,当你库里的数据量很大的时候,会造成redis的阻塞,cpu使用率飙升,慢慢的拖垮项目中对redis的相关请求直至出现各种timeout...
在Redis2.8版本以后,提供了一个更好的遍历key的操作"scan",它类似于我们jdbc中ResultSet,通过一个游标来迭代。使用方法为“SCAN cursor [MATCH pattern] [COUNT count]”
redis 127.0.0.1:6379> scan 0 1) "17" 2) 1) "key:12" 2) "key:8" 3) "key:4" 4) "key:14" 5) "key:16" 6) "key:17" 7) "key:15" 8) "key:10" 9) "key:3" 10) "key:7" 11) "key:1" redis 127.0.0.1:6379> scan 17 1) "0" 2) 1) "key:5" 2) "key:18" 3) "key:0" 4) "key:2" 5) "key:19" 6) "key:13" 7) "key:6" 8) "key:9" 9) "key:11"
“scan 0 ”表示开始一个新的迭代,当返回的第一参数为0时,则表示迭代结束,若不为0,下一次迭代的时候带上这个游标开始下一次遍历,直到返回0.第二个参数则是当前遍历出来的值。使用的时候需要注意版本,当版本低于2.8时,需升级才能使用。
key的设计
首先用“:”来分割key是一个约定俗成的东西,自己使用的时候就尽量不要用一些比较特殊的字符来代替。关于我们的key设计可以参照我们的关系型数据库。
假如有一个user表,有userid,age,username字段,那么我们key就可以"user:userid:useridValue:username"这么来设计,把表名作为key的前缀,查询的条件放在最后。中间用字段跟它所对应的value分割开来,所有的设计都是为了在查询的时候可以更便捷。
合理使用多个db
redis的db下标默认0-15,也就是有16个。通常大部分人都是使用db0,所有的k-v都在一个库中。这其实没多大问题,但是redis不是关系型数据库,存储的数据相互耦合不那么大,所以建议可以按照不同的业务把数据分散到各个库中,这样我们可以select 不同的 db 来执行不同的业务模块操作。
善用5种数据结构
redis提供了5种数据结构,但是根据以往的面试结果来看,很多应聘者几乎在项目中只用到string类型,甚至对其他类型一知半解。其实当我们能在不同的场景善用不同的结构的话,效率会有很大的提升。下面简单介绍几个例子。
SortSet
它提供了一个优先级(score)来排序,我们可以把score的值设置成时间戳,这样我们可以通过一些定时的操作来取出某段时间里面数据,在我们项目的机器人模块中有大量的此类操作。还有常用的地方是排行榜,通过score值的变化来快速高效的更新榜单。
list
它的实现是一个双向链表,我们可以把一些需要执行的任务通过lpush,rpush存放进来,组成符合我们需求的顺序,最后我们在依次取出来执行,类似于mq。
set
用来做一些自动去重的操作,比如redis的交集命令,可以取出2个人的共同好友。
禁用高危命令
redis中有很多高危命令。如“flushdb”,“config”等,我们可以禁止或者重命名这些命令来使得操作更加安全。
我们需要修改redis的配置文件redis.conf,在SECURITY这一项中,新增
rename-command FLUSHALL ""
rename-command CONFIG ""
假如是重命名的话
rename-command FLUSHALL abcdefg
配置完重启后生效。
结语
对于redis的话题,其实还有很多,比如发布订阅,持久化机制,集群等。很多最佳实践都需要结合自身的业务不断摸索,还是那句话,适合自己的才是最好的。
喜欢的话,关注一下公众号《深夜里的程序猿》,每天更新高质量IT文章~
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
你与解决“缓存污染”只差这篇文章的距离
微信公众号:IT一刻钟。 大型现实非严肃主义现场, 一刻钟与你分享优质技术架构与见闻,做一个有剧情的程序员。 关注可第一时间了解更多精彩内容,定期有福利相送哟。 什么是缓存污染? 由于缓存的读取速度比非缓存要快上很多,所以在高性能场景下,系统在读取数据时,是首先从缓存中查找需要的数据,如果找到了则直接读取结果,如果找不到的话,则从内存或者硬盘中查找,再将查找到的结果存入缓存,以备下次使用。 实际上,对于一个系统来说,缓存的空间是有限且宝贵的,我们不可能将所有的数据都放入缓存中进行操作,即便可以数据安全性也得不到保证,而且,如果缓存的数据量过大大,其速度也会变得越来越慢。 这个时候就需要考虑缓存的淘汰机制,但是淘汰哪些数据,又保留哪些数据,这是一个问题。如果处理不得当,就会造成“缓存污染”问题。 而缓存污染,是指系统将不常用的数据从内存移到缓存,造成常用数据的挤出,降低了缓存效率的现象。 解决缓存污染的算法 LFU算法 LFU,英文名Least Frequently Used,字面意思就是最不经常使用的淘汰掉算法,是通过数据被访问的频率来判断一个数据的热点情况。其核心理念是“历史上这个数...
- 下一篇
Kubernetes CNI网络最强对比:Flannel、Calico、Canal和Weave
本文将在介绍技术原理和相应术语的基础上,再集中探索与详细对比目前最流行的CNI插件:Flannel、Calico、Weave和Canal,对比介绍它们的原理、使用方法、适用场景和优缺点等。 介 绍 网络架构是Kubernetes中较为复杂、让很多用户头疼的方面之一。Kubernetes网络模型本身对某些特定的网络功能有一定要求,但在实现方面也具有一定的灵活性。因此,业界已有不少不同的网络方案,来满足特定的环境和要求。 CNI意为容器网络接口,它是一种标准的设计,为了让用户在容器创建或销毁时都能够更容易地配置容器网络。在本文中,我们将集中探索与对比目前最流行的CNI插件:Flannel、Calico、Weave和Canal(技术上是多个插件的组合)。这些插件既可以确保满足Kubernetes的网络要求,又能为Kubernetes集群管理员提供他们所需的某些特定的网络功能。 背 景 容器网络是容器选择连接到其他容器、主机和外部网络(如Internet)的机制。容器的runtime提供了各种网络模式,每种模式都会产生不同的体验。例如,Docker默认情况下可以为容器配置以下网络: none:...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Hadoop3单机部署,实现最简伪集群
- CentOS8编译安装MySQL8.0.19
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器