[{"data":1,"prerenderedAt":2045},["ShallowReactive",2],{"post-\u002Fposts\u002Fhigh-concurrency-rate-limiting-algorithms":3,"all-posts-nav":1773},{"id":4,"title":5,"body":6,"categories":1757,"date":1759,"description":1760,"draft":1761,"extension":1762,"hidden":1761,"meta":1763,"navigation":334,"path":1764,"published":1761,"seo":1765,"stem":1766,"tags":1767,"__hash__":1772},"posts\u002Fposts\u002Fhigh-concurrency-rate-limiting-algorithms.md","高并发限流算法：固定窗口、滑动窗口、漏桶与令牌桶",{"type":7,"value":8,"toc":1741},"minimark",[9,13,16,22,30,34,37,56,59,70,73,90,93,96,175,178,198,201,204,207,210,216,219,225,228,464,467,478,481,486,489,495,498,501,506,509,512,514,520,523,714,716,724,726,737,740,754,757,760,762,768,771,777,780,782,793,795,803,806,811,814,820,826,829,835,837,848,850,861,863,876,878,883,886,889,891,897,900,914,917,920,926,929,931,1164,1166,1180,1182,1190,1192,1206,1208,1213,1216,1219,1225,1227,1241,1244,1371,1374,1376,1381,1384,1387,1390,1393,1396,1468,1471,1477,1480,1491,1494,1511,1514,1520,1523,1526,1529,1549,1552,1558,1561,1565,1568,1606,1609,1614,1617,1620,1687,1690,1695,1698,1701,1707,1710,1713,1716,1722,1725,1728,1734,1737],[10,11,12],"p",{},"限流是高并发系统里最常见的稳定性手段之一。",[10,14,15],{},"一句话解释：",[17,18,19],"blockquote",{},[10,20,21],{},"限流就是在流量超过系统承载能力时，主动拒绝或延迟一部分请求，保护核心服务不被打爆。",[10,23,24,25,29],{},"它解决的问题不是“让系统处理无限流量”，而是",[26,27,28],"strong",{},"让系统在流量过载时有边界、有秩序地退化","。",[31,32,33],"h2",{"id":33},"为什么需要限流",[10,35,36],{},"一个服务能承受的资源是有限的：",[38,39,40,44,47,50,53],"ul",{},[41,42,43],"li",{},"CPU 有上限。",[41,45,46],{},"线程池有上限。",[41,48,49],{},"数据库连接数有上限。",[41,51,52],{},"Redis \u002F MQ \u002F 下游 RPC 都有上限。",[41,54,55],{},"模型推理服务的 GPU 资源也有上限。",[10,57,58],{},"如果没有限流，高峰流量可能会造成连锁反应：",[60,61,67],"pre",{"className":62,"code":64,"language":65,"meta":66},[63],"language-text","请求量暴涨\n  -> 线程池被打满\n  -> 请求排队变长\n  -> 超时增加\n  -> 调用方重试\n  -> 流量进一步放大\n  -> 下游服务雪崩\n","text","",[68,69,64],"code",{"__ignoreMap":66},[10,71,72],{},"所以限流的目标是：",[38,74,75,78,81,84,87],{},[41,76,77],{},"保护本服务。",[41,79,80],{},"保护下游服务。",[41,82,83],{},"保证核心链路优先可用。",[41,85,86],{},"避免重试风暴。",[41,88,89],{},"在过载时尽早失败，而不是让请求一直排队到超时。",[31,91,92],{"id":92},"限流限的是什么",[10,94,95],{},"常见限流维度：",[97,98,99,112],"table",{},[100,101,102],"thead",{},[103,104,105,109],"tr",{},[106,107,108],"th",{},"维度",[106,110,111],{},"例子",[113,114,115,124,135,143,151,159,167],"tbody",{},[103,116,117,121],{},[118,119,120],"td",{},"全局限流",[118,122,123],{},"整个服务最多 10 万 QPS",[103,125,126,129],{},[118,127,128],{},"接口限流",[118,130,131,134],{},[68,132,133],{},"\u002Frecommend\u002Ffeed"," 最多 2 万 QPS",[103,136,137,140],{},[118,138,139],{},"用户限流",[118,141,142],{},"单用户每秒最多 10 次请求",[103,144,145,148],{},[118,146,147],{},"IP 限流",[118,149,150],{},"单 IP 每分钟最多 100 次请求",[103,152,153,156],{},[118,154,155],{},"租户限流",[118,157,158],{},"每个租户独立配额",[103,160,161,164],{},[118,162,163],{},"下游限流",[118,165,166],{},"调用某个 RPC 最多 5000 QPS",[103,168,169,172],{},[118,170,171],{},"并发数限流",[118,173,174],{},"同时最多处理 1000 个请求",[10,176,177],{},"限流不一定只按 QPS，也可以按：",[38,179,180,183,186,189,192,195],{},[41,181,182],{},"QPS \u002F RPS。",[41,184,185],{},"并发请求数。",[41,187,188],{},"请求成本。",[41,190,191],{},"Token 数。",[41,193,194],{},"数据库连接数。",[41,196,197],{},"GPU 推理 batch 数。",[10,199,200],{},"比如 LLM 服务经常按 token 限流，而不是只按请求数限流，因为一个请求可能生成 100 token，也可能生成 10000 token。",[31,202,203],{"id":203},"固定窗口计数器",[10,205,206],{},"固定窗口是最简单的限流算法。",[10,208,209],{},"思路：",[60,211,214],{"className":212,"code":213,"language":65,"meta":66},[63],"把时间切成固定窗口\n每个窗口内维护一个计数器\n请求来了计数 +1\n如果计数超过阈值，就拒绝\n窗口结束后计数清零\n",[68,215,213],{"__ignoreMap":66},[10,217,218],{},"例如限制每秒最多 100 个请求：",[60,220,223],{"className":221,"code":222,"language":65,"meta":66},[63],"第 1 秒：允许 100 个\n第 2 秒：允许 100 个\n第 3 秒：允许 100 个\n",[68,224,222],{"__ignoreMap":66},[10,226,227],{},"伪代码：",[60,229,233],{"className":230,"code":231,"language":232,"meta":66,"style":66},"language-python shiki shiki-themes github-dark-dimmed github-light","class FixedWindowLimiter:\n    def __init__(self, limit: int, window_seconds: int):\n        self.limit = limit\n        self.window_seconds = window_seconds\n        self.window_start = 0\n        self.count = 0\n\n    def allow(self, now: int) -> bool:\n        if now - self.window_start >= self.window_seconds:\n            self.window_start = now\n            self.count = 0\n\n        if self.count >= self.limit:\n            return False\n\n        self.count += 1\n        return True\n","python",[68,234,235,252,276,291,304,317,329,336,358,383,396,407,412,428,437,442,455],{"__ignoreMap":66},[236,237,240,244,248],"span",{"class":238,"line":239},"line",1,[236,241,243],{"class":242},"s6PUj","class",[236,245,247],{"class":246},"sqRhv"," FixedWindowLimiter",[236,249,251],{"class":250},"ssh_m",":\n",[236,253,255,258,262,265,268,271,273],{"class":238,"line":254},2,[236,256,257],{"class":242},"    def",[236,259,261],{"class":260},"swcJU"," __init__",[236,263,264],{"class":250},"(self, limit: ",[236,266,267],{"class":260},"int",[236,269,270],{"class":250},", window_seconds: ",[236,272,267],{"class":260},[236,274,275],{"class":250},"):\n",[236,277,279,282,285,288],{"class":238,"line":278},3,[236,280,281],{"class":260},"        self",[236,283,284],{"class":250},".limit ",[236,286,287],{"class":242},"=",[236,289,290],{"class":250}," limit\n",[236,292,294,296,299,301],{"class":238,"line":293},4,[236,295,281],{"class":260},[236,297,298],{"class":250},".window_seconds ",[236,300,287],{"class":242},[236,302,303],{"class":250}," window_seconds\n",[236,305,307,309,312,314],{"class":238,"line":306},5,[236,308,281],{"class":260},[236,310,311],{"class":250},".window_start ",[236,313,287],{"class":242},[236,315,316],{"class":260}," 0\n",[236,318,320,322,325,327],{"class":238,"line":319},6,[236,321,281],{"class":260},[236,323,324],{"class":250},".count ",[236,326,287],{"class":242},[236,328,316],{"class":260},[236,330,332],{"class":238,"line":331},7,[236,333,335],{"emptyLinePlaceholder":334},true,"\n",[236,337,339,341,345,348,350,353,356],{"class":238,"line":338},8,[236,340,257],{"class":242},[236,342,344],{"class":343},"saVmf"," allow",[236,346,347],{"class":250},"(self, now: ",[236,349,267],{"class":260},[236,351,352],{"class":250},") -> ",[236,354,355],{"class":260},"bool",[236,357,251],{"class":250},[236,359,361,364,367,370,373,375,378,380],{"class":238,"line":360},9,[236,362,363],{"class":242},"        if",[236,365,366],{"class":250}," now ",[236,368,369],{"class":242},"-",[236,371,372],{"class":260}," self",[236,374,311],{"class":250},[236,376,377],{"class":242},">=",[236,379,372],{"class":260},[236,381,382],{"class":250},".window_seconds:\n",[236,384,386,389,391,393],{"class":238,"line":385},10,[236,387,388],{"class":260},"            self",[236,390,311],{"class":250},[236,392,287],{"class":242},[236,394,395],{"class":250}," now\n",[236,397,399,401,403,405],{"class":238,"line":398},11,[236,400,388],{"class":260},[236,402,324],{"class":250},[236,404,287],{"class":242},[236,406,316],{"class":260},[236,408,410],{"class":238,"line":409},12,[236,411,335],{"emptyLinePlaceholder":334},[236,413,415,417,419,421,423,425],{"class":238,"line":414},13,[236,416,363],{"class":242},[236,418,372],{"class":260},[236,420,324],{"class":250},[236,422,377],{"class":242},[236,424,372],{"class":260},[236,426,427],{"class":250},".limit:\n",[236,429,431,434],{"class":238,"line":430},14,[236,432,433],{"class":242},"            return",[236,435,436],{"class":260}," False\n",[236,438,440],{"class":238,"line":439},15,[236,441,335],{"emptyLinePlaceholder":334},[236,443,445,447,449,452],{"class":238,"line":444},16,[236,446,281],{"class":260},[236,448,324],{"class":250},[236,450,451],{"class":242},"+=",[236,453,454],{"class":260}," 1\n",[236,456,458,461],{"class":238,"line":457},17,[236,459,460],{"class":242},"        return",[236,462,463],{"class":260}," True\n",[10,465,466],{},"优点：",[38,468,469,472,475],{},[41,470,471],{},"实现简单。",[41,473,474],{},"内存占用低。",[41,476,477],{},"适合粗粒度限流。",[10,479,480],{},"缺点：",[38,482,483],{},[41,484,485],{},"有窗口边界突刺问题。",[10,487,488],{},"比如限制 1 秒 100 次：",[60,490,493],{"className":491,"code":492,"language":65,"meta":66},[63],"00:00:00.900 - 00:00:01.000 来了 100 次\n00:00:01.000 - 00:00:01.100 又来了 100 次\n",[68,494,492],{"__ignoreMap":66},[10,496,497],{},"从固定窗口看，每秒都没有超过 100 次；但从真实 200ms 时间片看，系统承受了 200 次请求，瞬时流量翻倍。",[10,499,500],{},"面试一句话：",[17,502,503],{},[10,504,505],{},"固定窗口实现简单，但窗口边界可能出现两倍流量突刺，因此适合简单限流，不适合对流量平滑性要求高的核心链路。",[31,507,508],{"id":508},"滑动日志",[10,510,511],{},"滑动日志是更精确的滑动窗口。",[10,513,209],{},[60,515,518],{"className":516,"code":517,"language":65,"meta":66},[63],"记录每次请求的时间戳\n请求到来时，删除窗口外的旧时间戳\n如果窗口内时间戳数量小于阈值，则允许\n否则拒绝\n",[68,519,517],{"__ignoreMap":66},[10,521,522],{},"例如限制最近 1 秒最多 100 次请求：",[60,524,526],{"className":230,"code":525,"language":232,"meta":66,"style":66},"from collections import deque\n\nclass SlidingLogLimiter:\n    def __init__(self, limit: int, window_seconds: float):\n        self.limit = limit\n        self.window_seconds = window_seconds\n        self.requests = deque()\n\n    def allow(self, now: float) -> bool:\n        while self.requests and self.requests[0] \u003C= now - self.window_seconds:\n            self.requests.popleft()\n\n        if len(self.requests) >= self.limit:\n            return False\n\n        self.requests.append(now)\n        return True\n",[68,527,528,542,546,555,572,582,592,604,608,624,658,665,669,691,697,701,708],{"__ignoreMap":66},[236,529,530,533,536,539],{"class":238,"line":239},[236,531,532],{"class":242},"from",[236,534,535],{"class":250}," collections ",[236,537,538],{"class":242},"import",[236,540,541],{"class":250}," deque\n",[236,543,544],{"class":238,"line":254},[236,545,335],{"emptyLinePlaceholder":334},[236,547,548,550,553],{"class":238,"line":278},[236,549,243],{"class":242},[236,551,552],{"class":246}," SlidingLogLimiter",[236,554,251],{"class":250},[236,556,557,559,561,563,565,567,570],{"class":238,"line":293},[236,558,257],{"class":242},[236,560,261],{"class":260},[236,562,264],{"class":250},[236,564,267],{"class":260},[236,566,270],{"class":250},[236,568,569],{"class":260},"float",[236,571,275],{"class":250},[236,573,574,576,578,580],{"class":238,"line":306},[236,575,281],{"class":260},[236,577,284],{"class":250},[236,579,287],{"class":242},[236,581,290],{"class":250},[236,583,584,586,588,590],{"class":238,"line":319},[236,585,281],{"class":260},[236,587,298],{"class":250},[236,589,287],{"class":242},[236,591,303],{"class":250},[236,593,594,596,599,601],{"class":238,"line":331},[236,595,281],{"class":260},[236,597,598],{"class":250},".requests ",[236,600,287],{"class":242},[236,602,603],{"class":250}," deque()\n",[236,605,606],{"class":238,"line":338},[236,607,335],{"emptyLinePlaceholder":334},[236,609,610,612,614,616,618,620,622],{"class":238,"line":360},[236,611,257],{"class":242},[236,613,344],{"class":343},[236,615,347],{"class":250},[236,617,569],{"class":260},[236,619,352],{"class":250},[236,621,355],{"class":260},[236,623,251],{"class":250},[236,625,626,629,631,633,636,638,641,644,647,650,652,654,656],{"class":238,"line":385},[236,627,628],{"class":242},"        while",[236,630,372],{"class":260},[236,632,598],{"class":250},[236,634,635],{"class":242},"and",[236,637,372],{"class":260},[236,639,640],{"class":250},".requests[",[236,642,643],{"class":260},"0",[236,645,646],{"class":250},"] ",[236,648,649],{"class":242},"\u003C=",[236,651,366],{"class":250},[236,653,369],{"class":242},[236,655,372],{"class":260},[236,657,382],{"class":250},[236,659,660,662],{"class":238,"line":398},[236,661,388],{"class":260},[236,663,664],{"class":250},".requests.popleft()\n",[236,666,667],{"class":238,"line":409},[236,668,335],{"emptyLinePlaceholder":334},[236,670,671,673,676,679,682,685,687,689],{"class":238,"line":414},[236,672,363],{"class":242},[236,674,675],{"class":260}," len",[236,677,678],{"class":250},"(",[236,680,681],{"class":260},"self",[236,683,684],{"class":250},".requests) ",[236,686,377],{"class":242},[236,688,372],{"class":260},[236,690,427],{"class":250},[236,692,693,695],{"class":238,"line":430},[236,694,433],{"class":242},[236,696,436],{"class":260},[236,698,699],{"class":238,"line":439},[236,700,335],{"emptyLinePlaceholder":334},[236,702,703,705],{"class":238,"line":444},[236,704,281],{"class":260},[236,706,707],{"class":250},".requests.append(now)\n",[236,709,710,712],{"class":238,"line":457},[236,711,460],{"class":242},[236,713,463],{"class":260},[10,715,466],{},[38,717,718,721],{},[41,719,720],{},"精度高。",[41,722,723],{},"没有固定窗口边界突刺问题。",[10,725,480],{},[38,727,728,731,734],{},[41,729,730],{},"每个请求都要存时间戳。",[41,732,733],{},"高并发下内存开销大。",[41,735,736],{},"清理旧时间戳有额外开销。",[10,738,739],{},"适合：",[38,741,742,745,748,751],{},[41,743,744],{},"单用户限流。",[41,746,747],{},"管理后台限流。",[41,749,750],{},"安全风控类限流。",[41,752,753],{},"QPS 不大但精度要求高的场景。",[31,755,756],{"id":756},"滑动窗口计数器",[10,758,759],{},"滑动窗口计数器是固定窗口和滑动日志之间的折中方案。",[10,761,209],{},[60,763,766],{"className":764,"code":765,"language":65,"meta":66},[63],"把一个大窗口拆成多个小窗口\n每个小窗口维护一个计数\n请求到来时统计最近 N 个小窗口的总和\n超过阈值则拒绝\n",[68,767,765],{"__ignoreMap":66},[10,769,770],{},"例如限制最近 1 分钟最多 6000 次，可以把 1 分钟拆成 60 个 1 秒小窗口：",[60,772,775],{"className":773,"code":774,"language":65,"meta":66},[63],"window = 60s\nbucket = 1s\nlimit = 6000\n",[68,776,774],{"__ignoreMap":66},[10,778,779],{},"每次请求只需要统计最近 60 个 bucket 的总和。",[10,781,466],{},[38,783,784,787,790],{},[41,785,786],{},"比固定窗口平滑。",[41,788,789],{},"比滑动日志省内存。",[41,791,792],{},"工程中很常用。",[10,794,480],{},[38,796,797,800],{},[41,798,799],{},"精度取决于小窗口大小。",[41,801,802],{},"小窗口越小越精确，但维护成本越高。",[10,804,805],{},"面试可以这样讲：",[17,807,808],{},[10,809,810],{},"滑动窗口计数器通过把大窗口拆成多个小桶，统计最近一段时间内的请求总数。它比固定窗口更平滑，又比滑动日志更省内存，是实际系统里常用的折中方案。",[31,812,813],{"id":813},"漏桶算法",[10,815,816,817,29],{},"漏桶算法的核心思想是：",[26,818,819],{},"请求先进桶，再以固定速率流出",[60,821,824],{"className":822,"code":823,"language":65,"meta":66},[63],"请求进入桶\n  -> 桶满则拒绝\n  -> 桶不满则排队\n  -> 系统按固定速率处理请求\n",[68,825,823],{"__ignoreMap":66},[10,827,828],{},"形象理解：",[60,830,833],{"className":831,"code":832,"language":65,"meta":66},[63],"水龙头往桶里倒水：请求进入\n桶底小孔匀速漏水：系统处理\n桶满溢出：请求被拒绝\n",[68,834,832],{"__ignoreMap":66},[10,836,466],{},[38,838,839,842,845],{},[41,840,841],{},"输出速率稳定。",[41,843,844],{},"对下游很友好。",[41,846,847],{},"适合削峰填谷。",[10,849,480],{},[38,851,852,855,858],{},[41,853,854],{},"不能很好支持突发流量。",[41,856,857],{},"请求可能排队，增加延迟。",[41,859,860],{},"如果队列太长，用户体验会变差。",[10,862,739],{},[38,864,865,867,870,873],{},[41,866,80],{},[41,868,869],{},"写数据库。",[41,871,872],{},"写消息队列。",[41,874,875],{},"发送短信、邮件、推送等需要稳定速率的场景。",[10,877,500],{},[17,879,880],{},[10,881,882],{},"漏桶算法强调稳定输出，不管入口流量多突发，出口都按固定速率处理；它适合保护下游，但对突发流量不够友好。",[31,884,885],{"id":885},"令牌桶算法",[10,887,888],{},"令牌桶是工程中最常用的限流算法之一。",[10,890,209],{},[60,892,895],{"className":893,"code":894,"language":65,"meta":66},[63],"系统按固定速率生成令牌\n令牌放入桶中，桶满则丢弃多余令牌\n请求到来时先拿令牌\n拿到令牌就允许\n拿不到令牌就拒绝或等待\n",[68,896,894],{"__ignoreMap":66},[10,898,899],{},"令牌桶和漏桶最大的区别：",[38,901,902,908],{},[41,903,904,905,29],{},"漏桶限制的是",[26,906,907],{},"请求流出的速度",[41,909,910,911,29],{},"令牌桶限制的是",[26,912,913],{},"请求进入时必须拿到令牌",[10,915,916],{},"令牌桶允许一定程度的突发。",[10,918,919],{},"例如：",[60,921,924],{"className":922,"code":923,"language":65,"meta":66},[63],"令牌生成速率：100 个 \u002F 秒\n桶容量：500 个\n",[68,925,923],{"__ignoreMap":66},[10,927,928],{},"如果前几秒流量很低，桶里会积累令牌。突然来一波 500 个请求，只要桶里有令牌，就可以一次性放行。",[10,930,227],{},[60,932,934],{"className":230,"code":933,"language":232,"meta":66,"style":66},"import time\n\nclass TokenBucketLimiter:\n    def __init__(self, rate: float, capacity: int):\n        self.rate = rate\n        self.capacity = capacity\n        self.tokens = capacity\n        self.last_refill = time.time()\n\n    def allow(self) -> bool:\n        now = time.time()\n        elapsed = now - self.last_refill\n        self.last_refill = now\n\n        self.tokens = min(self.capacity, self.tokens + elapsed * self.rate)\n\n        if self.tokens \u003C 1:\n            return False\n\n        self.tokens -= 1\n        return True\n",[68,935,936,943,947,956,974,986,998,1009,1021,1025,1038,1047,1063,1073,1077,1113,1117,1133,1140,1145,1157],{"__ignoreMap":66},[236,937,938,940],{"class":238,"line":239},[236,939,538],{"class":242},[236,941,942],{"class":250}," time\n",[236,944,945],{"class":238,"line":254},[236,946,335],{"emptyLinePlaceholder":334},[236,948,949,951,954],{"class":238,"line":278},[236,950,243],{"class":242},[236,952,953],{"class":246}," TokenBucketLimiter",[236,955,251],{"class":250},[236,957,958,960,962,965,967,970,972],{"class":238,"line":293},[236,959,257],{"class":242},[236,961,261],{"class":260},[236,963,964],{"class":250},"(self, rate: ",[236,966,569],{"class":260},[236,968,969],{"class":250},", capacity: ",[236,971,267],{"class":260},[236,973,275],{"class":250},[236,975,976,978,981,983],{"class":238,"line":306},[236,977,281],{"class":260},[236,979,980],{"class":250},".rate ",[236,982,287],{"class":242},[236,984,985],{"class":250}," rate\n",[236,987,988,990,993,995],{"class":238,"line":319},[236,989,281],{"class":260},[236,991,992],{"class":250},".capacity ",[236,994,287],{"class":242},[236,996,997],{"class":250}," capacity\n",[236,999,1000,1002,1005,1007],{"class":238,"line":331},[236,1001,281],{"class":260},[236,1003,1004],{"class":250},".tokens ",[236,1006,287],{"class":242},[236,1008,997],{"class":250},[236,1010,1011,1013,1016,1018],{"class":238,"line":338},[236,1012,281],{"class":260},[236,1014,1015],{"class":250},".last_refill ",[236,1017,287],{"class":242},[236,1019,1020],{"class":250}," time.time()\n",[236,1022,1023],{"class":238,"line":360},[236,1024,335],{"emptyLinePlaceholder":334},[236,1026,1027,1029,1031,1034,1036],{"class":238,"line":385},[236,1028,257],{"class":242},[236,1030,344],{"class":343},[236,1032,1033],{"class":250},"(self) -> ",[236,1035,355],{"class":260},[236,1037,251],{"class":250},[236,1039,1040,1043,1045],{"class":238,"line":398},[236,1041,1042],{"class":250},"        now ",[236,1044,287],{"class":242},[236,1046,1020],{"class":250},[236,1048,1049,1052,1054,1056,1058,1060],{"class":238,"line":409},[236,1050,1051],{"class":250},"        elapsed ",[236,1053,287],{"class":242},[236,1055,366],{"class":250},[236,1057,369],{"class":242},[236,1059,372],{"class":260},[236,1061,1062],{"class":250},".last_refill\n",[236,1064,1065,1067,1069,1071],{"class":238,"line":414},[236,1066,281],{"class":260},[236,1068,1015],{"class":250},[236,1070,287],{"class":242},[236,1072,395],{"class":250},[236,1074,1075],{"class":238,"line":430},[236,1076,335],{"emptyLinePlaceholder":334},[236,1078,1079,1081,1083,1085,1088,1090,1092,1095,1097,1099,1102,1105,1108,1110],{"class":238,"line":439},[236,1080,281],{"class":260},[236,1082,1004],{"class":250},[236,1084,287],{"class":242},[236,1086,1087],{"class":260}," min",[236,1089,678],{"class":250},[236,1091,681],{"class":260},[236,1093,1094],{"class":250},".capacity, ",[236,1096,681],{"class":260},[236,1098,1004],{"class":250},[236,1100,1101],{"class":242},"+",[236,1103,1104],{"class":250}," elapsed ",[236,1106,1107],{"class":242},"*",[236,1109,372],{"class":260},[236,1111,1112],{"class":250},".rate)\n",[236,1114,1115],{"class":238,"line":444},[236,1116,335],{"emptyLinePlaceholder":334},[236,1118,1119,1121,1123,1125,1128,1131],{"class":238,"line":457},[236,1120,363],{"class":242},[236,1122,372],{"class":260},[236,1124,1004],{"class":250},[236,1126,1127],{"class":242},"\u003C",[236,1129,1130],{"class":260}," 1",[236,1132,251],{"class":250},[236,1134,1136,1138],{"class":238,"line":1135},18,[236,1137,433],{"class":242},[236,1139,436],{"class":260},[236,1141,1143],{"class":238,"line":1142},19,[236,1144,335],{"emptyLinePlaceholder":334},[236,1146,1148,1150,1152,1155],{"class":238,"line":1147},20,[236,1149,281],{"class":260},[236,1151,1004],{"class":250},[236,1153,1154],{"class":242},"-=",[236,1156,454],{"class":260},[236,1158,1160,1162],{"class":238,"line":1159},21,[236,1161,460],{"class":242},[236,1163,463],{"class":260},[10,1165,466],{},[38,1167,1168,1171,1174,1177],{},[41,1169,1170],{},"支持突发流量。",[41,1172,1173],{},"平均速率可控。",[41,1175,1176],{},"实现相对简单。",[41,1178,1179],{},"工程实践成熟。",[10,1181,480],{},[38,1183,1184,1187],{},[41,1185,1186],{},"突发流量可能瞬间打到下游。",[41,1188,1189],{},"桶容量需要合理配置。",[10,1191,739],{},[38,1193,1194,1197,1200,1203],{},[41,1195,1196],{},"API 网关限流。",[41,1198,1199],{},"用户请求限流。",[41,1201,1202],{},"推荐主链路限流。",[41,1204,1205],{},"RPC 客户端限流。",[10,1207,500],{},[17,1209,1210],{},[10,1211,1212],{},"令牌桶按固定速率生成令牌，请求必须拿到令牌才能通过。它既能控制长期平均速率，又能允许短时间突发，所以比漏桶更适合大多数在线请求场景。",[31,1214,1215],{"id":1215},"并发数限制",[10,1217,1218],{},"前面几种算法主要限制的是速率，比如每秒多少请求。",[10,1220,1221,1222,29],{},"但有些场景更应该限制",[26,1223,1224],{},"同时正在处理的请求数",[10,1226,919],{},[38,1228,1229,1232,1235,1238],{},[41,1230,1231],{},"数据库连接池最多 100 个连接。",[41,1233,1234],{},"线程池最多 200 个 worker。",[41,1236,1237],{},"GPU 推理服务最多同时处理 32 个 batch。",[41,1239,1240],{},"下游 RPC 最多允许 1000 个 in-flight 请求。",[10,1242,1243],{},"这时可以用信号量限制并发：",[60,1245,1247],{"className":230,"code":1246,"language":232,"meta":66,"style":66},"import threading\n\nclass ConcurrencyLimiter:\n    def __init__(self, max_concurrency: int):\n        self.sem = threading.Semaphore(max_concurrency)\n\n    def handle(self, fn):\n        if not self.sem.acquire(blocking=False):\n            return \"too many requests\"\n\n        try:\n            return fn()\n        finally:\n            self.sem.release()\n",[68,1248,1249,1256,1260,1269,1282,1294,1298,1308,1331,1339,1343,1350,1357,1364],{"__ignoreMap":66},[236,1250,1251,1253],{"class":238,"line":239},[236,1252,538],{"class":242},[236,1254,1255],{"class":250}," threading\n",[236,1257,1258],{"class":238,"line":254},[236,1259,335],{"emptyLinePlaceholder":334},[236,1261,1262,1264,1267],{"class":238,"line":278},[236,1263,243],{"class":242},[236,1265,1266],{"class":246}," ConcurrencyLimiter",[236,1268,251],{"class":250},[236,1270,1271,1273,1275,1278,1280],{"class":238,"line":293},[236,1272,257],{"class":242},[236,1274,261],{"class":260},[236,1276,1277],{"class":250},"(self, max_concurrency: ",[236,1279,267],{"class":260},[236,1281,275],{"class":250},[236,1283,1284,1286,1289,1291],{"class":238,"line":306},[236,1285,281],{"class":260},[236,1287,1288],{"class":250},".sem ",[236,1290,287],{"class":242},[236,1292,1293],{"class":250}," threading.Semaphore(max_concurrency)\n",[236,1295,1296],{"class":238,"line":319},[236,1297,335],{"emptyLinePlaceholder":334},[236,1299,1300,1302,1305],{"class":238,"line":331},[236,1301,257],{"class":242},[236,1303,1304],{"class":343}," handle",[236,1306,1307],{"class":250},"(self, fn):\n",[236,1309,1310,1312,1315,1317,1320,1324,1326,1329],{"class":238,"line":338},[236,1311,363],{"class":242},[236,1313,1314],{"class":242}," not",[236,1316,372],{"class":260},[236,1318,1319],{"class":250},".sem.acquire(",[236,1321,1323],{"class":1322},"sNjOc","blocking",[236,1325,287],{"class":242},[236,1327,1328],{"class":260},"False",[236,1330,275],{"class":250},[236,1332,1333,1335],{"class":238,"line":360},[236,1334,433],{"class":242},[236,1336,1338],{"class":1337},"sXfbr"," \"too many requests\"\n",[236,1340,1341],{"class":238,"line":385},[236,1342,335],{"emptyLinePlaceholder":334},[236,1344,1345,1348],{"class":238,"line":398},[236,1346,1347],{"class":242},"        try",[236,1349,251],{"class":250},[236,1351,1352,1354],{"class":238,"line":409},[236,1353,433],{"class":242},[236,1355,1356],{"class":250}," fn()\n",[236,1358,1359,1362],{"class":238,"line":414},[236,1360,1361],{"class":242},"        finally",[236,1363,251],{"class":250},[236,1365,1366,1368],{"class":238,"line":430},[236,1367,388],{"class":260},[236,1369,1370],{"class":250},".sem.release()\n",[10,1372,1373],{},"并发数限制适合保护资源池。",[10,1375,500],{},[17,1377,1378],{},[10,1379,1380],{},"QPS 限流控制单位时间内的请求数量，并发数限制控制同时正在执行的请求数量。对于数据库连接池、线程池、GPU 推理这类资源，限制并发数往往比单纯限制 QPS 更直接。",[31,1382,1383],{"id":1383},"分布式限流",[10,1385,1386],{},"单机限流只在当前进程内生效。",[10,1388,1389],{},"如果服务有 100 个实例，每个实例限流 1000 QPS，那么全局就是 10 万 QPS。",[10,1391,1392],{},"如果想做全局限流，就需要分布式限流。",[10,1394,1395],{},"常见方案：",[97,1397,1398,1411],{},[100,1399,1400],{},[103,1401,1402,1405,1408],{},[106,1403,1404],{},"方案",[106,1406,1407],{},"优点",[106,1409,1410],{},"缺点",[113,1412,1413,1424,1435,1446,1457],{},[103,1414,1415,1418,1421],{},[118,1416,1417],{},"本地限流",[118,1419,1420],{},"快，依赖少",[118,1422,1423],{},"只能控制单机",[103,1425,1426,1429,1432],{},[118,1427,1428],{},"Redis 计数",[118,1430,1431],{},"实现简单，全局共享",[118,1433,1434],{},"Redis 成为热点",[103,1436,1437,1440,1443],{},[118,1438,1439],{},"Redis + Lua",[118,1441,1442],{},"原子性好",[118,1444,1445],{},"高并发下仍有 Redis 压力",[103,1447,1448,1451,1454],{},[118,1449,1450],{},"网关限流",[118,1452,1453],{},"入口统一控制",[118,1455,1456],{},"网关压力大",[103,1458,1459,1462,1465],{},[118,1460,1461],{},"配额下发",[118,1463,1464],{},"本地高性能",[118,1466,1467],{},"配额分配和动态调整复杂",[10,1469,1470],{},"Redis 固定窗口示意：",[60,1472,1475],{"className":1473,"code":1474,"language":65,"meta":66},[63],"key = rate_limit:user:123:2026-06-09-12:00:01\nINCR key\nEXPIRE key 1s\ncount > limit 则拒绝\n",[68,1476,1474],{"__ignoreMap":66},[10,1478,1479],{},"为什么用 Lua？",[10,1481,1482,1483,1486,1487,1490],{},"因为 ",[68,1484,1485],{},"INCR"," 和 ",[68,1488,1489],{},"EXPIRE"," 需要保证原子性。否则可能出现计数加了，但过期时间没设置成功，导致 key 永久存在。",[10,1492,1493],{},"分布式限流的核心问题：",[38,1495,1496,1499,1502,1505,1508],{},[41,1497,1498],{},"全局一致性和性能的权衡。",[41,1500,1501],{},"热点 key 问题。",[41,1503,1504],{},"Redis 故障时怎么降级。",[41,1506,1507],{},"多机房延迟。",[41,1509,1510],{},"限流配置如何动态下发。",[10,1512,1513],{},"工程上很多系统会采用混合方案：",[60,1515,1518],{"className":1516,"code":1517,"language":65,"meta":66},[63],"网关做粗粒度全局限流\n服务本地做细粒度限流\n下游客户端再做保护性限流\n",[68,1519,1517],{"__ignoreMap":66},[31,1521,1522],{"id":1522},"限流后怎么处理",[10,1524,1525],{},"限流不是只会返回错误。",[10,1527,1528],{},"常见处理方式：",[38,1530,1531,1537,1540,1543,1546],{},[41,1532,1533,1534,29],{},"直接拒绝：返回 ",[68,1535,1536],{},"429 Too Many Requests",[41,1538,1539],{},"排队等待：适合后台任务，不适合强交互请求。",[41,1541,1542],{},"降级返回：返回缓存、默认结果、热门结果。",[41,1544,1545],{},"延迟重试：告诉客户端稍后再试。",[41,1547,1548],{},"动态降级：关闭非核心功能，保核心链路。",[10,1550,1551],{},"推荐系统里的例子：",[60,1553,1556],{"className":1554,"code":1555,"language":65,"meta":66},[63],"个性化召回限流\n  -> 返回热门召回\n\n精排模型服务限流\n  -> 使用粗排结果兜底\n\n实时特征服务限流\n  -> 使用离线特征或默认特征\n",[68,1557,1555],{"__ignoreMap":66},[10,1559,1560],{},"用户侧不一定要看到“系统繁忙”，可以返回一个质量略低但可用的结果。",[31,1562,1564],{"id":1563},"限流和熔断降级的区别","限流和熔断、降级的区别",[10,1566,1567],{},"这三个概念经常一起出现。",[97,1569,1570,1580],{},[100,1571,1572],{},[103,1573,1574,1577],{},[106,1575,1576],{},"概念",[106,1578,1579],{},"解决什么问题",[113,1581,1582,1590,1598],{},[103,1583,1584,1587],{},[118,1585,1586],{},"限流",[118,1588,1589],{},"流量太大，主动控制进入系统的请求量",[103,1591,1592,1595],{},[118,1593,1594],{},"熔断",[118,1596,1597],{},"下游持续失败，暂时停止调用，避免故障扩散",[103,1599,1600,1603],{},[118,1601,1602],{},"降级",[118,1604,1605],{},"牺牲非核心能力，保证核心功能可用",[10,1607,1608],{},"一句话区分：",[17,1610,1611],{},[10,1612,1613],{},"限流处理流量过大，熔断处理依赖故障，降级处理能力不足或依赖不可用后的兜底体验。",[31,1615,1616],{"id":1616},"面试怎么选型",[10,1618,1619],{},"可以直接背这张表：",[97,1621,1622,1632],{},[100,1623,1624],{},[103,1625,1626,1629],{},[106,1627,1628],{},"场景",[106,1630,1631],{},"推荐算法",[113,1633,1634,1642,1649,1656,1664,1672,1679],{},[103,1635,1636,1639],{},[118,1637,1638],{},"简单接口限流",[118,1640,1641],{},"固定窗口",[103,1643,1644,1647],{},[118,1645,1646],{},"单用户精确限流",[118,1648,508],{},[103,1650,1651,1654],{},[118,1652,1653],{},"大多数接口 QPS 限流",[118,1655,756],{},[103,1657,1658,1661],{},[118,1659,1660],{},"需要稳定输出保护下游",[118,1662,1663],{},"漏桶",[103,1665,1666,1669],{},[118,1667,1668],{},"允许突发的在线请求",[118,1670,1671],{},"令牌桶",[103,1673,1674,1677],{},[118,1675,1676],{},"保护线程池 \u002F 连接池 \u002F GPU",[118,1678,1215],{},[103,1680,1681,1684],{},[118,1682,1683],{},"多实例全局限流",[118,1685,1686],{},"Redis \u002F 网关 \u002F 配额下发",[10,1688,1689],{},"高频面试回答：",[17,1691,1692],{},[10,1693,1694],{},"固定窗口简单但有边界突刺；滑动日志精确但内存开销大；滑动窗口计数器是折中方案；漏桶强调稳定输出，适合保护下游；令牌桶允许突发，同时控制平均速率，是在线服务最常见的选择；如果瓶颈是连接池、线程池或 GPU 资源，还需要配合并发数限制。",[31,1696,1697],{"id":1697},"系统设计里怎么说",[10,1699,1700],{},"如果面试官问“如何设计一个高并发接口的限流”，可以按下面结构回答：",[60,1702,1705],{"className":1703,"code":1704,"language":65,"meta":66},[63],"1. 先明确限流目标\n   全局 QPS、单用户 QPS、接口 QPS、下游 QPS、并发数？\n\n2. 选择限流位置\n   网关、本服务、本地客户端、下游入口？\n\n3. 选择算法\n   在线请求用令牌桶\n   下游保护用漏桶或并发数限制\n   用户维度用滑动窗口\n\n4. 设计限流后的处理\n   返回 429、排队、降级、缓存兜底、热门结果兜底\n\n5. 做监控和动态配置\n   限流次数、通过率、拒绝率、P99、下游错误率、配置热更新\n",[68,1706,1704],{"__ignoreMap":66},[10,1708,1709],{},"不要只讲算法，要讲完整工程闭环。",[31,1711,1712],{"id":1712},"最后总结",[10,1714,1715],{},"限流算法可以这样记：",[60,1717,1720],{"className":1718,"code":1719,"language":65,"meta":66},[63],"固定窗口：简单，但边界突刺。\n滑动日志：精确，但内存开销大。\n滑动窗口计数器：平滑和成本之间的折中。\n漏桶：稳定输出，保护下游。\n令牌桶：允许突发，在线服务常用。\n并发数限制：保护线程池、连接池、GPU 等有限资源。\n",[68,1721,1719],{"__ignoreMap":66},[10,1723,1724],{},"工程里不会只用一种限流。",[10,1726,1727],{},"更常见的是：",[60,1729,1732],{"className":1730,"code":1731,"language":65,"meta":66},[63],"网关全局限流\n  + 服务本地限流\n  + 用户维度限流\n  + 下游客户端限流\n  + 并发数限制\n  + 降级兜底\n",[68,1733,1731],{"__ignoreMap":66},[10,1735,1736],{},"限流的本质不是拒绝请求，而是让系统在流量超过承载能力时，仍然能稳定、可控、优先保证核心链路。",[1738,1739,1740],"style",{},"html pre.shiki code .s6PUj, html code.shiki .s6PUj{--shiki-default:#F47067;--shiki-light:#D73A49}html pre.shiki code .sqRhv, html code.shiki .sqRhv{--shiki-default:#F69D50;--shiki-light:#6F42C1}html pre.shiki code .ssh_m, html code.shiki .ssh_m{--shiki-default:#ADBAC7;--shiki-light:#24292E}html pre.shiki code .swcJU, html code.shiki .swcJU{--shiki-default:#6CB6FF;--shiki-light:#005CC5}html pre.shiki code .saVmf, html code.shiki .saVmf{--shiki-default:#DCBDFB;--shiki-light:#6F42C1}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .sNjOc, html code.shiki .sNjOc{--shiki-default:#F69D50;--shiki-light:#E36209}html pre.shiki code .sXfbr, html code.shiki .sXfbr{--shiki-default:#96D0FF;--shiki-light:#032F62}",{"title":66,"searchDepth":254,"depth":278,"links":1742},[1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756],{"id":33,"depth":254,"text":33},{"id":92,"depth":254,"text":92},{"id":203,"depth":254,"text":203},{"id":508,"depth":254,"text":508},{"id":756,"depth":254,"text":756},{"id":813,"depth":254,"text":813},{"id":885,"depth":254,"text":885},{"id":1215,"depth":254,"text":1215},{"id":1383,"depth":254,"text":1383},{"id":1522,"depth":254,"text":1522},{"id":1563,"depth":254,"text":1564},{"id":1616,"depth":254,"text":1616},{"id":1697,"depth":254,"text":1697},{"id":1712,"depth":254,"text":1712},[1758],"技术","2026-06-09","面试和工程都常见的限流算法总结，讲清楚固定窗口、滑动窗口、漏桶、令牌桶、并发数限制以及分布式限流如何落地。",false,"md",{},"\u002Fposts\u002Fhigh-concurrency-rate-limiting-algorithms",{"title":5,"description":1760},"posts\u002Fhigh-concurrency-rate-limiting-algorithms",[1768,1586,1769,1770,1771],"高并发","后端架构","系统设计","面试","HbIZZhtxFefTB41oVPPVfG0sTKZu_I6ZHT5PrFLz7FU",[1774,1787,1799,1805,1814,1817,1826,1836,1846,1855,1865,1876,1889,1901,1909,1919,1931,1942,1952,1960,1971,1977,1983,1989,1997,2006,2014,2020,2028,2036],{"slug":1775,"path":1776,"title":1777,"date":1778,"tags":1779,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":360},"multimodal-rag-from-scratch","\u002Fposts\u002Fmultimodal-rag-from-scratch","从零实现多模态 RAG：BM25、Dense 检索、RRF 融合、MMR 重排全部手写","2026-06-30 18:00:00",[1780,1781,1782,1783,1784,1785,1786],"RAG","多模态","AI Infra","BM25","向量检索","混合检索","实习求职",{"slug":1788,"path":1789,"title":1790,"date":1791,"tags":1792,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":398},"mini-llm-engine-deep-dive","\u002Fposts\u002Fmini-llm-engine-deep-dive","讲透 mini-llm-engine：从显存碎片到六大推理优化","2026-06-30 14:00:00",[1793,1782,1794,1795,1796,1797,1798,1786],"LLM","vLLM","PagedAttention","KV Cache","推理优化","投机解码",{"slug":1800,"path":1801,"title":1802,"date":1803,"tags":1804,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":385},"mini-llm-engine-from-scratch","\u002Fposts\u002Fmini-llm-engine-from-scratch","从零实现 LLM 推理引擎：深挖 vLLM 的六大核心优化","2026-06-30 10:00:00",[1793,1782,1794,1795,1797,1798,1786],{"slug":1806,"path":1807,"title":1808,"date":1759,"tags":1809,"description":1813,"draft":1761,"hidden":1761,"published":334,"readingTime":1135},"bytedance-recommendation-architecture-intern-interview","\u002Fposts\u002Fbytedance-recommendation-architecture-intern-interview","字节推荐架构实习生 Data 面试准备：推荐系统、实时特征与高并发八股",[1771,1810,1769,1811,1812],"推荐系统","实时计算","字节跳动","面向字节跳动推荐架构团队实习岗位的八股准备清单，覆盖推荐系统链路、实时数据、特征服务、高并发后端、分布式系统与项目包装。",{"slug":1815,"path":1764,"title":5,"date":1759,"tags":1816,"description":1760,"draft":1761,"hidden":1761,"published":334,"readingTime":409},"high-concurrency-rate-limiting-algorithms",[1768,1586,1769,1770,1771],{"slug":1818,"path":1819,"title":1820,"date":1759,"tags":1821,"description":1825,"draft":1761,"hidden":1761,"published":334,"readingTime":338},"kafka-producer-broker-consumer","\u002Fposts\u002Fkafka-producer-broker-consumer","Kafka 入门：生产者、Broker、消费者和“消费”到底是什么意思",[1822,1823,1824,1771,1810],"Kafka","消息队列","后端","用推荐系统里的用户行为日志为例，讲清楚 Kafka 的作用、Producer、Broker、Consumer、Topic、Partition、Offset 和消费语义。",{"slug":1827,"path":1828,"title":1829,"date":1759,"tags":1830,"description":1835,"draft":1761,"hidden":1761,"published":334,"readingTime":319},"leetcode-lru-merge-k-reverse-list","\u002Fposts\u002Fleetcode-lru-merge-k-reverse-list","链表与缓存高频题：LRU Cache、合并 K 个有序链表、反转链表",[1831,1832,1833,1834,1771],"算法","链表","LRU","LeetCode","面试高频算法题速记，整理 LRU Cache、合并 K 个有序链表、反转链表的核心思路、复杂度和 C++ 代码。",{"slug":1837,"path":1838,"title":1839,"date":1840,"tags":1841,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":444},"meddococr-interpreter-source-analysis","\u002Fposts\u002Fmeddococr-interpreter-source-analysis","MedDocOCR-Interpreter 源码导读：医疗文档 OCR、结构化抽取与报告解读原型","2026-05-22 10:30:00",[1842,1781,1843,1780,1844,1845],"OCR","医疗 AI","Python","源码分析",{"slug":1847,"path":1848,"title":1849,"date":1850,"tags":1851,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":385},"cet6-writing-model-essays","\u002Fposts\u002Fcet6-writing-model-essays","六级写作范文背诵包：10 个高频话题","2026-05-20 09:00:00",[1852,1853,1854],"English","CET6","Writing",{"slug":1856,"path":1857,"title":1858,"date":1859,"tags":1860,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":1864},"claude-code-context-management","\u002Fposts\u002Fclaude-code-context-management","Claude Code 上下文管理机制：从 Microcompact 到 Auto Compact","2026-05-19 10:00:00",[1861,1862,1793,1782,1863],"Claude Code","Agent","上下文工程",27,{"slug":1866,"path":1867,"title":1868,"date":1869,"tags":1870,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":1142},"nanotron-llm-pretraining-framework-analysis","\u002Fposts\u002Fnanotron-llm-pretraining-framework-analysis","Nanotron 项目详解：Hugging Face 的大模型预训练框架怎么做分布式训练","2026-05-10 12:10:00",[1793,1871,1872,1873,1874,1782,1875],"大模型训练","分布式训练","Nanotron","Hugging Face","PyTorch",{"slug":1877,"path":1878,"title":1879,"date":1880,"tags":1881,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":1888},"gofoundry-go-backend-foundation-framework","\u002Fposts\u002Fgofoundry-go-backend-foundation-framework","GoFoundry 项目详解：基于 Go 的后端基础框架套件设计","2026-05-10 11:20:00",[1882,1883,1884,1885,1886,1823,1887],"Go","后端框架","ORM","分布式缓存","分布式锁","项目架构",25,{"slug":1890,"path":1891,"title":1892,"date":1893,"tags":1894,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":1864},"cloudvault-go-cloud-storage-system","\u002Fposts\u002Fcloudvault-go-cloud-storage-system","CloudVault 项目详解：基于 Go 的云端存储与网盘系统架构设计","2026-05-10 10:30:00",[1882,1895,1896,1897,1887,1898,1899,1900],"云存储","网盘系统","分布式系统","Redis","RabbitMQ","Elasticsearch",{"slug":1902,"path":1903,"title":1904,"date":1905,"tags":1906,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":1147},"openclaw-source-code-analysis","\u002Fposts\u002Fopenclaw-source-code-analysis","OpenClaw 源码导读：个人 AI 助手的网关、通道、插件与运行时架构","2026-05-08 16:30:00",[1907,1862,1782,1908,1845],"OpenClaw","TypeScript",{"slug":1910,"path":1911,"title":1912,"date":1913,"tags":1914,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":385},"flow-matching-generative-models","\u002Fposts\u002Fflow-matching-generative-models","Flow Matching：从噪声到数据的连续流生成模型","2026-05-07 00:00:00",[1915,1916,1917,1918],"生成模型","Diffusion","Flow Matching","深度学习",{"slug":1920,"path":1921,"title":1922,"date":1923,"tags":1924,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":439},"database-ai-week4","\u002Fposts\u002Fdatabase-ai-week4","Week 4：数据库速成——从 Storage、Index、Query Optimization 到 Vector DB 与 RAG","2026-05-05 12:00:00",[1925,1926,1927,1780,1928,1929,1930],"数据库","CMU 15-445","Vector DB","LLM Memory","Query Optimization","Caching",{"slug":1932,"path":1933,"title":1934,"date":1935,"tags":1936,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":444},"distributed-systems-week3","\u002Fposts\u002Fdistributed-systems-week3","Week 3：分布式系统速成——MapReduce、Raft、容错与 Distributed KV Store","2026-05-05 11:00:00",[1897,1937,1938,1939,1940,1941,1862],"MIT 6.824","MapReduce","Raft","KV Store","Ray",{"slug":1943,"path":1944,"title":1945,"date":1946,"tags":1947,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":439},"gpu-inference-acceleration-week2","\u002Fposts\u002Fgpu-inference-acceleration-week2","Week 2：GPU 与推理加速——从 Kernel、算子融合到 LLM Serving","2026-05-05 10:00:00",[1918,1948,1949,1793,1950,1794,1951],"GPU","推理加速","CMU 10-414","TensorRT",{"slug":1953,"path":1954,"title":1955,"date":1956,"tags":1957,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":1135},"dl-framework-autograd-mini","\u002Fposts\u002Fdl-framework-autograd-mini","Week 1：DL 框架与 Autograd——从计算图、反向传播到 Mini Autograd 实现","2026-05-05 09:00:00",[1918,1958,1875,1950,1959],"Autograd","Mini Framework",{"slug":1961,"path":1962,"title":1963,"date":1964,"tags":1965,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":409},"lock-free-concurrency-notes","\u002Fposts\u002Flock-free-concurrency-notes","无锁并发入门：从 CAS 到 Atomic Ring Buffer","2026-04-25",[1966,1967,1968,1969,1970],"C++","并发","无锁编程","性能优化","量化开发",{"slug":1972,"path":1973,"title":1974,"date":1975,"tags":1976,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":306},"agent-memory","\u002Fposts\u002Fagent-memory","Agent 对话记忆化：从原理到实现","2026-04-24",[1793,1862,1780,1771],{"slug":1978,"path":1979,"title":1980,"date":1975,"tags":1981,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":319},"llm-context-compression","\u002Fposts\u002Fllm-context-compression","LLM 上下文五层压缩机制详解",[1793,1862,1982,1771],"上下文压缩",{"slug":1984,"path":1985,"title":1986,"date":1987,"tags":1988,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":360},"cpp-concurrency-basics","\u002Fposts\u002Fcpp-concurrency-basics","C++ 并发编程入门：从数据竞争到线程池","2026-04-15",[1966,1967,1771,1970],{"slug":1990,"path":1991,"title":1992,"date":1993,"tags":1994,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":239},"travel-in-shenzhen","\u002Fposts\u002Ftravel-in-shenzhen","XCPC 深圳游记","2026-04-13",[1995,1966,1996],"XCPC","比赛",{"slug":1998,"path":1999,"title":2000,"date":2001,"tags":2002,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":331},"backend-stack-deep-dive","\u002Fposts\u002Fbackend-stack-deep-dive","后端五件套：FastAPI \u002F Node.js \u002F SQLAlchemy async \u002F PostgreSQL \u002F Docker 面试速通","2026-04-07",[1824,2003,2004,2005,1771],"FastAPI","PostgreSQL","Docker",{"slug":2007,"path":2008,"title":2009,"date":2010,"tags":2011,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":319},"deepscientist-tech-stack","\u002Fposts\u002Fdeepscientist-tech-stack","DeepScientist 技术栈全解析：一个 AI 科研平台的架构设计","2026-04-06",[2012,2003,2013,2004,1771],"全栈","Next.js",{"slug":2015,"path":2016,"title":2017,"date":2010,"tags":2018,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":338},"minicode-source-analysis","\u002Fposts\u002Fminicode-source-analysis","MiniCode 源码解析：用 5000 行 TypeScript 实现一个 AI 编程助手",[1908,2019,1793,1845,1771],"CLI",{"slug":2021,"path":2022,"title":2023,"date":2010,"tags":2024,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":306},"nova-theme-implementation","\u002Fposts\u002Fnova-theme-implementation","我是怎么从零实现 Nova 主题的",[2025,2026,2027],"Hexo","前端","开源",{"slug":2029,"path":2030,"title":2031,"date":2032,"tags":2033,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":254},"git-cheatsheet","\u002Fposts\u002Fgit-cheatsheet","Git 常用操作备忘","2026-04-05 14:00:00",[2034,2035],"Git","工具",{"slug":2037,"path":2038,"title":2039,"date":2040,"tags":2041,"description":66,"draft":1761,"hidden":1761,"published":334,"readingTime":278},"github-actions-intro","\u002Fposts\u002Fgithub-actions-intro","GitHub Actions 入门：自动化你的工作流","2026-04-04 09:00:00",[2042,2043,2044],"GitHub Actions","CI\u002FCD","自动化",1782796012177]