ngx_srcache + lua异步更新缓存----提高10倍的响应速度

nginx_lua异步更新缓存

NGINX

一直使用nginx做为反向代理服务器,一来nginx基于事件驱动,速度快。而来nginx的反向代理模块能很好的支持页面缓存负载均衡nginx

页面缓存

nginx有proxy_cache这个内置的缓存功能,是基于文件的。若是把缓存路径设置到RAMDISK上面,能够达到和内存缓存差很少的缓存读写速度。这样作虽然解决了文件读写慢的问题,可是若是分布式部署的时候,这个缓存不能跨机器共享。git

srcache-nginx-module

章大神写的这个模块支持和另外一个模块配合将页面缓存写入redis集群。就很好的解决了github

  1. 缓存不能跨机器共享的问题redis

  2. 也使得缓存大小不受单机资源限制后端

  3. 同时,redis自己还能提供快速的读写速度缓存

问题

看上面列的几点,彷佛已经很完美了。
可是在实际使用的时候仍是发现有须要改善的地方:服务器

  1. 缓存不存在的时候:
    第一个请求查询redis失败,到后端,最后还要存储redis。比没有缓存的状况还多出两次redis访问,一次读一次写。并且当并发访问的时候还可能请求都会进入后端服务器,后端不够健壮的时候会致使“雪崩效应”。(若是使用默认的proxy_cache模块还能经过proxy_cache_use_stale命令避免,可是srcache模块没有实现相似功能)并发

  2. 缓存失效的时候
    一般咱们为页面设置缓存时间,缓存失效的时候,须要从新更新缓存。这个时候也会出现第一种状况相似的问题。负载均衡

以上两种状况,第一种出现较少,第二种状况出现较多。都是因为redis自动删除过时缓存,致使的缓存缺失。异步

解决办法

因为nginx不知道redis里面数据的缓存时间,因此会频繁的致使缓存缺失的状况出现。
既然知道缘由了,那么我们就来针对性的解决一下这个问题。让nginx可以知道甚至参与到缓存时间的管理里面,就能有效的避免被动的缓存缺失问题,能有意识的主动更新缓存

ngx_lua

这里须要提到一个nginx的第三方模块就是把lua集成到nginx里面扩展了nginx配置文件语法,支持在配置文件里面直接使用lua语言编写逻辑。

lua-resty-cache

我将本身在项目中使用的一个仓库开源到github上面了。

  1. 能让nginx主动的检测缓存的过时时间

  2. 在快过时的时候,直接返回旧的缓存数据

  3. 使用异步任务更新缓存

以上的第二第三两点,就能在缓存快过时的时候,主动的异步更新缓存,让终端用户感知不到更新缓存的过程。
项目中实测,使用这个缓存机制以后,用户感知到的平均响应速度提高了10倍(nginx access log分析结果),而这都是在原有系统性能不变的状况下实现的!是否是有点难以想象。

原理

下面就来讲一说提高速度的原理:

  1. 若是缓存缺失,直接跳过srcache_fetch步骤,将请求发到后端server。同时申请一个共享内存锁,并发而来的相同的请求不用发送到后端,而是等待这个请求返回。

  2. 更新缓存的时候,在过时时间expire基础上加上一个stale time。那么在到了过时时间的时候,redis还不会当即删掉这个数据。

  3. 若是检测到数据过时,可是redis还能拿到这个“过时”数据,则当即返回过时数据给终端用户。

  4. 在结束请求的同时,使用一个异步任务去更新缓存,考虑到并发状况,这里也须要使用一个共享内存锁。

这样,即便在缓存过时的时候,用户也不多会遇到只能从后端server拿数据的状况。因此能节省至关的时间,在速度上有这么大的提高。

后记

这个库运行了有好几个月了,很是的稳定。固然这得益于nginx的稳定。可是也不得不说,使用这个库以后,后端server可以收到的请求,已经绝大部分都是由那个异步的任务发出的。用户基本都能在缓存里面直接拿到数据。因此,后端server的性能,没有提高,可是给用户的感受倒是快了不少!!!

相关文章
相关标签/搜索