幼儿饰品瑜伽美体用品微软
投稿投诉
微软创意
爱情通信
用品婚姻
爱好看病
美体软件
影音星座
瑜伽周边
星座办公
饰品塑形
搞笑减肥
幼儿两性
智家潮品

redisson分布式限流RRateLimiter源码分析

  分布式限流单位时间多实例多线程访问次数限制
  接前面聊一聊redisson及优雅实现和说一说springboot优雅集成redisson,简单以源码的方式给大家介绍了redisson的:可重入性、阻塞、续约、红锁、联锁、加锁解锁流程和集成springboot注意点和优雅实现方式。
  接下来在讲一讲平时用的比较多的限流模块RRateLimiter1。简单使用publicstaticvoidmain(String〔〕args)throwsInterruptedException{RRateLimiterrateLimitercreateLimiter();intallThreadNum20;CountDownLatchlatchnewCountDownLatch(allThreadNum);longstartTimeSystem。currentTimeMillis();for(inti0;iallThreadNum;i){newThread((){if(i30)Thread。sleep(1000);booleanpassrateLimiter。tryAcquire();if(pass){log。info(get);}else{log。info(no);}latch。countDown();})。start();}latch。await();System。out。println(Elapsed(System。currentTimeMillis()startTime));}publicstaticRRateLimitercreateLimiter(){ConfigconfignewConfig();config。useSingleServer()。setTimeout(1000000)。setPassword(123456)。setAddress(redis:xxxx:6379);RedissonClientredissonRedisson。create(config);RRateLimiterrateLimiterredisson。getRateLimiter(myRateLimiter3);初始化:PERCLIENT单实例执行,OVERALL全实例执行最大流速每10秒钟产生3个令牌rateLimiter。trySetRate(RateType。OVERALL,3,10,RateIntervalUnit。SECONDS);returnrateLimiter;}复制代码
  实际结果:〔2022102914:32:46。261〕〔INFO〕〔main〕〔〕〔〕RedisTestget〔2022102914:32:46。312〕〔INFO〕〔main〕〔〕〔〕RedisTestget〔2022102914:32:46。358〕〔INFO〕〔main〕〔〕〔〕RedisTestget〔2022102914:32:47。416〕〔INFO〕〔main〕〔〕〔〕RedisTestno〔2022102914:32:47。469〕〔INFO〕〔main〕〔〕〔〕RedisTestno〔2022102914:32:47。517〕〔INFO〕〔main〕〔〕〔〕RedisTestno〔2022102914:32:48。577〕〔INFO〕〔main〕〔〕〔〕RedisTestno〔2022102914:32:48。623〕〔INFO〕〔main〕〔〕〔〕RedisTestno复制代码2。实现限流redisson使用了哪些redis数据结构Hash结构限流器结构:参数rate代表速率参数interval代表多少时间内产生的令牌参数type代表单机还是集群ZSET结构记录获取令牌的时间戳,用于时间对比。16670251663122022102914:32:4616670251662622022102914:32:4616670251662152022102914:32:46
  3。String结构记录的是当前令牌桶中的令牌数【很明显被我用完了现在是0】
  3。超过10s,我再次获取一个令牌,数据结构发生的变化ZSET结构。新生成一个ZSET结构,存放获取令牌的时间戳
  String结构当前令牌桶还有2个令牌
  4。源码浅析RRateLimiterrateLimiterredisson。getRateLimiter(myRateLimiter3);初始化最大流速每10秒钟产生3个令牌rateLimiter。trySetRate(RateType。PERCLIENT,3,10,RateIntervalUnit。SECONDS);复制代码
  初始化定义没有什么好讲的,就是创建HASH结构
  主要还是讲讲:rateLimiter。tryAcquire()privateTRFutureTtryAcquireAsync(RedisCommandTcommand,Longvalue){returnthis。commandExecutor。evalWriteAsync(this。getName(),LongCodec。INSTANCE,command,localrateredis。call(hget,KEYS〔1〕,rate);localintervalredis。call(hget,KEYS〔1〕,interval);localtyperedis。call(hget,KEYS〔1〕,type);assert(ratefalseandintervalfalseandtypefalse,RateLimiterisnotinitialized)localvalueNameKEYS〔2〕;localpermitsNameKEYS〔4〕;iftype1thenvalueNameKEYS〔3〕;permitsNameKEYS〔5〕;end;localcurrentValueredis。call(get,valueName);ifcurrentValuefalsethenlocalexpiredValuesredis。call(zrangebyscore,permitsName,0,tonumber(ARGV〔2〕)interval);localreleased0;fori,vinipairs(expiredValues)dolocalrandom,permitsstruct。unpack(fI,v);releasedreleasedpermits;end;ifreleased0thenredis。call(zrem,permitsName,unpack(expiredValues));currentValuetonumber(currentValue)released;redis。call(set,valueName,currentValue);end;iftonumber(currentValue)tonumber(ARGV〔1〕)thenlocalnearestredis。call(zrangebyscore,permitsName,(。。(tonumber(ARGV〔2〕)interval),tonumber(ARGV〔2〕),withscores,limit,0,1);localrandom,permitsstruct。unpack(fI,nearest〔1〕);returntonumber(nearest〔2〕)(tonumber(ARGV〔2〕)interval);elseredis。call(zadd,permitsName,ARGV〔2〕,struct。pack(fI,ARGV〔3〕,ARGV〔1〕));redis。call(decrby,valueName,ARGV〔1〕);returnnil;end;elseassert(tonumber(rate)tonumber(ARGV〔1〕),Requestedpermitsamountcouldnotexceeddefinedrate);redis。call(set,valueName,rate);redis。call(zadd,permitsName,ARGV〔2〕,struct。pack(fI,ARGV〔3〕,ARGV〔1〕));redis。call(decrby,valueName,ARGV〔1〕);returnnil;end;,Arrays。asList(this。getName(),this。getValueName(),this。getClientValueName(),this。getPermitsName(),this。getClientPermitsName()),newObject〔〕{value,System。currentTimeMillis(),ThreadLocalRandom。current()。nextLong()});}复制代码
  主要就是这段lua代码,下面我详细过一下
  作者目前用的3。16。3版本,刚好遇见redisson的bug,见3197,请大家用最新版本,以下为修复后解析。获取hash结构的速率localrateredis。call(hget,KEYS〔1〕,rate)获取hash结构的时间区间(ms)localintervalredis。call(hget,KEYS〔1〕,interval)获取hash结构的时间类型localtyperedis。call(hget,KEYS〔1〕,type)判断是否初始化限流结构assert(ratefalseandintervalfalseandtypefalse,RateLimiterisnotinitialized){name}:valuestring结构,这个key记录的是当前令牌桶中的令牌数localvalueNameKEYS〔2〕{name}:permitszset结构,记录了请求的令牌数,score则为请求的时间戳localpermitsNameKEYS〔4〕单机限流才会用到,集群模式不用关注iftype1thenvalueNameKEYS〔3〕permitsNameKEYS〔5〕end生产速率rate必须比请求的令牌数大assert(tonumber(rate)tonumber(ARGV〔1〕),Requestedpermitsamountcouldnotexceeddefinedrate)初始化RateLimiter并不会初始化stirng结构,因此第一次获取这里currentValue是nulllocalcurrentValueredis。call(get,valueName)ifcurrentValuefalsethen第二次获取令牌执行获取zset结构:统计之前的请求令牌数范围是0(第二次请求时间戳令牌生产的时间)localexpiredValuesredis。call(zrangebyscore,permitsName,0,tonumber(ARGV〔2〕)interval)localreleased0lua迭代器,遍历expiredValues,如果有值,那么released等于之前所有请求的令牌数之和,表示应该释放多少令牌fori,vinipairs(expiredValues)do获取请求数permitslocalrandom,permitsstruct。unpack(fI,v)releasedreleasedpermitsend之前的请求令牌数0,例如10s产生3个令牌,现在超过10s了,重置周期并计算剩余令牌数ifreleased0then移除zset中所有元素【要求是同一个限流器permitsName,不然就移除不了,尴尬】redis。call(zrem,permitsName,unpack(expiredValues))currentValuetonumber(currentValue)released更新string结构:剩下令牌数释放令牌数redis。call(set,valueName,currentValue)end如果当前令牌数请求的令牌数iftonumber(currentValue)tonumber(ARGV〔1〕)then从zset中找到距离当前时间最近的那个请求,也就是上一次放进去的请求信息localnearestredis。call(zrangebyscore,permitsName,(。。(tonumber(ARGV〔2〕)interval),tonumber(ARGV〔2〕),withscores,limit,0,1);localrandom,permitsstruct。unpack(fI,nearest〔1〕)返回上一次请求的时间戳(当前时间戳令牌生成的时间间隔)这个值表示还需要多久才能生产出足够的令牌returntonumber(nearest〔2〕)(tonumber(ARGV〔2〕)interval)else如果当前令牌数请求的令牌数,表示令牌够多,更新zset更新zset结构redis。call(zadd,permitsName,ARGV〔2〕,struct。pack(fI,ARGV〔3〕,ARGV〔1〕))更新Stringt结构,减少一个剩下的令牌数redis。call(decrby,valueName,ARGV〔1〕)returnnilendelse汀雨笔记初始化Stringt结构,当前限流器的令牌数redis。call(set,valueName,rate)汀雨笔记初始化zset结构redis。call(zadd,permitsName,ARGV〔2〕,struct。pack(fI,ARGV〔3〕,ARGV〔1〕))struct。pack第一个参数表示格式字符串,f是浮点数、I是长整数。所以这个格式字符串表示的是把一个浮点数和长整数拼起来的结构体,ARGV〔2〕就是请求时间戳,ARGV〔1〕是请求的令牌数,统计会用到,ARGV〔3〕是当前时间戳为种子的随机数,具体用处还不知道,知道的网友可以留言更新Stringt结构,因为这是获取令牌操作,减掉一个令牌【本文作者认为,这里可以直接初始化string结构,值为rate1】redis。call(decrby,valueName,ARGV〔1〕)returnnilend复制代码
  这段lua代码也并不复杂,令牌桶的数量主要是通过时间窗口来控制,判断上一个请求是否超过了令牌生产周期。
  留下一个疑问?移除zset中所有元素【要求是同一个限流器permitsName,不然就移除不了,尴尬】redis。call(zrem,permitsName,unpack(expiredValues))复制代码
  我自己在本地测试,只要超过10s,permitsName就不一样,这就导致了这部分数据是不能移除的,就产生了冗余数据,从前面的截图也可以看出,是新生成了一个zset数据结构。
  相当于直接走到了这一步:更新zset结构redis。call(zadd,permitsName,ARGV〔2〕,struct。pack(fI,ARGV〔3〕,ARGV〔1〕))复制代码
  至于为什么会产生这样的结果,会的小伙伴可以留言,或者过段时间我提个issue。
  及时当勉励岁月不待人
  能看到这里的人呀,都是菁英。
  非常感谢

西藏天然鱼库鱼量庞大,或达2亿公斤?人们怎么不进行打捞?无人问津的西藏湖鱼西藏有的不止是风景,还有十分吸引人的人文气息,藏传佛教、民间风俗、地方小吃、建筑构造等等,这些不一样的风土人情并不常见。哪怕是跋山涉水,开车上千公里观看……4。8万名安卓开发者受益,谷歌同意提供9000万美元以结束诉Alphabet旗下谷歌(Google)同意设立一个9000万美元的基金,作为与安卓(Android)应用开发者就其收入发生法律纠纷的拟议解决方案的一部分,以避免这家搜索巨头所……是你在吃槟榔,还是槟榔在吃你?槟榔带来的毁容与癌症40岁的张先生自从前年换了一份工作以后,就爱上了吃槟榔。张先生有着20多年的烟龄,他从上学时就开始抽烟,烟瘾非常大,但是新工作所在的办公楼禁止吸烟。吸烟需要坐20多层电梯……儿子和女儿的差别到底在哪里?这30张图太真实了本文转载于凯叔讲故事(ID:kaishujianggushi)文茱莉漫画怪怪最后曾听过有人吐槽:小时候乖巧听话的是女孩,上学了成绩好的是女孩,班长和课代表是女孩,作……经常腹胀的人不要乱吃,如果是这四种食物,就要少吃腹胀是生活中很常见的症状。虽然不是特别严重的症状,但是会给生活带来很多不便,这可能是一种疾病的症状,要引起重视。在找出腹胀原因的同时,更要注意饮食,少吃会让腹胀更严重的食物,这……留一天时间给束河古镇,享受浮生半日闲过一枯涧石桥,西瞻中海,柳暗波萦,有大聚落临其上,是为十和院。《徐霞客游记》束河(十和)纳西语称绍坞,意为高峰之下的村寨。来丽江,一定要留一天的时间给束河。这里永远……早上洗头和晚上洗头,哪个健康?劝你早些了解洗头发是很平常的一件事情,有些人几乎天天都会洗洗头,因为他们无法忍受头发上的灰尘和油垢。但是也有人觉得频繁洗头对头发不好,会把头皮保护层洗掉,久而久之,可能会有秃顶的风险。……克卜勒太空望远镜发现最遥远的系外行星天文学家从已退役的克卜勒太空望远镜于2016年收集的数据中,发现了一颗系外行星,距离地球约17,000光年,是之前克卜勒太空望远镜观测记录的两倍,质量和木星相似,轨道距离也几乎……走进内蒙夕阳下的草原跟着边凡看世界《走进内蒙》傍晚时分,正是夕阳西下的时候,内蒙古大草原上笼罩着金色的寂静,远处山峦披上晚霞的彩衣,那天边牛乳般洁白的云朵,也变得如火焰一般鲜红,草浪平息了,牧归的……让骁龙8冷静下来,iQOONeo6将采用高导热稀土散热材料博主数码闲聊站在一份爆料中提到,蓝厂iQOONeo5的正统迭代马上也要来了,就在4月上旬。旗舰机的游戏体验继续下放,E4直屏双压感口碑很好的稀土散热一起堆了,手游党可等近……让中国儿童爱上刷牙,远离龋齿,usmile做对了哪些事?我发现我家孩子也有龋齿问题了。在开学之初,有不少家长都反映现在儿童龋齿问题越来越普遍。据《第四次全国口腔健康流行病学调查报告》显示,全国5岁儿童乳牙患龋率为70。9,比起……孙杨沉默式直播惹争议,被吐槽丢人,冠军就不能为生存努力吗?近日,世界冠军孙杨在直播带货中选择沉默互动引起网友热议。作为运动员,在赛场上孙杨拿下诸多金牌,但如今却现身带货直播间,网友不仅认为跌价,还调侃他的直播方式。在最新一场直播……
45月,社保养老金工资迎来新调整,退休和在职人员受益不少点击上方蓝色按钮,即可收听全文!45月,社保、养老金、工资迎来新调整,退休和在职人员受益不少呢。2023年是一个充满变化的一年,不仅疫情得到了有效控制,经济也逐步恢……邓紫棋的心酸情史,苦等林宥嘉9年等来一首说谎,出歌内涵华晨宇邓紫棋在4月1日愚人节这天,发布了一首名为《超能力》的新歌。这首歌由邓紫棋亲自作词作曲,不过这些都不是重点。重点是有网友发现,这首歌疑似在DISS邓紫棋的昔日绯闻男……SpaceX员工实名举报老板马斯克,五人被原地解雇来源:机器之心,谢谢面对SpaceX员工的呼吁,马斯克反应很快:至少五人立刻被解雇。编辑感知芯视界周四,关注马斯克消息的人都知道发生了一件事:他被几位Spac……开普勒通信公司融资9200万美元,计划构建光学数据中继网络据Spacenews4月13日报道,加拿大小型卫星运营商开普勒通信公司(KeplerCommunications)表示,已经筹集了9200万美元,用于明年开始部署一个光学数据中……只要不臭,都能继续用?后续来了全市门店停业!被称作烤鱼界头牌的半天妖摊上事了据报道今年2月下旬至3月上旬有记者在安徽合肥两家半天妖门店卧底暗访发现后厨使用的鱼类食材都是冷冻产品很多鱼解……五角大楼太阳系或有外星飞船向地球发探测器美国五角大楼不明飞行物研究办公室主任在上周分享的一份报告草案中指出,我们的太阳系中可能存在外星航空母机,并向地球发射微型探测器。美国国防部全域异常解决办公室(AARO)主……移动挖电信墙角19元白给1000M宽带,老用户心里笑开花前几年,我所处的江西移动曾搞过免费送100M宽带的活动,最早就连8元保号套餐都能参与(后来不行了,需要39元或49元以上套餐),硬生生挖了一波电信的墙角。如今,广州移动又借着携……智慧园区数字化平台工业云平台智能工厂总体规划与建设方案原文《智慧园区数字化平台、工业云平台、智能工厂总体规划与建设方案》PPT格式,共50页。主要建设内容:智慧园区数字化平台总体规划、智慧园区工业云平台建设方案、园区智慧办公平台建……可以改变人生的20个认知文章念念与光编辑念念与光图片网络1。很多事不要只站在当时当地的一个时空维度去思考和看待,跳出来看,你会有新的收获。2。行动是治愈一切的良药,包括焦虑、自……青岛崂山怎么玩?一篇教你玩转崂山巍巍山脉自海边拔地而起,松涛与波涛交相辉映,千年道观自林中露出一角,香火混着炊烟袅袅升上天空。这,便是崂山。去崂山看什么山海一色的迤逦风光作为中国海岸线第一高峰,在这里既……鸭肉是癌症加速器吗?医生不想病情恶化,对这7物说不导语:饮食问题一直是人们非常重视的问题,众所周知,很多疾病皆因从口而入。一说起癌症,很多人会谈癌色变,认为只要患了癌症,生存时间大大缩短,再加上即使现如今的医疗技术非常的……玉米须能让结石排出,是真的吗?大家好我是陈医生,最近有朋友问我:陈医生,听说玉米须能让结石排出,是真的吗?答:确实是真的,多喝玉米须水确实能有利于结石排出。没错,就是每个玉米上都有的那个须须。《……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网