0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

电子工程师 来源:网络整理 作者:工程师李察 2018-09-08 10:18 次阅读

线上服务为了限制用户频繁访问敏感资源,通常会引入一种机制来限制这种访问操作。其中一种常见的方案就是为每个用户的访问做一次时间戳,同一个用户再次访问对应资源时,检查当前时间和已经记录的时间戳的差值 -- 如果此差值小于我们定义的超时时间,此次访问被判定为频繁访问。

我们在某系统的实现中便采用了此种机制,限定用户在 1s内不能连续访问2次,配合Memcache,实现起来非常简单。 核心代码如下:

publicbooleanisOutOfTime(Stringkey){

returnmemCachedClient.add(key,"abc",newDate(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的定义为:

typedefunsignedintrel_time_t;

毫无疑问,Memcache的时间是用秒计算而不是毫秒。我们使用的客户端接口方法:

publicbooleanadd(Stringkey,Objectvalue,Dateexpiry);

非常具有误导性,因为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内存吃紧时,需要关注此问题;

过期时间精度为秒。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 服务器
    +关注

    关注

    12

    文章

    8997

    浏览量

    85134
  • Memcached
    +关注

    关注

    0

    文章

    12

    浏览量

    7003
收藏 人收藏

    评论

    相关推荐

    为什么DCM会限制输出频率

    亲爱的专家:在我的项目中,我需要使用几个频率,例如.2.048M,2.048 * 6M,512k,64k,8k。但我发现DCM限制了输出频率。我想知道为什么限制,我该怎么办。非常感谢
    发表于 05-10 13:43

    memcache源码实验步骤

    memcache源码安装及测试
    发表于 07-01 16:46

    Mac上memcache的安装配置方法

    Mac上memcache的安装配置
    发表于 07-13 15:33

    示波器实现频率分析的方法

    研究领域和行业的最常用的仪器。  但是示波器能够频率分析是近年来才实现的。随着数字信号处理技术的发展、算法技术改进以及集成电路规模不断按摩尔定律的指数级增长等相关条件的成熟,研发工程师就把快速傅立叶
    发表于 09-04 17:28

    memcache主线程和工人线程进行通信的设计实现

    1、memcache多线程模型memcache 是采用单进程多线程模型,内部使用 lib 事件库来处理网络请求。其工作是主线程负责接受的客户端请求,然后轮询模式新任务模式获取连接工作人员的新线
    发表于 06-23 16:46

    Minitab柏拉图分析

    Minitab柏拉图分析:
    发表于 08-17 08:48 52次下载
    Minitab<b class='flag-5'>做</b>柏拉图<b class='flag-5'>分析</b>

    CPU降低频率或保持最大频率(不超频)_如何手动给笔记本CPU限制频率

    处理器最大频率不能随便设置,因为CPU超频时,产生大量热量,容易烧坏设备或出现故障,我就是保持CPU的最大频率,不超率。当CPU满载运行以至于温度飙升时怎么手动给笔记本CPU限制
    发表于 01-15 11:34 17.3w次阅读

    redis和mongodb数据库对比_redis、memcache、mongoDB 对比

    本文是对redis和mongodb数据库对比分析。以及redis、memcache、mongoDB 区别对比。MongoDB和Redis都是NoSQL,采用结构型数据存储。二者在使用场景中,存在一定
    发表于 02-07 08:45 4228次阅读
    redis和mongodb数据库对比_redis、<b class='flag-5'>memcache</b>、mongoDB 对比

    redis、memcache原理对比

    redis、memcache原理对比。Memcached和Redis都能很好的满足解决我们的问题,它们性能都很高,总的来说,可以把Redis理解为是对Memcached的拓展,是更加重量级的实现,提供了更多更强大的功能。
    的头像 发表于 02-09 15:31 3408次阅读
    redis、<b class='flag-5'>memcache</b>原理对比

    Memcache系统中有哪些常用的命令?

    Memcache是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcache
    发表于 04-03 15:09 2次下载

    IBM将内存驱动到uDepot!Memcache的问题

    IBM还使用两个Intel Optane 3D XPoint驱动器(Intel P4800X 375GB)实现了uDepot,并将其与DRAM和闪存Memcache实施进行了比较,再次使用memaslap测试。该公司比较了五种备选的memcache实现
    的头像 发表于 01-18 14:25 3253次阅读
    IBM将内存驱动到uDepot!<b class='flag-5'>Memcache</b>的问题

    ADV7xx限制MCLK输出频率

    ADV7xx限制MCLK输出频率
    发表于 05-16 10:53 5次下载
    ADV7xx<b class='flag-5'>限制</b>MCLK输出<b class='flag-5'>频率</b>

    Memcache系统常用命令讲解

    Memcache系统常用命令讲解(无线电源技术商业计划书)-该文档为Memcache系统常用命令讲解文档,是一份还算不错的参考文档,感兴趣的可以下载看看,,,,,,,,,,,,,,,,
    发表于 09-28 11:27 5次下载
    <b class='flag-5'>Memcache</b>系统常用命令讲解

    windows-redis-memcahed redis和memcache集成快速使用包

    ./oschina_soft/gitee-win-redis-memcache.zip
    发表于 06-23 10:09 2次下载
    windows-redis-memcahed redis和<b class='flag-5'>memcache</b>集成快速使用包

    信号分析设备可分析频率低于磁带频率

    本文主要介绍了信号分析设备的基本原理、类型和应用。特别关注了信号分析设备在分析低于磁带频率的信号时的性能和限制。 引言 信号
    的头像 发表于 06-03 10:52 384次阅读