Redis如何处理客户端连接
本文主要介绍了 Redis 处理客户端连接的一些内部实现机制,包括连接处理、超时、缓冲区等一系列内容。
注:本文所述内容基于 Redis2.6 及以上版本。
连接的建立
Redis 通过监听一个 TCP 端口或者 Unix socket 的方式来接收来自客户端的连接,当一个连接建立后,Redis 内部会进行以下一些操作:
- 首先,客户端 socket 会被设置为非阻塞模式,因为 Redis 在网络事件处理上采用的是非阻塞多路复用模型。
- 然后为这个socket 设置 TCP_NODELAY 属性,禁用 Nagle 算法
- 然后创建一个 readable 的文件事件用于监听这个客户端 socket 的数据发送
当客户端连接被初始化后,Redis 会查看目前的连接数,然后对比配置好的 maxclients 值,如果目前连接数已经达到最大连接数 maxclients 了,那么说明这个连接不能再接收,Redis 会直接返回客户端一个连接错误,并马上关闭掉这个连接。
服务端处理顺序
如果有多个客户端连接上 Redis,并且都向 Redis 发送命令,那么 Redis 服务端会先处理哪个客户端的请求呢?答案其实并不确定,主要与两个因素有关,一是客户端对应的 socket 对应的数字的大小,二是 kernal 报告各个客户端事件的先后顺序。
Redis 处理一个客户端传来数据的步骤如下:
- 它对触发事件的 socket 调用一次 read(),只读一次(而不是把这个 socket 上的消息读完为止),是为了防止由于某个别客户端持续发送太多命令,导致其它客户端的请求长时间得不到处理的情况。
- 当然,当这一次 read() 调用完成后,它里面无论包含多少个命令,都会被一次性顺序地执行。这样就保证了对各个客户端命令的公平对待。
关于最大连接数 maxclients
在 Redis2.4 中,最大连接数是被直接硬编码在代码里面的,而在2.6版本中这个值变成可配置的。maxclients 的默认值是 10000,你也可以在 redis.conf 中对这个值进行修改。
当然,这个值只是 Redis 一厢情愿的值,Redis 还会照顾到系统本身对进程使用的文件描述符数量的限制。在启动时 Redis 会检查系统的 soft limit,以查看打开文件描述符的个数上限。如果系统设置的数字,小于咱们希望的最大连接数加32,那么这个 maxclients 的设置将不起作用,Redis 会按系统要求的来设置这个值。(加32是因为 Redis 内部会使用最多32个文件描述符,所以连接能使用的相当于所有能用的描述符号减32)。
当上面说的这种情况发生时(maxclients 设置后不起作用的情况),Redis 的启动过程中将会有相应的日志记录。比如下面命令希望设置最大客户端数量为100000,所以 Redis 需要 100000+32 个文件描述符,而系统的最大文件描述符号设置为10144,所以 Redis 只能将 maxclients 设置为 10144 – 32 = 10112。
$ ./redis-server --maxclients 100000
[41422] 23 Jan 11:28:33.179 # Unable to set the max number of files limit to 100032 (Invalid argument), setting the max clients configuration to 10112.
所以说当你想设置 maxclients 值时,最好顺便修改一下你的系统设置,当然,养成看日志的好习惯也能发现这个问题。
具体的设置方法就看你个人的需求了,你可以只修改此次会话的限制,也可以直接通过sysctl 修改系统的默认设置。如:
ulimit -Sn 100000 # This will only work if hard limit is big enough.
sysctl -w fs.file-max=100000
输出缓冲区大小限制
对于 Redis 的输出(也就是命令的返回值)来说,其大小经常是不可控的,可能是一个简单的命令,能够产生体积庞大的返回数据。另外也有可能因为执行命令太多,产生的返回数据的速率超过了往客户端发送的速率,这时也会产生消息堆积,从而造成输出缓冲区越来越大,占用过多内存,甚至导致系统崩溃。
所以 Redis 设置了一些保护机制来避免这种情况的出现,这些机制作用于不同种类的客户端,有不同的输出缓冲区大小限制,限制方式有两种:
- 一种是大小限制,当某一个客户端的缓冲区超过某一大小时,直接关闭掉这个客户端连接
- 另一种是当某一个客户端的缓冲区持续一段时间占用空间过大时,也直接关闭掉客户端连接
对于不同客户端的策略如下:
- 对普通客户端来说,限制为0,也就是不限制,因为普通客户端通常采用阻塞式的消息应答模式,如:发送请求,等待返回,再发请求,再等待返回。这种模式通常不会导致输出缓冲区的堆积膨胀。
- 对于 Pub/Sub 客户端来说,大小限制是32m,当输出缓冲区超过32m时,会关闭连接。持续性限制是,当客户端缓冲区大小持续60秒超过8m,也会导致连接关闭。
- 而对于 Slave 客户端来说,大小限制是256m,持续性限制是当客户端缓冲区大小持续60秒超过64m时,关闭连接。
上面三种规则都是可配置的。可以通过 CONFIG SET 命令或者修改 redis.conf 文件来配置。
输入缓冲区大小限制
Redis 对输入缓冲区大小的限制比较暴力,当客户端传输的请求大小超过1G时,服务端会直接关闭连接。这种方式可以有效防止一些客户端或服务端 bug 导致的输入缓冲区过大的问题。
Client 超时
对当前的 Redis 版本来说,服务端默认是不会关闭长期空闲的客户端的。但是你可以修改默认配置来设置你希望的超时时间。比如客户端超过多长时间无交互,就直接关闭。同理,这也可以通过 CONFIG SET 命令或者修改 redis.conf 文件来配置。
值得注意的是,超时时间的设置,只对普通客户端起作用,对 Pub/Sub 客户端来说,长期空闲状态是正常的。
另外,实际的超时时间可能不会像设定的那样精确,这是因为 Redis 并不会采用计时器或者轮训遍历的方法来检测客户端超时,而是通过一种渐近式的方式来完成,每次检查一部分。所以导致的结果就是,可能你设置的超时时间是10s,但是真实执行的时间是超时12s后客户端才被关闭。
CLIENT 命令
Redis 的 CLIENT 命令能够实现三种功能:检查连接的状态,杀掉某个连接以及为连接设置名字。
CLIENT LIST 命令能够获取当前所有客户端的状态,使用方法如下:
redis 127.0.0.1:6379> client list
addr=127.0.0.1:52555 fd=5 name= age=855 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
addr=127.0.0.1:52787 fd=6 name= age=6 idle=5 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
如上面命令的输出可知,目前此 Redis 有两个客户端连接,每一行表示一个连接的各项信息:
- addr: 客户端的TCP地址,包括IP和端口
- fd: 客户端连接 socket 对应的文件描述符句柄号
- name: 连接的名字,默认为空,可以通过 CLIENT SETNAME 设置
- age: 客户端存活的秒数
- idle: 客户端空闲的秒数
- flags: 客户端的类型 (N 表示普通客户端,更多类型见 http://redis.io/commands/client-list)
- omem: 输出缓冲区的大小
- cmd: 最后执行的命令名称
你可以查看 CLIENT LIST 的文档来具体查看所有输出的含义。
当你通过上面命令获取到客户端列表后,就可以通过 CLIENT KILL 命令来杀死指定的连接了。CLIENT KILL 的参数就是上面的 addr 值。
如上面提到的 CLIENT SETNAME 和 CLIENT GETNAME 可以用来为一个连接设置一个名字。
参考来源:http://redis.io/topics/clients http://blog.nosqlfan.com/html/4153.html
Redis如何处理客户端连接的更多相关文章
- Redis 处理客户端连接的一些内部实现机制
本文主要介绍了 Redis 处理客户端连接的一些内部实现机制,包括连接处理.超时.缓冲区等一系列内容. 注:本文所述内容基于 Redis2.6 及以上版本. 连接的建立 Redis 通过监听一个 TC ...
- Redis基础知识之————如何处理客户端连接
redis 连接建立 Redis Redis 通过监听一个 TCP 端口或者 Unix socket 的方式来接收来自客户端的连接,当一个连接建立后,Redis 内部会进行以下一些操作: 首先,客户端 ...
- Redis客户端连接池
使用场景 对于一些大对象,或者初始化过程较长的可复用的对象,我们如果每次都new对象出来,那么意味着会耗费大量的时间. 我们可以将这些对象缓存起来,当接口调用完毕后,不是销毁对象,当下次使用的时候,直 ...
- redis客户端连接异常
本文参考:http://mdba.cn/2015/04/02/redistwemproxy-%e5%ae%a2%e6%88%b7%e7%ab%af%e8%bf%9e%e6%8e%a5%e5%bc%82 ...
- Redis 客户端连接
Redis 通过监听一个 TCP 端口或者 Unix socket 的方式来接收来自客户端的连接,当一个连接建立后,Redis 内部会进行以下一些操作: 首先,客户端 socket 会被设置为非阻 ...
- redis基础操作~~数据备份与恢复、数据安全、性能测试、客户端连接、分区
数据备份与恢复 数据备份redis save 命令用于创建当前数据库的备份. redis 127.0.0.1:6379> SAVE OK 该命令将在 redis 安装目录中创建dump.rdb文 ...
- redis拾趣(客户端连接,keys命令,数据备份,缓存有效期等)
1.客户端连接 为了安全保护,redis支持绑定IP跟端口,这个通过conf配置文件中的bind跟port来设置. 绑定后登录client控制台时就需要写明ip(或者hostname)跟端口了,如: ...
- Redis客户端连接以及持久化数据(三)
0.Redis目录结构 1)Redis介绍及部署在CentOS7上(一) 2)Redis指令与数据结构(二) 3)Redis客户端连接以及持久化数据(三) 4)Redis高可用之主从复制实践(四) 5 ...
- Redis客户端连接
Redis接受上配置监听TCP端口和Unix套接字客户端的连接,如果启用.当一个新的客户端连接被接受,如有以下操作进行: 客户端套接字置于非阻塞状态,因为Redis的使用复用和非阻塞I/O操作. TC ...
随机推荐
- Sublime Text 2 绿化与汉化 [Windows篇]
其实 ST3 已经出了很久了,可是我这个人恋旧,一直钟爱 ST2,所以就选择她了.最近我的 ST2 越来越卡,甚至有时候输入都会延迟1秒,所以打算自己搞个绿化版. 打开 Sublime Text 官网 ...
- html template--(来自网易)
html template 概述 包含完整头部信息和主体结构的HTML基础模板. 代码展示 <!DOCTYPE html> <html> <head> < ...
- AngularJS入门基础——表单验证
<form name="form" novalidata> <label name="email">your email</l ...
- 洛谷 P1045 【麦森数】快速幂
不用快速幂,压位出奇迹! 本人是个蒟蒻,不太熟悉快速幂,这里给大家介绍一种压位大法. 让我们来分析一下题目,第一位是送分的,有一个专门求位数的函数:n*log10(2)+1. 然后题目中p<=3 ...
- 批量增加Linux系统账号、重置账号密码、FTP账号批量测试
批量增加Linux系统账号.重置账号密码是用Linux Shell脚本来做的:批量FTP账号测试是用Python脚本来做的.这些脚本都是读取一个用户名和密码文件,然后基于该用户名密码文件进行自动批量测 ...
- objective-c 几何类常用方法整理
CGGeometry参考定义几何结构和功能,操作简单.数据结构中的一个点CGPoint代表在一个二维坐标系统.数据结构的位置和尺寸CGRect代表的一个长方形.数据结构的尺寸CGSize代表宽度和高度 ...
- 【SVN】命令行忽略不必要的文件和文件夹
SVN命令参考: https://www.cnblogs.com/wlsxmhz/p/5775393.html 我们需要明白命令行设置忽略文件和文件夹是通过设置svn:ignore属性设置的,pr ...
- java future 并发简单实现
List<Future<>> futures = new ArrayList<>();List<T> t= new ArrayList<>( ...
- Linux内核启动流程分析(二)【转】
转自:http://blog.chinaunix.net/uid-25909619-id-3380544.html S3C2410 Linux 2.6.35.7启动分析(第二阶段) 接着上面的分析,第 ...
- Python学习二|Python的一些疑问
最近写了一点Python代码,作为一个java程序员,面对Python这么便捷的语言不禁有点激动.不过呢,有时候也会遇到一些无法理解的东西. 例如: er = [[1,2,3], [4,5,6], [ ...