共计 2564 个字符,预计需要花费 7 分钟才能阅读完成。
自动写代码机器人,免费开通
这篇文章主要介绍“redis 在高并发下的性能讲解”,在日常操作中,相信很多人在 redis 在高并发下的性能讲解问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”redis 在高并发下的性能讲解”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!
前言:
最近上手了一个项目,我负责该项目的架构设计与实现。本来公司做了很多给公司以外的人使用的 API,但是在外人使用的时候,接口的链接是怎样就给别人怎么样,没有加密也没有做并发控制,接口程序所在的机器在哪,给别人的 IP 就在哪,而且没有平台进行管理。因此我清楚地知道,这些接口的价值很难被发现(哪个接口别人用的比较多,哪个接口别人用的比较少)。
仅仅针对”监控“的这一需求,我们引入了 redis 作为中间层,首先我们完善了用户使用接口的注册流程,通过用户信息和地址,hash 出一个 key,这个 key 是对应着一个地址的,把这个(key – 地址)对存在了 redis 里面。其次是 nginx,nginx 在我们的项目里面的流程大概是这样:
1、用户注册之后获取到他的 key,通过包含了 key 的跟原本的 url 完全不同的 url 来访问
2、nginx 捕获到用户特殊的 key,然后程序根据这个 key 从 redis 中取出目标地址,再由 nginx 代替用户访问真正的地址,继而返回。
(这个过程好处是很多的)
(1)、隐藏了真实的地址,程序可以在上游服务器之外的地方干预用户的访问,提高安全性,干预过程可以很复杂
(2)、获取用户的信息,并将其存回 redis,上游服务器通过定时程序将存在 redis 中的日志持久化进 oracle 并删除,然后进一步分析和可视化
问题来了
这个项目还处于测试阶段,资源是一台 window server 服务器,和 centos6.5 服务器,测试阶段 10 秒内大概有 10 万的并发量,刚部署上去的一两天还是没有问题的,接下来却出现了 redis 连接不上的情况。查看进程访问,会出现下面的情况。(window server 下)
出现很多 FiN_WAIT_2 的 TCP 链接。
(学习视频分享:redis 视频教程)
分析
一、redis 是使用单线程处理连接的,意味着它绝对会出现下面二所说的情况。
二、很明显这是由于 nginx 和 redis 之间有很多没有释放的资源造成的,查看这个 TCP 的状态 FIN_WAIT_2,解释一下:
在 HTTP 应用中,存在一个问题,SERVER 由于某种原因关闭连接,如 KEEPALIVE 的超时,这样,作为主动关闭的 SERVER 一方就会进入 FIN_WAIT2 状态,但 TCP/IP 协议栈有个问题,FIN_WAIT2 状态是没有超时的(不象 TIME_WAIT 状态),所以如果 CLIENT 不关闭,这个 FIN_WAIT_2 状态将保持到系统重新启动,越来越多的 FIN_WAIT_2 状态会致使内核 crash。
好吧,大学没有好好念书,下面是 http 连接的状态变化
客户端状态迁移
CLOSED- SYN_SENT- ESTABLISHED- FIN_WAIT_1- FIN_WAIT_2- TIME_WAIT- CLOSEDb.
服务器状态迁移
CLOSED- LISTEN- SYN 收到 - ESTABLISHED- CLOSE_WAIT- LAST_ACK- CLOSED
有缺陷的客户端与持久连接
有一些客户端在处理持久连接 (akakeepalives) 时存在问题。当连接空闲下来服务器关闭连接时(基于 KeepAliveTimeout 指令),
客户端的程序编制使它不发送 FIN 和 ACK 回服务器。这样就意味着这个连接 将停留在 FIN_WAIT_2 状态直到以下之一发生:
客户端为同一个或者不同的站点打开新的连接,这样会使它在该个套接字上完全关闭以前的连接。
用户退出客户端程序,这样在一些 (也许是大多数?) 客户端上会使操作系统完全关闭连接。
FIN_WAIT_2 超时,在那些具有 FIN_WAIT_2 状态超时设置的服务器上。
如果你够幸运,这样意味着那些有缺陷的客户端会完全关闭连接并释放你服务器的资源。
然而,有一些情况下套接字永远不会完全关闭,比如一个拨号客户端在关闭客户端程序之前从 ISP 断开。
此外,有的客户端有可能空置好几天不创建新连接,并且这样在好几天里保持着套接字的有效即使已经不再使用。这是浏览器或者操作系统的 TCP 实现的 Bug。
产生原因有:
1、长连接并且当连接一直处于 IDLE 状态导致 SERVERCLOSE 时,CLIENT 编程缺陷,没有向 SERVER 发出 FIN 和 ACK 包
2、APACHE1.1 和 APACHE1.2 增加了 linger_close()函数,前面的帖子有介绍,这个函数可能引起了这个问题(为什么我也不清楚)
解决办法:
1。对 FIN_WAIT_2 状态增加超时机制,这个特性在协议里没有体现,但在一些 OS 中已经实现
如:LINUX、SOLARIS、FREEBSD、HP-UNIX、IRIX 等
2。不要用 linger_close()编译
3。用 SO_LINGER 代替,这个在某些系统中还能很好地处理
4。增加用于存储网络连接状态的内存 mbuf,以防止内核 crash
5。DISABLE KEEPALIVE
针对这种情况,我们做了几次讨论,有些结论,分别是:
1、设置 nginx 与 redis 的连接池,keepalive 的时间,分别设为 10 秒,5 秒,但是结果还是一样
2、不用 keepalive,即不使用连接池,即每次用完就 close()掉,你可以看到连接少了,但是不使用连接池,意味着 10 秒内要打开关闭 10 万次,开销太大
3、redis 集群,在原本集群的体系上添加 redis 的集群,这或许能解决问题,但是 10 秒内 10 万实际上并不多,这样做了或许是取巧,并没有找到问题
4、设置 redis 的 idle(空闲)时间限制,结果一样。
解决方案:
实际上不算解决方案,因为放弃了 redis 的内存机制,而是使用 nginx 本身的内存技术。网上关于 redis 的优化大部分不适用,这个问题有待分析解决。
到此,关于“redis 在高并发下的性能讲解”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注丸趣 TV 网站,丸趣 TV 小编会继续努力为大家带来更多实用的文章!
向 AI 问一下细节