缓存服务器可能的瓶颈
- CPU内核的计算能力
- 网络带宽的限制
- 内存的大小,但是内存的大小主要限制存储能力
针对以上问题,Redis进行了相关的性能优化,主要从以下两个方面进行解析
Redis的传输协议
Redis是client-server类型的组件,启动Redis之后,服务默认起在6379端口,可以通过默认的client使用命令行进行set、get操作,各种语言也都有自己实现的客户端,例如java中经常使用的jedis。
以java客户端为例,它们通过socket网络连接,连接到Redis的server,那么要使server能够识别client端的请求,就需要按照一定的协议发送命令。这个建立在tcp连接之上的协议不是我们熟悉的http协议,而是RESP协议。
简单来说,RESP协议可以用来描述client和server之间的request和response。主要的协议内容如下:
普通字符串以+开头
+OK
错误以-开头
-ERROR
Integer以:开头
:100
大字符串以$开头,不超过512M
$OK
数组以*开头
一个综合的示例,[“foo”,nil,“bar”]
*3\r\n
$3\r\n
foo\r\n
$-1\r\n
$3\r\n
bar\r\n
对于请求的命令,按照RESP协议进行组织,官网上给了示例,LLEN mylist命令在RESP协议的表示下为
C: *2\r\n
C: $4\r\n
C: LLEN\r\n
C: $6\r\n
C: mylist\r\n
S: :48293\r\n
通过以上的简单介绍就知道通过RESP协议组织请求,可以大大地节省网络带宽。
RESP协议官网描述
pipeline机制
同时,Redis还提供了pipeline机制来进行批量操作,普通的命令运行如下:
Client: INCR X
Server: 1
Client: INCR X
Server: 2
Client: INCR X
Server: 3
Client: INCR X
Server: 4
而在pipeline下,命令的编排如下:
Client: INCR X
Client: INCR X
Client: INCR X
Client: INCR X
Server: 1
Server: 2
Server: 3
Server: 4
其实很容易理解,在pipeline机制下,从两方面提高了效率,一个是减少了网络时延,把多次网络的请求损耗降低到了一次,另一方面是减少了socket的I/O操作,减少了用户态和内核态之间的上下文切换。
但是,使用pipeline需要注意的一点是,由于pipline的命令不需要拿到response就可以直接返回,则需要将指令在内存中排队,所以我理解一次的批量操作应当有上限,以防止内存不足。
以上都引用自Redis官网,Redis官网是我见过写的最友好的官网。