Memcache做频率限制引发的问题分析.doc

Memcache做频率限制引发的问题分析.doc

ID:27498978

大小:148.00 KB

页数:7页

时间:2018-12-04

Memcache做频率限制引发的问题分析.doc_第1页
Memcache做频率限制引发的问题分析.doc_第2页
Memcache做频率限制引发的问题分析.doc_第3页
Memcache做频率限制引发的问题分析.doc_第4页
Memcache做频率限制引发的问题分析.doc_第5页
资源描述:

《Memcache做频率限制引发的问题分析.doc》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库

1、Memcache做频率限制引发的问题分析  returnmemCachedClient.add(key,”abc”,newDate(System.currentTimeMillis()+1000));  }  问题  一切看起来很顺利,直到有一天线上报错资源在100ms内被访问两次。也就是说,同一个用户的超时键被设置为1s以后,100ms再次去检查居然键过期了。什么鬼?逻辑上无懈可击的代码怎么可能会有漏洞?先不管那些,复现再说。  Memcache做频率限制引发的问题分析  returnmemCa

2、chedClient.add(key,”abc”,newDate(System.currentTimeMillis()+1000));  }  问题  一切看起来很顺利,直到有一天线上报错资源在100ms内被访问两次。也就是说,同一个用户的超时键被设置为1s以后,100ms再次去检查居然键过期了。什么鬼?逻辑上无懈可击的代码怎么可能会有漏洞?先不管那些,复现再说。    代码简单粗暴,就是启5个线程,每个线程连续尝试过滤某个键十万次。  运行上述代码,每次都有很多键被判定为过期。充分分析整个流程,

3、定位可能的问题原因:  后台业务服务器与Memcache服务器时钟不同步。Memcache的过期时间是一个时间戳,而不是相对时间偏移量,所以如果Memcache客户端和服务器有时间差的话,比如客户端的时间比服务器时间慢1s,那么客户端设置的过期时间(它当前的时间+1000ms)在服务器看来却已经过期了。  Memcache的键清理机制导致。在极端情况下(比如说Memcache被分配的内存不够用了),Memcache会清理一些键值对,即使这些键还没有过期。  但是以上两个原因中,时钟不同步的原因很快

4、被排除了。因为从日志分析来看,相当一部分频繁请求是被拦截下来的,如果时钟不同步,应该有相当比例的频繁请求被放过才对。并且跟运维确认,线上的服务器都开启了时钟同步功能,两个服务器的时钟差不会超过10ms。  现在看来只有内存清理机制这一个原因了。研究了下Memcache的键清理机制,总结如下:  当有新数据需要存储的时候,Memcache会先看数据大小对应的Slab是否有空闲Item,如果有,将数据存入Item,同时更新LRU表。  如果没有空闲Item,Memcache会尝试去看对应Slab是否有

5、过期键。如果有,清空过期键,将数据存入新的Item,同时更新LRU表。  如果没有过期键,Memcache会尝试申请一个新的Slab,如果申请成功,将数据存入新Slab对应的Item,同时更新LRU表。  如果申请失败,并且Memcache配置了强制淘汰机制,会将LRU链表尾部的Item强制清空,并存入新Item,同时更新LRU表。  总体看下来,强制淘汰的触发条件还是很苛刻的,并且具体的实现中,LRU链表分为Hot,Warm,Cold三个区域,新加入的数据会在Hot区,等Hot区满了,较早的数据

6、才会被降级到其他区。也就是说,假设存入数据为大小为100B,对应Slab在Memcache服务器上只有一个(一般会有很多),那么此Slab中可用Item数量约为10000个。在这种情况下,如果要触发刚刚存入100ms的未过期键被强制清理的话,需要在100ms内有超过10000条100B左右大小的数据写入Memcache。在测试环境几乎不可能。但是这是一个公共的Memcache,谁知道呢?所以需要排除一下这个情况。诊断  本地起一个虚拟机,装个Memcache,顺便打开日志打印(本来的目的是为了看到

7、键淘汰日志)。如果是强制淘汰机制引起,那在只有一个client的本地Memcache上,应该就不会出现这个问题(测试代码可以控制键数量和写入速度),但是不幸的是,在这个空的Memcache上也出现了同样的现象--这直接排除了此现象是由强制淘汰机制导致的的可能性。  在本地虚拟机启动的Memcache打印的日志中,发现了一个现象:所有时间戳都是类似于这样的格式:1527001620,有点奇怪,比毫秒时间戳短。去查了一下源码,果然被猜中:    而rel_time_t的定义为:  typedefuns

8、ignedintrel_time_t;  毫无疑问,Memcache的时间是用秒计算而不是毫秒。我们使用的客户端接口方法:  publicbooleanadd(Stringkey,Objectvalue,Dateexpiry);  非常具有误导性,因为Date是精确到毫秒的,这也使我们一直理所当然地以为Memcache提供毫秒精度的过期时间校验,然而这是不对的。原因  至此,问题的原因就很明朗了,Memcache的过期判断代码如下:    最重要的一句是:  it->exptime

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。