AWS Solutions Architect · Lektion

Sessionslagring och topplistemönster

Använd ElastiCache för att avlasta HTTP-sessionsstatus från programservrarna och implementera topplistor i realtid med Redis-sorterade mängder.

Lektion 4 av 413 steg

Sessionslagring och topplistemönster är en gratis lektion i AWS Solutions Architect på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för AWS Solutions Architect, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i AWS Solutions Architect innehåller totalt 4 lektioner.

Problemet med serversidesessioner

Traditionella webbapplikationer lagrar sessionsdata i minnet på servern. Det fungerar med en enda server, men fallerar när Ni skalar horisontellt — om en användares efterföljande begäran dirigeras till en annan EC2-instans känner den instansen inte till användarens session, och användaren loggas ut. Sticky sessions (sessionstillhörighet i lastbalanseraren) löser delvis problemet, men minskar lastbalanseringens effektivitet. Den skalbara lösningen är att flytta sessionstillståndet till ett delat lager med låg latens som alla instanser kommer åt — exakt vad ElastiCache Redis tillhandahåller.

Redis för sessionslagring

Genom att lagra sessioner i Redis får Ni: läsningar av sessioner på under en millisekund från alla applikationsservrar, inbyggd TTL för automatisk sessionens utgång, atomiska sessionsuppdateringar som förhindrar race conditions samt möjlighet att omedelbart ogiltigförklara en session genom att ta bort nyckeln. Applikationen lagrar sessions-ID:t i en cookie och slår vid varje begäran upp sessions-ID:t i Redis för att hämta sessionsdata. Alla applikationsservrar delar samma Redis, så vilken server som helst kan hantera vilken användares begäran som helst.

# Session storage with Redis (Python Flask example)
import redis, json, uuid
from datetime import timedelta

redis_client = redis.Redis(host='prod-redis-primary', port=6379)
SESSION_TTL = int(timedelta(hours=8).total_seconds())

def create_session(user_id):
    session_id = str(uuid.uuid4())
    session_data = {'user_id': user_id, 'logged_in': True}
    redis_client.setex(f'session:{session_id}', SESSION_TTL, json.dumps(session_data))
    return session_id

def get_session(session_id):
    data = redis_client.get(f'session:{session_id}')
    return json.loads(data) if data else None

Sessionens TTL och glidande utgång

En fast TTL innebär att sessionen upphör N sekunder efter att den skapades, oavsett aktivitet. En glidande TTL (där utgångstiden förlängs vid varje åtkomst) är mer användarvänlig — sessionen upphör N sekunder efter den senaste åtkomsten. I Redis implementerar Ni glidande TTL genom att anropa EXPIRE (eller EXPIREAT) på sessionsnyckeln vid varje lyckad läsning av sessionen för att starta om nedräkningen till utgång. Då loggas aktiva användare aldrig oväntat ut, samtidigt som inaktiva sessioner löper ut automatiskt och frigör minne.

# Sliding TTL session implementation
def get_session_with_sliding_ttl(session_id, redis_client, ttl_seconds=1800):
    session_key = f'session:{session_id}'

    # Pipeline: GET + EXPIRE in one round trip
    pipe = redis_client.pipeline()
    pipe.get(session_key)
    pipe.expire(session_key, ttl_seconds)  # Reset TTL on access
    results = pipe.execute()

    data = results[0]
    if data:
        return json.loads(data)
    return None   # Session expired or not found

Varukorg i Redis

En varukorg i e-handeln passar naturligt för Redis. Varje varukorg lagras som en Redis Hash där fältet är produktens SKU och värdet är antalet. Hash-operationer som HINCRBY och HDEL möjliggör atomiska uppdateringar utan att hela varukorgen behöver hämtas och skrivas om. Tillsammans med en TTL (för att låta övergivna varukorgar upphöra efter 24 timmar) tillhandahåller Redis ett snabbt och beständigt lager för varukorgar utan kostnaden för en relationsdatabas vid varje händelse när en produkt läggs i varukorgen.

# Shopping cart operations using Redis Hash
cart_key = f'cart:{user_id}'

# Add item (or increase quantity)
# HINCRBY cart:user42 SKU-001 2
redis_client.hincrby(cart_key, 'SKU-001', 2)

# Remove item
# HDEL cart:user42 SKU-001
redis_client.hdel(cart_key, 'SKU-001')

# Get all items in cart
# HGETALL cart:user42
cart = redis_client.hgetall(cart_key)  # {b'SKU-001': b'2', b'SKU-002': b'1'}

# Set TTL for cart abandonment (24 hours)
redis_client.expire(cart_key, 86400)

Leaderboard-arkitektur

