欢迎来到三一文库! | 帮助中心 三一文库31doc.com 一个上传文档投稿赚钱的网站
三一文库
全部分类
  • 研究报告>
  • 工作总结>
  • 合同范本>
  • 心得体会>
  • 工作报告>
  • 党团相关>
  • 幼儿/小学教育>
  • 高等教育>
  • 经济/贸易/财会>
  • 建筑/环境>
  • 金融/证券>
  • 医学/心理学>
  • ImageVerifierCode 换一换
    首页 三一文库 > 资源分类 > DOC文档下载  

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

    • 资源ID:3256137       资源大小:18.50KB        全文页数:4页
    • 资源格式: DOC        下载积分:2
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录   微博登录  
    二维码
    微信扫一扫登录
    下载资源需要2
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

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

    Memcache做频率限制引发的问题分析线上服务为了限制用户频繁访问敏感资源,通常会引入一种机制来限制这种访问操作。其中一种常见的方案就是为每个用户的访问做一次时间戳,同一个用户再次访问对应资源时,检查当前时间和已经记录的时间戳的差值 - 如果此差值小于我们定义的超时时间,此次访问被判定为频繁访问。我们在某系统的实现中便采用了此种机制,限定用户在 1s内不能连续访问2次,配合Memcache,实现起来非常简单。 核心代码如下:public boolean isOutOfTime(String key)     return memCachedClient.add(key,"abc",new Date(System.currentTimeMillis() + 1000);  问题一切看起来很顺利,直到有一天线上报错资源在100ms内被访问两次。也就是说,同一个用户的超时键被设置为1s以后,100ms再次去检查居然键过期了。 什么鬼?逻辑上无懈可击的代码怎么可能会有漏洞?先不管那些,复现再说。代码简单粗暴,就是启5个线程,每个线程连续尝试过滤某个键十万次。运行上述代码,每次都有很多键被判定为过期。充分分析整个流程,定位可能的问题原因:后台业务服务器与Memcache服务器时钟不同步。Memcache的过期时间是一个时间戳,而不是相对时间偏移量,所以如果Memcache客户端和服务器有时间差的话,比如客户端的时间比服务器时间慢1s,那么客户端设置的过期时间(它当前的时间 + 1000ms)在服务器看来却已经过期了。Memcache的键清理机制导致。在极端情况下(比如说Memcache被分配的内存不够用了),Memcache会清理一些键值对,即使这些键还没有过期。但是以上两个原因中,时钟不同步的原因很快被排除了。因为从日志分析来看,相当一部分频繁请求是被拦截下来的,如果时钟不同步,应该有相当比例的频繁请求被放过才对。并且跟运维确认,线上的服务器都开启了时钟同步功能,两个服务器的时钟差不会超过10ms。现在看来只有内存清理机制这一个原因了。研究了下Memcache的键清理机制,总结如下:当有新数据需要存储的时候,Memcache会先看数据大小对应的Slab是否有空闲Item,如果有,将数据存入Item,同时更新LRU表。如果没有空闲Item,Memcache会尝试去看对应Slab是否有过期键。如果有,清空过期键,将数据存入新的Item,同时更新LRU表。如果没有过期键,Memcache会尝试申请一个新的Slab,如果申请成功,将数据存入新Slab对应的Item,同时更新LRU表。如果申请失败,并且Memcache配置了强制淘汰机制,会将LRU链表尾部的Item强制清空,并存入新Item,同时更新LRU表。总体看下来,强制淘汰的触发条件还是很苛刻的,并且具体的实现中,LRU链表分为Hot,Warm,Cold三个区域,新加入的数据会在Hot区,等Hot区满了,较早的数据才会被降级到其他区。也就是说,假设存入数据为大小为100B,对应Slab在Memcache服务器上只有一个(一般会有很多),那么此Slab中可用Item数量约为10000个。在这种情况下,如果要触发刚刚存入100ms的未过期键被强制清理的话,需要在100ms内有超过10000条100B左右大小的数据写入Memcache。在测试环境几乎不可能。但是这是一个公共的Memcache,谁知道呢?所以需要排除一下这个情况。诊断本地起一个虚拟机,装个Memcache,顺便打开日志打印(本来的目的是为了看到键淘汰日志)。如果是强制淘汰机制引起,那在只有一个client的本地Memcache上,应该就不会出现这个问题(测试代码可以控制键数量和写入速度),但是不幸的是,在这个空的Memcache上也出现了同样的现象 - 这直接排除了此现象是由强制淘汰机制导致的的可能性。在本地虚拟机启动的Memcache打印的日志中,发现了一个现象:所有时间戳都是类似于这样的格式:1527001620,有点奇怪,比毫秒时间戳短。去查了一下源码,果然被猜中:而rel_time_t的定义为:typedef unsigned int rel_time_t; 毫无疑问,Memcache的时间是用秒计算而不是毫秒。我们使用的客户端接口方法:public boolean add(String key, Object value, Date expiry); 非常具有误导性,因为Date是精确到毫秒的,这也使我们一直理所当然地以为Memcache提供毫秒精度的过期时间校验,然而这是不对的。原因至此,问题的原因就很明朗了,Memcache的过期判断代码如下:最重要的一句是:it->exptime <= current_time  即:过期检测中,当前时间与过期时间相等即被判定为过期。 在这个前提下,当如下情况发生时就会偶现线上的现象。第一个请求,当前时间××××01900 ,计算出的过期时间是××××02900(+1000ms) 存入的过期时间是××××02第二次请求,当前时间××××02000,计算出的过期时间是××××03000(+1000ms) 请求时,服务器判断键过期(键过期时间 ××××02,当前时间××××02) 此次请求add成功。第一次请求和第二次请求仅隔100ms。事实上,如果过期时间设置为1000ms,Memcache能帮我们随机过滤0 1000ms内的请求。频繁请求是否被过滤依赖于最后一次成功请求的时间。总结使用Memcache的add方法做过期判断时需要注意以下三点:Memcache客户端与服务器时间要同步;内存被强制淘汰的可能性极低,除非过期时间比较长,Memcache内存吃紧时,需要关注此问题;过期时间精度为秒。

    注意事项

    本文(Memcache做频率限制引发的问题分析.doc)为本站会员(白大夫)主动上传,三一文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一文库(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    经营许可证编号:宁ICP备18001539号-1

    三一文库
    收起
    展开