[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"public-branding":3,"content-de-redis-cache-patterns":8,"public-ads-config":1261},{"siteName":4,"primaryColor":5,"accentColor":6,"faviconUrl":7,"logoUrl":7},"KiroCloud","#ffffff","#888888","",{"id":9,"title":10,"author":11,"body":12,"category":11,"description":1246,"extension":1247,"lastUpdated":11,"meta":1248,"navigation":135,"order":1249,"path":1250,"readTime":11,"seo":1251,"stem":1259,"__hash__":1260},"docs\u002Fdocs\u002Fde\u002Fredis-cache-patterns.md","[object Object]",null,{"type":13,"value":14,"toc":1239},"minimark",[15,20,29,37,40,45,54,56,64,75,93,910,912,916,923,1226,1228,1232,1235],[16,17,19],"h1",{"id":18},"high-speed-redis-cache-patterns-für-discord-bots-sub-millisekunden-leaderboards","High-Speed Redis Cache Patterns für Discord Bots: Sub-Millisekunden Leaderboards",[21,22,23,24,28],"p",{},"Wenn ein Discord-Bot auf Tausenden von Servern aktiv ist, führt jede Chat-Nachricht (XP-Vergabe, Level-Aufstiege, Cooldown-Prüfungen) zu Datenbank-Interaktionen. Würde jede Nachricht einen SQL-Befehl auf PostgreSQL absetzen (",[25,26,27],"code",{},"SELECT * FROM users WHERE id = ?","), bricht der Datenbank-Verbindungspool bei hoher Aktivität schnell zusammen.",[21,30,31,32,36],{},"Mit ",[33,34,35],"strong",{},"Redis"," als In-Memory-Caching-Layer lagern wir transiente Zustände in den RAM aus. Abfragen laufen in unter 1 Millisekunde ab und entlasten die persistente SQL-Datenbank um bis zu 95 %.",[38,39],"hr",{},[41,42,44],"h2",{"id":43},"_1-die-caching-topologie-write-through-vs-write-behind","1. Die Caching-Topologie: Write-Through vs. Write-Behind",[46,47,52],"pre",{"className":48,"code":50,"language":51},[49],"language-text","┌─────────────────────────────────────────────────────────────────┐\n│                     Discord Gateway Events                      │\n└────────────────────────────────┬────────────────────────────────┘\n                                 │\n                                 ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                        KiroCloud Bot Engine                     │\n├────────────────────────────────┬────────────────────────────────┤\n│ 1. Schnelle In-Memory Abfrage  │ 2. Asynchrone Batch-Speicherung│\n│    (Latenz: 0.4 ms)            │    (alle 60 Sekunden)          │\n│    ▼                           │    ▼                           │\n│  ┌───────────────────────┐     │  ┌──────────────────────────┐  │\n│  │     Redis Cache       │     │  │  PostgreSQL Datenbank    │  │\n│  │ (Sorted Sets, TTL)    │     │  │  (Persistente Sicherung) │  │\n│  └───────────────────────┘     │  └──────────────────────────┘  │\n└────────────────────────────────┴────────────────────────────────┘\n","text",[25,53,50],{"__ignoreMap":7},[38,55],{},[41,57,59,60,63],{"id":58},"_2-echtzeit-ranglisten-mit-redis-sorted-sets-zset","2. Echtzeit-Ranglisten mit Redis Sorted Sets (",[25,61,62],{},"ZSET",")",[21,65,66,67,70,71,74],{},"Der naheliegendste Anwendungsfall für Redis in Discord-Bots sind Level- und Coin-Ranglisten (",[25,68,69],{},"\u002Fleaderboard","). In SQL erfordert dies ein teures ",[25,72,73],{},"ORDER BY xp DESC LIMIT 10",", das bei Tabellen mit Millionen Zeilen erhebliche CPU-Zeit beansprucht.",[21,76,77,78,81,82,85,86,85,89,92],{},"In Redis nutzen wir ",[33,79,80],{},"Sorted Sets"," (",[25,83,84],{},"ZADD",", ",[25,87,88],{},"ZREVRANGE",[25,90,91],{},"ZREVRANK","), die intern als Skip-Lists organisiert sind und Rangabfragen in $O(\\log N)$ Komplexität lösen:",[46,94,98],{"className":95,"code":96,"language":97,"meta":7,"style":7},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import Redis from 'ioredis';\n\nconst redis = new Redis(process.env.REDIS_URL || 'redis:\u002F\u002Flocalhost:6379');\n\n\u002F**\n * Erhöht die Erfahrungspunkte eines Nutzers auf einem Server\n *\u002F\nexport async function addGuildUserXp(guildId: string, userId: string, xpDelta: number): Promise\u003Cnumber> {\n  const leaderboardKey = `guild:${guildId}:xp_leaderboard`;\n\n  \u002F\u002F ZINCRBY erhöht den Score atomar und liefert den neuen Wert zurück\n  const newXp = await redis.zincrby(leaderboardKey, xpDelta, userId);\n  return parseFloat(newXp);\n}\n\n\u002F**\n * Ermittelt die Top 10 Nutzer eines Servers in Sub-Millisekunden\n *\u002F\nexport async function getTopUsers(guildId: string, limit = 10): Promise\u003CArray\u003C{ userId: string; score: number }>> {\n  const leaderboardKey = `guild:${guildId}:xp_leaderboard`;\n\n  \u002F\u002F ZREVRANGE mit WITHSCORES liefert die ranghöchsten Einträge\n  const rawResults = await redis.zrevrange(leaderboardKey, 0, limit - 1, 'WITHSCORES');\n\n  const formatted: Array\u003C{ userId: string; score: number }> = [];\n  for (let i = 0; i \u003C rawResults.length; i += 2) {\n    formatted.push({\n      userId: rawResults[i],\n      score: parseFloat(rawResults[i + 1]),\n    });\n  }\n\n  return formatted;\n}\n\n\u002F**\n * Ermittelt den genauen Platz (Rank) eines bestimmten Nutzers\n *\u002F\nexport async function getUserRank(guildId: string, userId: string): Promise\u003Cnumber | null> {\n  const leaderboardKey = `guild:${guildId}:xp_leaderboard`;\n  \u002F\u002F ZREVRANK liefert den 0-basierten Index absteigend sortiert\n  const rank = await redis.zrevrank(leaderboardKey, userId);\n  return rank !== null ? rank + 1 : null;\n}\n","typescript",[25,99,100,130,137,185,190,197,203,209,276,310,315,321,360,378,384,389,394,400,405,469,494,499,505,556,561,600,648,663,685,714,724,730,735,744,749,754,759,765,770,816,841,847,878,905],{"__ignoreMap":7},[101,102,105,109,113,116,120,124,127],"span",{"class":103,"line":104},"line",1,[101,106,108],{"class":107},"s7zQu","import",[101,110,112],{"class":111},"sTEyZ"," Redis ",[101,114,115],{"class":107},"from",[101,117,119],{"class":118},"sMK4o"," '",[101,121,123],{"class":122},"sfazB","ioredis",[101,125,126],{"class":118},"'",[101,128,129],{"class":118},";\n",[101,131,133],{"class":103,"line":132},2,[101,134,136],{"emptyLinePlaceholder":135},true,"\n",[101,138,140,144,147,150,153,157,160,163,166,168,171,174,176,179,181,183],{"class":103,"line":139},3,[101,141,143],{"class":142},"spNyl","const",[101,145,146],{"class":111}," redis ",[101,148,149],{"class":118},"=",[101,151,152],{"class":118}," new",[101,154,156],{"class":155},"s2Zo4"," Redis",[101,158,159],{"class":111},"(process",[101,161,162],{"class":118},".",[101,164,165],{"class":111},"env",[101,167,162],{"class":118},[101,169,170],{"class":111},"REDIS_URL ",[101,172,173],{"class":118},"||",[101,175,119],{"class":118},[101,177,178],{"class":122},"redis:\u002F\u002Flocalhost:6379",[101,180,126],{"class":118},[101,182,63],{"class":111},[101,184,129],{"class":118},[101,186,188],{"class":103,"line":187},4,[101,189,136],{"emptyLinePlaceholder":135},[101,191,193],{"class":103,"line":192},5,[101,194,196],{"class":195},"sHwdD","\u002F**\n",[101,198,200],{"class":103,"line":199},6,[101,201,202],{"class":195}," * Erhöht die Erfahrungspunkte eines Nutzers auf einem Server\n",[101,204,206],{"class":103,"line":205},7,[101,207,208],{"class":195}," *\u002F\n",[101,210,212,215,218,221,224,227,231,234,238,241,244,246,248,250,253,255,258,261,264,267,270,273],{"class":103,"line":211},8,[101,213,214],{"class":107},"export",[101,216,217],{"class":142}," async",[101,219,220],{"class":142}," function",[101,222,223],{"class":155}," addGuildUserXp",[101,225,226],{"class":118},"(",[101,228,230],{"class":229},"sHdIc","guildId",[101,232,233],{"class":118},":",[101,235,237],{"class":236},"sBMFI"," string",[101,239,240],{"class":118},",",[101,242,243],{"class":229}," userId",[101,245,233],{"class":118},[101,247,237],{"class":236},[101,249,240],{"class":118},[101,251,252],{"class":229}," xpDelta",[101,254,233],{"class":118},[101,256,257],{"class":236}," number",[101,259,260],{"class":118},"):",[101,262,263],{"class":236}," Promise",[101,265,266],{"class":118},"\u003C",[101,268,269],{"class":236},"number",[101,271,272],{"class":118},">",[101,274,275],{"class":118}," {\n",[101,277,279,282,285,288,291,294,297,299,302,305,308],{"class":103,"line":278},9,[101,280,281],{"class":142},"  const",[101,283,284],{"class":111}," leaderboardKey",[101,286,287],{"class":118}," =",[101,289,290],{"class":118}," `",[101,292,293],{"class":122},"guild:",[101,295,296],{"class":118},"${",[101,298,230],{"class":111},[101,300,301],{"class":118},"}",[101,303,304],{"class":122},":xp_leaderboard",[101,306,307],{"class":118},"`",[101,309,129],{"class":118},[101,311,313],{"class":103,"line":312},10,[101,314,136],{"emptyLinePlaceholder":135},[101,316,318],{"class":103,"line":317},11,[101,319,320],{"class":195},"  \u002F\u002F ZINCRBY erhöht den Score atomar und liefert den neuen Wert zurück\n",[101,322,324,326,329,331,334,337,339,342,345,348,350,352,354,356,358],{"class":103,"line":323},12,[101,325,281],{"class":142},[101,327,328],{"class":111}," newXp",[101,330,287],{"class":118},[101,332,333],{"class":107}," await",[101,335,336],{"class":111}," redis",[101,338,162],{"class":118},[101,340,341],{"class":155},"zincrby",[101,343,226],{"class":344},"swJcz",[101,346,347],{"class":111},"leaderboardKey",[101,349,240],{"class":118},[101,351,252],{"class":111},[101,353,240],{"class":118},[101,355,243],{"class":111},[101,357,63],{"class":344},[101,359,129],{"class":118},[101,361,363,366,369,371,374,376],{"class":103,"line":362},13,[101,364,365],{"class":107},"  return",[101,367,368],{"class":155}," parseFloat",[101,370,226],{"class":344},[101,372,373],{"class":111},"newXp",[101,375,63],{"class":344},[101,377,129],{"class":118},[101,379,381],{"class":103,"line":380},14,[101,382,383],{"class":118},"}\n",[101,385,387],{"class":103,"line":386},15,[101,388,136],{"emptyLinePlaceholder":135},[101,390,392],{"class":103,"line":391},16,[101,393,196],{"class":195},[101,395,397],{"class":103,"line":396},17,[101,398,399],{"class":195}," * Ermittelt die Top 10 Nutzer eines Servers in Sub-Millisekunden\n",[101,401,403],{"class":103,"line":402},18,[101,404,208],{"class":195},[101,406,408,410,412,414,417,419,421,423,425,427,430,432,436,438,440,442,445,448,450,452,454,457,460,462,464,467],{"class":103,"line":407},19,[101,409,214],{"class":107},[101,411,217],{"class":142},[101,413,220],{"class":142},[101,415,416],{"class":155}," getTopUsers",[101,418,226],{"class":118},[101,420,230],{"class":229},[101,422,233],{"class":118},[101,424,237],{"class":236},[101,426,240],{"class":118},[101,428,429],{"class":229}," limit",[101,431,287],{"class":118},[101,433,435],{"class":434},"sbssI"," 10",[101,437,260],{"class":118},[101,439,263],{"class":236},[101,441,266],{"class":118},[101,443,444],{"class":236},"Array",[101,446,447],{"class":118},"\u003C{",[101,449,243],{"class":344},[101,451,233],{"class":118},[101,453,237],{"class":236},[101,455,456],{"class":118},";",[101,458,459],{"class":344}," score",[101,461,233],{"class":118},[101,463,257],{"class":236},[101,465,466],{"class":118}," }>>",[101,468,275],{"class":118},[101,470,472,474,476,478,480,482,484,486,488,490,492],{"class":103,"line":471},20,[101,473,281],{"class":142},[101,475,284],{"class":111},[101,477,287],{"class":118},[101,479,290],{"class":118},[101,481,293],{"class":122},[101,483,296],{"class":118},[101,485,230],{"class":111},[101,487,301],{"class":118},[101,489,304],{"class":122},[101,491,307],{"class":118},[101,493,129],{"class":118},[101,495,497],{"class":103,"line":496},21,[101,498,136],{"emptyLinePlaceholder":135},[101,500,502],{"class":103,"line":501},22,[101,503,504],{"class":195},"  \u002F\u002F ZREVRANGE mit WITHSCORES liefert die ranghöchsten Einträge\n",[101,506,508,510,513,515,517,519,521,524,526,528,530,533,535,537,540,543,545,547,550,552,554],{"class":103,"line":507},23,[101,509,281],{"class":142},[101,511,512],{"class":111}," rawResults",[101,514,287],{"class":118},[101,516,333],{"class":107},[101,518,336],{"class":111},[101,520,162],{"class":118},[101,522,523],{"class":155},"zrevrange",[101,525,226],{"class":344},[101,527,347],{"class":111},[101,529,240],{"class":118},[101,531,532],{"class":434}," 0",[101,534,240],{"class":118},[101,536,429],{"class":111},[101,538,539],{"class":118}," -",[101,541,542],{"class":434}," 1",[101,544,240],{"class":118},[101,546,119],{"class":118},[101,548,549],{"class":122},"WITHSCORES",[101,551,126],{"class":118},[101,553,63],{"class":344},[101,555,129],{"class":118},[101,557,559],{"class":103,"line":558},24,[101,560,136],{"emptyLinePlaceholder":135},[101,562,564,566,569,571,574,576,578,580,582,584,586,588,590,593,595,598],{"class":103,"line":563},25,[101,565,281],{"class":142},[101,567,568],{"class":111}," formatted",[101,570,233],{"class":118},[101,572,573],{"class":236}," Array",[101,575,447],{"class":118},[101,577,243],{"class":344},[101,579,233],{"class":118},[101,581,237],{"class":236},[101,583,456],{"class":118},[101,585,459],{"class":344},[101,587,233],{"class":118},[101,589,257],{"class":236},[101,591,592],{"class":118}," }>",[101,594,287],{"class":118},[101,596,597],{"class":344}," []",[101,599,129],{"class":118},[101,601,603,606,608,611,614,616,618,620,622,625,627,629,632,634,636,639,642,645],{"class":103,"line":602},26,[101,604,605],{"class":107},"  for",[101,607,81],{"class":344},[101,609,610],{"class":142},"let",[101,612,613],{"class":111}," i",[101,615,287],{"class":118},[101,617,532],{"class":434},[101,619,456],{"class":118},[101,621,613],{"class":111},[101,623,624],{"class":118}," \u003C",[101,626,512],{"class":111},[101,628,162],{"class":118},[101,630,631],{"class":111},"length",[101,633,456],{"class":118},[101,635,613],{"class":111},[101,637,638],{"class":118}," +=",[101,640,641],{"class":434}," 2",[101,643,644],{"class":344},") ",[101,646,647],{"class":118},"{\n",[101,649,651,654,656,659,661],{"class":103,"line":650},27,[101,652,653],{"class":111},"    formatted",[101,655,162],{"class":118},[101,657,658],{"class":155},"push",[101,660,226],{"class":344},[101,662,647],{"class":118},[101,664,666,669,671,673,676,679,682],{"class":103,"line":665},28,[101,667,668],{"class":344},"      userId",[101,670,233],{"class":118},[101,672,512],{"class":111},[101,674,675],{"class":344},"[",[101,677,678],{"class":111},"i",[101,680,681],{"class":344},"]",[101,683,684],{"class":118},",\n",[101,686,688,691,693,695,697,700,702,704,707,709,712],{"class":103,"line":687},29,[101,689,690],{"class":344},"      score",[101,692,233],{"class":118},[101,694,368],{"class":155},[101,696,226],{"class":344},[101,698,699],{"class":111},"rawResults",[101,701,675],{"class":344},[101,703,678],{"class":111},[101,705,706],{"class":118}," +",[101,708,542],{"class":434},[101,710,711],{"class":344},"])",[101,713,684],{"class":118},[101,715,717,720,722],{"class":103,"line":716},30,[101,718,719],{"class":118},"    }",[101,721,63],{"class":344},[101,723,129],{"class":118},[101,725,727],{"class":103,"line":726},31,[101,728,729],{"class":118},"  }\n",[101,731,733],{"class":103,"line":732},32,[101,734,136],{"emptyLinePlaceholder":135},[101,736,738,740,742],{"class":103,"line":737},33,[101,739,365],{"class":107},[101,741,568],{"class":111},[101,743,129],{"class":118},[101,745,747],{"class":103,"line":746},34,[101,748,383],{"class":118},[101,750,752],{"class":103,"line":751},35,[101,753,136],{"emptyLinePlaceholder":135},[101,755,757],{"class":103,"line":756},36,[101,758,196],{"class":195},[101,760,762],{"class":103,"line":761},37,[101,763,764],{"class":195}," * Ermittelt den genauen Platz (Rank) eines bestimmten Nutzers\n",[101,766,768],{"class":103,"line":767},38,[101,769,208],{"class":195},[101,771,773,775,777,779,782,784,786,788,790,792,794,796,798,800,802,804,806,809,812,814],{"class":103,"line":772},39,[101,774,214],{"class":107},[101,776,217],{"class":142},[101,778,220],{"class":142},[101,780,781],{"class":155}," getUserRank",[101,783,226],{"class":118},[101,785,230],{"class":229},[101,787,233],{"class":118},[101,789,237],{"class":236},[101,791,240],{"class":118},[101,793,243],{"class":229},[101,795,233],{"class":118},[101,797,237],{"class":236},[101,799,260],{"class":118},[101,801,263],{"class":236},[101,803,266],{"class":118},[101,805,269],{"class":236},[101,807,808],{"class":118}," |",[101,810,811],{"class":236}," null",[101,813,272],{"class":118},[101,815,275],{"class":118},[101,817,819,821,823,825,827,829,831,833,835,837,839],{"class":103,"line":818},40,[101,820,281],{"class":142},[101,822,284],{"class":111},[101,824,287],{"class":118},[101,826,290],{"class":118},[101,828,293],{"class":122},[101,830,296],{"class":118},[101,832,230],{"class":111},[101,834,301],{"class":118},[101,836,304],{"class":122},[101,838,307],{"class":118},[101,840,129],{"class":118},[101,842,844],{"class":103,"line":843},41,[101,845,846],{"class":195},"  \u002F\u002F ZREVRANK liefert den 0-basierten Index absteigend sortiert\n",[101,848,850,852,855,857,859,861,863,866,868,870,872,874,876],{"class":103,"line":849},42,[101,851,281],{"class":142},[101,853,854],{"class":111}," rank",[101,856,287],{"class":118},[101,858,333],{"class":107},[101,860,336],{"class":111},[101,862,162],{"class":118},[101,864,865],{"class":155},"zrevrank",[101,867,226],{"class":344},[101,869,347],{"class":111},[101,871,240],{"class":118},[101,873,243],{"class":111},[101,875,63],{"class":344},[101,877,129],{"class":118},[101,879,881,883,885,888,890,893,895,897,899,902],{"class":103,"line":880},43,[101,882,365],{"class":107},[101,884,854],{"class":111},[101,886,887],{"class":118}," !==",[101,889,811],{"class":118},[101,891,892],{"class":118}," ?",[101,894,854],{"class":111},[101,896,706],{"class":118},[101,898,542],{"class":434},[101,900,901],{"class":118}," :",[101,903,904],{"class":118}," null;\n",[101,906,908],{"class":103,"line":907},44,[101,909,383],{"class":118},[38,911],{},[41,913,915],{"id":914},"_3-cooldown-verwaltung-mit-automatischer-ttl-verfallszeit","3. Cooldown-Verwaltung mit automatischer TTL-Verfallszeit",[21,917,918,919,922],{},"Befehls-Cooldowns (z. B. 5 Sekunden Pause zwischen ",[25,920,921],{},"\u002Fdaily",") erfordern keine persistente Speicherung. Mit Redis-TTL verfällt der Schlüssel automatisch:",[46,924,926],{"className":95,"code":925,"language":97,"meta":7,"style":7},"export async function checkRateLimit(userId: string, action: string, windowSeconds: number): Promise\u003C{ allowed: boolean; remainingSec: number }> {\n  const key = `ratelimit:${userId}:${action}`;\n\n  \u002F\u002F SET mit NX (nur setzen wenn nicht existiert) und EX (Ablaufzeit)\n  const acquired = await redis.set(key, '1', 'EX', windowSeconds, 'NX');\n\n  if (acquired === 'OK') {\n    return { allowed: true, remainingSec: 0 };\n  }\n\n  const ttl = await redis.ttl(key);\n  return { allowed: false, remainingSec: Math.max(0, ttl) };\n}\n",[25,927,928,993,1025,1029,1034,1092,1096,1120,1147,1151,1155,1181,1222],{"__ignoreMap":7},[101,929,930,932,934,936,939,941,944,946,948,950,953,955,957,959,962,964,966,968,970,972,975,977,980,982,985,987,989,991],{"class":103,"line":104},[101,931,214],{"class":107},[101,933,217],{"class":142},[101,935,220],{"class":142},[101,937,938],{"class":155}," checkRateLimit",[101,940,226],{"class":118},[101,942,943],{"class":229},"userId",[101,945,233],{"class":118},[101,947,237],{"class":236},[101,949,240],{"class":118},[101,951,952],{"class":229}," action",[101,954,233],{"class":118},[101,956,237],{"class":236},[101,958,240],{"class":118},[101,960,961],{"class":229}," windowSeconds",[101,963,233],{"class":118},[101,965,257],{"class":236},[101,967,260],{"class":118},[101,969,263],{"class":236},[101,971,447],{"class":118},[101,973,974],{"class":344}," allowed",[101,976,233],{"class":118},[101,978,979],{"class":236}," boolean",[101,981,456],{"class":118},[101,983,984],{"class":344}," remainingSec",[101,986,233],{"class":118},[101,988,257],{"class":236},[101,990,592],{"class":118},[101,992,275],{"class":118},[101,994,995,997,1000,1002,1004,1007,1009,1011,1013,1015,1017,1020,1023],{"class":103,"line":132},[101,996,281],{"class":142},[101,998,999],{"class":111}," key",[101,1001,287],{"class":118},[101,1003,290],{"class":118},[101,1005,1006],{"class":122},"ratelimit:",[101,1008,296],{"class":118},[101,1010,943],{"class":111},[101,1012,301],{"class":118},[101,1014,233],{"class":122},[101,1016,296],{"class":118},[101,1018,1019],{"class":111},"action",[101,1021,1022],{"class":118},"}`",[101,1024,129],{"class":118},[101,1026,1027],{"class":103,"line":139},[101,1028,136],{"emptyLinePlaceholder":135},[101,1030,1031],{"class":103,"line":187},[101,1032,1033],{"class":195},"  \u002F\u002F SET mit NX (nur setzen wenn nicht existiert) und EX (Ablaufzeit)\n",[101,1035,1036,1038,1041,1043,1045,1047,1049,1052,1054,1057,1059,1061,1064,1066,1068,1070,1073,1075,1077,1079,1081,1083,1086,1088,1090],{"class":103,"line":192},[101,1037,281],{"class":142},[101,1039,1040],{"class":111}," acquired",[101,1042,287],{"class":118},[101,1044,333],{"class":107},[101,1046,336],{"class":111},[101,1048,162],{"class":118},[101,1050,1051],{"class":155},"set",[101,1053,226],{"class":344},[101,1055,1056],{"class":111},"key",[101,1058,240],{"class":118},[101,1060,119],{"class":118},[101,1062,1063],{"class":122},"1",[101,1065,126],{"class":118},[101,1067,240],{"class":118},[101,1069,119],{"class":118},[101,1071,1072],{"class":122},"EX",[101,1074,126],{"class":118},[101,1076,240],{"class":118},[101,1078,961],{"class":111},[101,1080,240],{"class":118},[101,1082,119],{"class":118},[101,1084,1085],{"class":122},"NX",[101,1087,126],{"class":118},[101,1089,63],{"class":344},[101,1091,129],{"class":118},[101,1093,1094],{"class":103,"line":199},[101,1095,136],{"emptyLinePlaceholder":135},[101,1097,1098,1101,1103,1106,1109,1111,1114,1116,1118],{"class":103,"line":205},[101,1099,1100],{"class":107},"  if",[101,1102,81],{"class":344},[101,1104,1105],{"class":111},"acquired",[101,1107,1108],{"class":118}," ===",[101,1110,119],{"class":118},[101,1112,1113],{"class":122},"OK",[101,1115,126],{"class":118},[101,1117,644],{"class":344},[101,1119,647],{"class":118},[101,1121,1122,1125,1128,1130,1132,1136,1138,1140,1142,1144],{"class":103,"line":211},[101,1123,1124],{"class":107},"    return",[101,1126,1127],{"class":118}," {",[101,1129,974],{"class":344},[101,1131,233],{"class":118},[101,1133,1135],{"class":1134},"sfNiH"," true",[101,1137,240],{"class":118},[101,1139,984],{"class":344},[101,1141,233],{"class":118},[101,1143,532],{"class":434},[101,1145,1146],{"class":118}," };\n",[101,1148,1149],{"class":103,"line":278},[101,1150,729],{"class":118},[101,1152,1153],{"class":103,"line":312},[101,1154,136],{"emptyLinePlaceholder":135},[101,1156,1157,1159,1162,1164,1166,1168,1170,1173,1175,1177,1179],{"class":103,"line":317},[101,1158,281],{"class":142},[101,1160,1161],{"class":111}," ttl",[101,1163,287],{"class":118},[101,1165,333],{"class":107},[101,1167,336],{"class":111},[101,1169,162],{"class":118},[101,1171,1172],{"class":155},"ttl",[101,1174,226],{"class":344},[101,1176,1056],{"class":111},[101,1178,63],{"class":344},[101,1180,129],{"class":118},[101,1182,1183,1185,1187,1189,1191,1194,1196,1198,1200,1203,1205,1208,1210,1213,1215,1217,1219],{"class":103,"line":323},[101,1184,365],{"class":107},[101,1186,1127],{"class":118},[101,1188,974],{"class":344},[101,1190,233],{"class":118},[101,1192,1193],{"class":1134}," false",[101,1195,240],{"class":118},[101,1197,984],{"class":344},[101,1199,233],{"class":118},[101,1201,1202],{"class":111}," Math",[101,1204,162],{"class":118},[101,1206,1207],{"class":155},"max",[101,1209,226],{"class":344},[101,1211,1212],{"class":434},"0",[101,1214,240],{"class":118},[101,1216,1161],{"class":111},[101,1218,644],{"class":344},[101,1220,1221],{"class":118},"};\n",[101,1223,1224],{"class":103,"line":362},[101,1225,383],{"class":118},[38,1227],{},[41,1229,1231],{"id":1230},"_4-cache-invalidierung-postgresql-synchronisation","4. Cache-Invalidierung & PostgreSQL-Synchronisation",[21,1233,1234],{},"Um Datenverlust bei Server-Neustarts zu verhindern, synchronisieren wir geänderte Redis-Scores periodisch in die relationale PostgreSQL-Datenbank (Write-Behind-Pattern). Dies geschieht im Hintergrund alle 60 Sekunden ohne Blockierung des Discord-Event-Loops.",[1236,1237,1238],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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 .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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":7,"searchDepth":132,"depth":132,"links":1240},[1241,1242,1244,1245],{"id":43,"depth":132,"text":44},{"id":58,"depth":132,"text":1243},"2. Echtzeit-Ranglisten mit Redis Sorted Sets (ZSET)",{"id":914,"depth":132,"text":915},{"id":1230,"depth":132,"text":1231},"Wenn ein Discord-Bot auf Tausenden von Servern aktiv ist, führt jede Chat-Nachricht (XP-Vergabe, Level-Aufstiege, Cooldown-Prüfungen) zu Datenbank-Interaktionen. Würde jede Nachricht einen SQL-Befehl auf PostgreSQL absetzen (SELECT * FROM users WHERE id = ?), bricht der Datenbank-Verbindungspool bei hoher Aktivität schnell zusammen.","md",{},0,"\u002Fdocs\u002Fde\u002Fredis-cache-patterns",{"title":1252,"description":1246},{"High-Speed Redis Cache Patterns für Discord Bots":1253,"description":1254,"category":1255,"order":132,"author":1256,"readTime":1257,"lastUpdated":1258},"Sub-Millisekunden Leaderboards","Architekturleitfaden für Redis Caching in Discord-Bots. Sorted Sets für globale Leaderboards, Key-TTL Strategien und Cache-Invalidierung.","performance","Luca Lichtenwald","11 min","2026-10-09","docs\u002Fde\u002Fredis-cache-patterns","wc1CRxXggZbMNTRkgWQ04pFPemd-SI5JovvmAbbfFbI",{"enabled":135,"clientPubId":1262,"docsSlotId":7,"newsSlotId":7,"guidesSlotId":7,"dashboardSlotId":7,"docsEnabled":135,"newsEnabled":135,"guidesEnabled":135,"dashboardEnabled":135},"ca-pub-9454065621077312"]