En leaderboard i realtid är ett klassiskt användningsområde för Redis som möjliggörs av sorterade mängder (ZSET). Varje spelarpost har en poäng, och den sorterade mängden håller alltid medlemmarna ordnade i stigande poängordning. Leaderboard-frågor (de N bästa spelarna, en spelares placering, spelare inom ett poängintervall) har komplexiteten O(log n) eller O(log n + m) — extremt snabbt även för miljontals spelare. Redis sorterade mängder utgör grunden för många funktioner för rankning inom spel, träning och sociala plattformar, utan att det krävs komplexa databasfrågor eller att placeringen beräknas om vid varje sidvisning.

# Real-time leaderboard with Redis Sorted Set

# Add or update a player's score
# ZADD game:weekly:leaderboard 15750 'player:alice'
redis_client.zadd('game:weekly:leaderboard', {'player:alice': 15750})

# Increment score (atomic)
# ZINCRBY game:weekly:leaderboard 500 'player:alice'
redis_client.zincrby('game:weekly:leaderboard', 500, 'player:alice')

# Get top 10 players (highest scores first)
# ZREVRANGE game:weekly:leaderboard 0 9 WITHSCORES
top_10 = redis_client.zrevrange('game:weekly:leaderboard', 0, 9, withscores=True)

Spelarplacering och närliggande spelare

Två vanliga leaderboard-funktioner utöver ”visa topp 10” är visa en spelares placering och visa spelare nära en viss spelare. Båda är triviala med Redis sorterade mängder. ZREVRANK returnerar en spelares nollbaserade placering i fallande poängordning. Om Ni vill visa 5 spelare ovanför och nedanför en spelare hämtar Ni först spelarens placering och använder sedan ZREVRANGE från placering-5 till placering+5. Det ger en personlig leaderboard-vy med två Redis-kommandon — inga komplexa SQL-fönsterfunktioner behövs.

# Get Alice's rank (0-indexed, so add 1 for display)
# ZREVRANK game:weekly:leaderboard 'player:alice'
rank = redis_client.zrevrank('game:weekly:leaderboard', 'player:alice')
print(f'Alice is rank #{rank + 1}')

# Get 5 players above and below Alice
start = max(0, rank - 5)
end = rank + 5
nearby = redis_client.zrevrange(
    'game:weekly:leaderboard', start, end, withscores=True
)
print('Players near Alice:', nearby)

Begränsning av anropsfrekvens med Redis

Begränsning av anropsfrekvens (att begränsa hur många anrop en klient kan göra under ett tidsintervall) är ett annat värdefullt användningsområde för Redis. Algoritmen med glidande fönster använder en sorterad mängd där varje medlem är en tidsstämpel för ett anrop. Vid varje anrop: ta bort medlemmar som är äldre än fönstret, räkna de återstående medlemmarna, avvisa anropet om antalet överskrider gränsen och lägg till den nya tidsstämpeln. Detta implementerar exakt begränsning med glidande fönster och millisekundupplösning — betydligt mer exakt än räknare med fasta fönster och utan belastning på databasen.

# Sliding window rate limiter (100 requests per 60 seconds)
import time

def is_rate_limited(user_id, redis_client, limit=100, window_seconds=60):
    key = f'ratelimit:{user_id}'
    now = time.time()
    window_start = now - window_seconds

    pipe = redis_client.pipeline()
    pipe.zremrangebyscore(key, '-inf', window_start)  # Remove old
    pipe.zcard(key)                                    # Count current
    pipe.zadd(key, {str(now): now})                   # Add this request
    pipe.expire(key, window_seconds)
    results = pipe.execute()

    request_count = results[1]
    return request_count >= limit  # True = rate limited

Distribuerad låsning med Redis

Distribuerade lås samordnar exklusiv åtkomst till en delad resurs mellan flera applikationsservrar. Redis-kommandot SET key value NX EX ttl tillhandahåller atomiskt förvärv av låset — det anger nyckeln endast om den inte redan finns (NX = Not eXists) och anger en TTL för att förhindra dödlägen om innehavaren kraschar. När åtgärden är klar tar innehavaren bort nyckeln. Redlock-algoritmen (som använder flera Redis-noder för att uppnå kvorum) ger ett robustare distribuerat lås, men ökar komplexiteten. För de flesta användningsområden räcker ett lås på en enda Redis-nod.

# Distributed lock with Redis SET NX EX
import uuid

def acquire_lock(redis_client, resource, ttl_seconds=30):
    lock_id = str(uuid.uuid4())  # Unique ID to identify this lock holder
    key = f'lock:{resource}'
    acquired = redis_client.set(key, lock_id, nx=True, ex=ttl_seconds)
    return lock_id if acquired else None

def release_lock(redis_client, resource, lock_id):
    key = f'lock:{resource}'
    # Only delete if we still own the lock (Lua script for atomicity)
    lua = 'if redis.call("get",KEYS[1])==ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end'
    redis_client.eval(lua, 1, key, lock_id)

Sessionslagring: ElastiCache jämfört med DynamoDB

