前言

说到分布式缓存,可能大多数人脑海浮现的就是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的话题,其实还有很多,比如发布订阅,持久化机制,集群等。很多最佳实践都需要结合自身的业务不断摸索,还是那句话,适合自己的才是最好的。

文章始发于微信公众号《深夜里的程序猿》,转载请注明出处,侵权必究。

Redis的正确使用姿势的更多相关文章

  1. 如约而至,Java 10 正式发布! Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十四)Redis缓存正确的使用姿势 努力的孩子运气不会太差,跌宕的人生定当更加精彩 优先队列详解(转载)

    如约而至,Java 10 正式发布!   3 月 20 日,Oracle 宣布 Java 10 正式发布. 官方已提供下载:http://www.oracle.com/technetwork/java ...

  2. xpath轴的正确使用姿势

    网上看了许多关于轴的介绍,只介绍了语法,而没有明说具体实际中该怎么使用,百思不得其解. 背景--python中使用xpath:  ----------------------------------- ...

  3. 高版本jquery尤其是1.10.2的版本设置input radio设置值的最正确的姿势。

    $("input:radio[name="analyshowtype"]").attr("checked",false); $(" ...

  4. NSnotificationCenter 正确使用姿势, removeObject 探索

    最近在做平板的过程中,发现了一些很不规范的代码.偶然修复支付bug的时候,看到其他项目代码,使用通知的地方没有移除,我以为我这个模块的支付闪退是因为他通知没有移除的缘故.而在debug和看了具体的代码 ...

  5. 微信H5中静默登录及非静默登录的正确使用姿势

    在微信中打开网页且需要调用微信登录接口时,微信官方给我们提供了两种登录调用方式:静默登录和非静默登录:但是官方文档中却没有说明在何种情况下使用静默登录,何种情况下使用非静默登录,所以在这里,我想将之前 ...

  6. Java日志正确使用姿势

    前言 关于日志,在大家的印象中都是比较简单的,只须引入了相关依赖包,剩下的事情就是在项目中“尽情”的打印我们需要的信息了.但是往往越简单的东西越容易让我们忽视,从而导致一些不该有的bug发生,作为一名 ...

  7. MongoDB系列:五、MongoDB Driver使用正确的姿势连接复制集

    MongoDB复制集(Replica Set)通过存储多份数据副本来保证数据的高可靠,通过自动的主备切换机制来保证服务的高可用.但需要注意的时,连接副本集的姿势如果不对,服务高可用将不复存在. 使用复 ...

  8. 基于winserver的Apollo配置中心分布式&集群部署实践(正确部署姿势)

    基于winserver的Apollo配置中心分布式&集群部署实践(正确部署姿势)   前言 前几天对Apollo配置中心的demo进行一个部署试用,现公司已决定使用,这两天进行分布式部署的时候 ...

  9. 玩转java多线程(wait和notifyAll的正确使用姿势)

    转载请标明博客的地址 本人博客和github账号,如果对你有帮助请在本人github项目AioSocket上点个star,激励作者对社区贡献 个人博客:https://www.cnblogs.com/ ...

随机推荐

  1. Linux——浅析信号处理

    信号及其处理 信号处理是Unix和LInux系统为了响应某些状况而产生的事件,通常内核产生信号,进程收到信号后采取相应的动作. 例如当我们想强制结束一个程序的时候,我们通常会给它发送一个信号,然后该进 ...

  2. python笔记:#002#第一个python程序

    第一个 Python 程序 目标 第一个 HelloPython 程序 Python 2.x 与 3​​.x 版本简介 执行 Python 程序的三种方式 解释器 -- python / python ...

  3. centOS7固定IP

    接续安装完成centOS虚拟机后,重启完成后,会出现如下的界面: 这里,我们使用root帐号和已配置的root密码进行登陆,登陆完成后,输入如下命令,运行结果如下图: dhclient 通过上述命令, ...

  4. Python学习 Part5:输入输出

    Python学习 Part5:输入输出 1. 格式化输出 三种输出值的方法: 表达式语句 print()函数 使用文件对象的write()方法 两种方式格式化输出: 由自己处理整个字符串,通过使用字符 ...

  5. 使用input file上传文件中onChange事件只触发一次问题

    每次上传文件的时候,都会将当前的文件路径保存至$event.target.value中,当第二次选择文件时,由于两次$event.target.value相同,所以不会触发change事件. 解决方案 ...

  6. java集合HashMap、HashTable、HashSet详解

    一.Set和Map关系 Set代表集合元素无序,集合元素不可重复的集合,Map代表一种由多个key-value组成的集合,map集合是set集合的扩展只是名称不同,对应如下 二.HashMap的工作原 ...

  7. Redis的并发竞争问题的解决方案总结

    什么是Redis的并发竞争问题 Redis的并发竞争问题,主要是发生在并发写竞争. 考虑到redis没有像db中的sql语句,update val = val + 10 where ...,无法使用这 ...

  8. CentOS7快速搭建LNMP环境

    名词解释: LNMP:Linux+Nginx+MySql+PHPLAMP:LInux+Apache+MySql+PHPNginx的正确读法应该是Engine X我们使用CentOS自带的YUM来安装 ...

  9. ES7 Async/Await 陷阱

    什么是Async/Await ES6新增了Promise函数用于简化项目代码流程.然而在使用promise时,我们仍然要使用callback,并且并不知道程序要干什么,例如: function doS ...

  10. centos网络配置方法(手动设置,自动获取)

    不知道为什么最近一段时间网络特别的慢,还老是断,断的时候,局域网都连不上,当我手动设置一下ip后就可以了,搞得我很无语.下面是2种设置网络连接的方法,在说怎么设置前,一定要做好备份工作,特别是对于新手 ...