API 限流器(二)史上最優秀的訪問頻率控制器的演算法設計詳解
專案程式碼地址: https://github.com/tangaiyun/RedisRateLimiter
演算法的核心思想是用redis中的有序集合來記錄訪問痕跡,集合的key與時間段序號強相關,集合中加入訪問痕跡元素時,score值和member都來自於redis的當前精確到微秒的時間。
舉例如果限制的時間單位為分鐘,限制字首為一個IP(128.9.9.23)訪問頻率,則當前有序集合的key的運算規則如下:
求出當前時間所處的分鐘序號: long index = Long.parseLong(jedis.time().get(0)) / 60;
當前有序集合的key為:“128.9.9.23”+“:”+index
對於任意一次訪問,設當前時間為T,如上圖所示,我們要分別統計A、B 集合中一個統計區間的元素之和,則對於B集合來說,我們需要統計B集合中到目前為止所有的訪問記錄,其實就是B中的所有元素,簡單一點的做法就是 redis.zcount(keyB, Long.MIN_VALUE,Long.MAX_VALUE)。對於A集合,統計的時間起始點為當前時間-單位時間, 命名為Ta,則Ta = T - 單位時間(微秒)
則A中滿足條件的元素個數為 redis.zcount(keyA, Ta, Long.MAX_VALUE).
如果redis.zcount(keyB, Long.MIN_VALUE,Long.MAX_VALUE) + redis.zcount(keyA, Ta, Long.MAX_VALUE) 小於限制次數,則訪問允許通過,並且在當前的集合中呼叫redis.zadd(key, score, member)。
在呼叫redis.zadd方法時,key、score、member的引數取值邏輯如下:
1. key的取值上述已有說明。
2. Score的取值為當前時間,精度到微秒,演算法為:
private long getRedisTime(Jedis jedis) {
List<String> jedisTime = jedis.time();
Long currentSecond = Long.parseLong(jedisTime.get(0));
Long microSecondsElapseInCurrentSecond = Long.parseLong(jedisTime.get(1));
Long currentTimeInMicroSecond = currentSecond * 1000000 + microSecondsElapseInCurrentSecond;
return currentTimeInMicroSecond;
}
因為redis time命令會返回一個包含兩個字串的列表: 第一個字串是當前時間(以 UNIX 時間戳格式表示,是從1970年1月1日(UTC/GMT的午夜)開始所經過的秒數,不考慮閏秒),而第二個字串是當前這一秒鐘已經逝去的微秒數。
3. member呢?我們如何給member引數傳值?我們說了這個是redis管理的有序集合,集合的意思很明確,就是元素不能重複,如果2次訪問時間一致,則訪問次數會被漏記一次。
這裡有個簡單可行的方案,就是把member的值設為score的字串化的表示,為什麼可以這麼做?因為redis訪問實際上是單執行緒執行的,而且jedis.time()方法返回的時間精度為微秒級,每一個jedis.time()呼叫耗時應該會超過1微秒,因此我們可以認為每次jedis.time()返回的時間都是唯一且遞增的。
程式碼還有部分邏輯是控制有序集合的TTL的,簡單講TTL = 2 * 單位時間段 + K。
這個頻率訪問控制器經過筆者多次改善,希望大家多多使用,多提意見。
聯絡方式:
email: [email protected]
weixin: 13851932401
相關推薦
API 限流器(二)史上最優秀的訪問頻率控制器的演算法設計詳解
專案程式碼地址: https://github.com/tangaiyun/RedisRateLimiter演算法的核心思想是用redis中的有序集合來記錄訪問痕跡,集合的key與時間段序號強相關,集合中加入訪問痕跡元素時,score值和member都來自於redis的當前精
API 限流器(一):基於redis的API訪問頻率控制器的實現
在open API日益盛行的今天,API的訪問頻率控制尤為重要。Google開源的Guava中有個類叫RateLimiter,但是此類控制粒度只是秒級別的,沒有提供分鐘,小時,天級別的限制,而且採取的是阻塞的模式,應用起來不是很方便。本人依據Redis的有序集合開發了一個訪
API 限流器(三) 在Spring Cloud 微服務體系中整合RedisRateLimiter
這篇是API限流器這個系列的終章,就是講述如何在Spring Cloud 微服務開發中應用我發明的先進限流器。開篇明義,基本思路如下:1. 定義一個annotation - RedisLimiter2. 在RestController 中有URL Mapping 的方法上
聊聊高併發系統之限流特技(二)(轉)
上一篇《聊聊高併發系統限流特技-1》講了限流演算法、應用級限流、分散式限流;本篇將介紹接入層限流實現。 接入層限流 接入層通常指請求流量的入口,該層的主要目的有:負載均衡、非法請求過濾、請求聚合、快取、降級、限流、 A/B 測試、服務質量監控
分散式系統限流策略(二)
前文中介紹了系統限流的原理和基礎的使用場景,本篇將介紹應用接入層(Nginx)、分散式應用如何限流。 應用接入層限流(Nginx/OpenResty) 接入層通常是指流量的入口,主要的目的有:負載均衡、非法請求過濾、請求聚合、快取、降級、限流、A/B測
查找(一)史上最簡單清晰的紅黑樹解說
ont 演示 detail align article 向上 節點 動態插入 列表 查找(一) 我們使用符號表這個詞來描寫敘述一張抽象的表格。我們會將信息(值)存儲在當中,然後依照指定的鍵來搜索並獲取這些信息。鍵和值的詳細意義取決於不同的應用。 符號表中可能會保
查詢(一)史上最簡單清晰的紅黑樹講解
查詢(一) 我們使用符號表這個詞來描述一張抽象的表格,我們會將資訊(值)儲存在其中,然後按照指定的鍵來搜尋並獲取這些資訊。鍵和值的具體意義取決於不同的應用。 符號表中可能會儲存很多鍵和很多資訊,因此實現一張高效的符號表也是一項很有挑戰性的任務。 我們會用三種經典的資料型
oracle筆記(9)---- 史上最全oracle練習題
13.列出所有員工及直接上級的姓名 Select e.ename, nvl (m.ename, '沒有上級') mname from emp e left join emp m on e.mgr = m.empno 14.列出受僱日期早於其直接上級的所有員工的編號,姓名,部門名稱 select e.empno
史上最全web.xml配置檔案元素詳解(轉載防丟)
web.xml配置檔案常用元素及其意義預覽 1 <web-app> 2 3 <!--定義了WEB應用的名字--> 4 <display-name></display-name> 5
專案管理學習總結(9)——史上最全網際網路八大技術崗位詳解
網際網路技術崗位詳解,涉及到前段開發、後端開發、移動端開發、大資料、專案管理、測試、運維、技術管理等八大領域。架構師每個產品線都有架構師,在技術平臺部門也需要技術平臺的架構師。架構師負責設計系統整體架構,從需求到設計的每個細節都要考慮到,把握整個專案,使設計的專案儘量效率高,
(轉)史上最全人工智慧產品清單(1/3)
「翻譯」史上最全人工智慧產品清單(1/3) 來源:https://zhuanlan.zhihu.com/p/27741586 1 天前 簡評: 這篇文章簡直就是史上最全 B2C 領域 AI 產品名單!部分內容有刪減。作者列舉了很多目前市面上能看到的人工智慧
Intel硬編碼(二):不定長指令、ModR/M與SIB詳解(基於P6微架構)
Intel硬編碼(一):Opcode Map、定長指令與指令字首 我們在Opcode Map中提到定長指令的索引方式,也分析了比較常見的一些定長指令,接著我們就要進行不定長指令的分析了。所謂不定長指得是SIB部分、Displcement、Immediate三部
Android Material Design(一)史上最全的材料設計控制元件大全
主要內容: 本文將要介紹Material design和Support library控制元件,主要包括TextInputLayout、SwitchCompat、SnackBar、FloatingActionButton、Shadows
史上最全的Maven Pom檔案標籤詳解
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
史上最全web.xml配置檔案元素詳解
一、web.xml配置檔案常用元素及其意義預覽 1 <web-app> 2 3 <!--定義了WEB應用的名字--> 4 <display-name></display-name>
史上最全面的Spring Boot配置檔案詳解
Spring Boot在工作中是用到的越來越廣泛了,簡單方便,有了它,效率提高不知道多少倍。Spring Boot配置檔案對Spring Boot來說就是入門和基礎,經常經常會用到,所以寫下做個總結以便日後檢視。 1.配置檔案 當我們構建完Spring Boot專案後,會在resources目錄下給我們一個預
Android AIDL技術實戰專案-音樂播放器(二)-使用retrofit完成音樂API的封裝
使用retrofit完成音樂API的封裝 程式碼結構 1、匯入retrofit相關庫 compile 'com.squareup.retrofit2:retrofit:2.2.0' 2、編寫介面API public interfac
CSS3學習系列之選擇器(二)
計算 選擇器 sky :focus ddr gree for 指定元素 學習 first-child選擇器和last-child選擇器 first-child指定第一個元素。last-child指定最後一個子元素。 例如: <!DOCTYPE html>
機器學習系列——樸素貝葉斯分類器(二)
表示 -h line log ima 條件 code 樸素貝葉斯 spa 貝葉斯定理: 其中: 表示事件B已經發生的前提下,事件A發生的概率,叫做事件B發生下事件A的條件概率。其基本求解公式為:。 機器學習系列——樸素貝葉斯分類器(二)
Java IO流總結(二)-示例
一行 spa ascii 路徑名 指向 每次 字節數 判斷 pri 1.使用文件操作的9大方法完成文件的判斷 判斷文件或目錄是否存在 : exits() 返回值boolean型 * 判斷是否是文件: isFile() boolean * 判斷是否是目錄: isDie