Både ElastiCache Redis och DynamoDB kan lagra sessionsdata, men de har olika avvägningar. ElastiCache Redis: latens på mikrosekundnivå, minnesbaserat (flyktigt om inte beständig lagring har aktiverats), enklare datamodell och kräver VPC. DynamoDB: latens på ensiffrigt millisekundtal (DAX kan matcha Redis), fullt hanterat utan kluster att underhålla, beständigt som standard, global åtkomst med Global Tables, serverlöst med kapacitet på begäran. För SAA-C03-provet: om frågan betonar latens på mikrosekundnivå eller komplexa minnesbaserade åtgärder, väljer Ni Redis. Om den betonar beständighet, serverlöshet eller global skala, bör Ni överväga DynamoDB.

Geospatial indexering med Redis

Redis har en inbyggd geospatial datatyp (GEO-kommandon) som lagrar latitud- och longitudkoordinater och möjliggör närhetsfrågor. Med GEOADD, GEODIST och GEORADIUS (numera GEOSEARCH i Redis 6.2) kan Ni hitta alla platser inom en angiven radie från en punkt på O(n + log n)-tid. Användningsområden är att hitta närliggande förare (samåkningstjänster), hitta restauranger inom 5 km och sortera sökresultat efter avstånd. Det eliminerar behovet av en separat geospatial databas och håller platsfrågor på minnesbaserad hastighetsnivå.

# Store driver locations
# GEOADD drivers 13.361389 38.115556 'driver:001'
# GEOADD drivers 15.087269 37.502669 'driver:002'

# Find all drivers within 10 km of a point
# GEOSEARCH drivers FROMLONLAT 13.5 38.1 BYRADIUS 10 km ASC COUNT 5 WITHCOORD

# Result: sorted list of driver IDs within 10 km with coordinates

HyperLogLog för räkning av unika besökare

En HyperLogLog är en probabilistisk datastruktur som uppskattar antalet unika element i en mängd med en fast mängd minne (12 KB i Redis), oavsett hur många unika objekt som läggs till. Den ger ett standardfel på ungefär 0,81 %. Använd PFADD för att lägga till element och PFCOUNT för att hämta uppskattningen. Detta passar perfekt för att räkna unika dagliga aktiva användare, unika sidvisningar eller unika IP-adresser när exakta antal inte krävs och minneseffektivitet är viktig. Att lagra miljontals unika användar-ID:n som en Redis Set skulle förbruka flera GB; HyperLogLog använder 12 KB.

# Count unique daily visitors using HyperLogLog
date = '2024-01-15'
hll_key = f'unique_visitors:{date}'

# Track a visitor (PFADD is idempotent for the same user)
# PFADD unique_visitors:2024-01-15 'user:12345'
redis_client.pfadd(hll_key, 'user:12345')
redis_client.pfadd(hll_key, 'user:67890')
redis_client.pfadd(hll_key, 'user:12345')  # Duplicate — not counted again

# Get estimated unique visitor count
# PFCOUNT unique_visitors:2024-01-15
count = redis_client.pfcount(hll_key)
print(f'Unique visitors today (estimate): {count}')

Snabbkontroll

Testa Er förståelse av begreppen från AWS Solutions Architect (SAA-C03) i den här lektionen.

Lektionssammanfattning

I den här lektionen har Ni lärt Er att: Redis-sessionslagring möjliggör tillståndslös horisontell skalning genom att ge alla instanser åtkomst till ett delat sessionstillstånd med submillisekundlatens, Redis sorterade mängder driver leaderboards i realtid med placeringsfrågor med komplexiteten O(log n), och specialiserade Redis-datatyper (HyperLogLog för unika antal, GEO för närhet och distribuerade lås) löser vanliga arkitekturproblem effektivt. Därmed är kursen Caching with ElastiCache slutförd — härnäst utforskar vi arkitekturer med hög tillgänglighet och feltolerans.

Gratis att börja

Lär dig AWS Solutions Architect med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
30
Lektioner
120

Vanliga frågor

Är lektionen ”Sessionslagring och topplistemönster” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen AWS Solutions Architect, inklusive ”Sessionslagring och topplistemönster”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i AWS Solutions Architect innehåller totalt 4 lektioner.

Vad lär jag mig i ”Sessionslagring och topplistemönster”?

Använd ElastiCache för att avlasta HTTP-sessionsstatus från programservrarna och implementera topplistor i realtid med Redis-sorterade mängder. Ni övar på AWS Solutions Architect med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig AWS Solutions Architect?

Du behöver inga förkunskaper. Utbildningen i AWS Solutions Architect på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Sessionslagring och topplistemönster”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här AWS Solutions Architect-lektionen?

Ja. Varje AWS Solutions Architect-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Redis jämfört med Memcached: Välj rätt motor
  2. ElastiCache Redis-replikeringsgrupper och klusterläge
  3. Cachelagringsstrategier: Lazy Loading och Write-Through
  4. Sessionslagring och topplistemönster
← Tillbaka till AWS Solutions Architect