Offline Queue: alapelvek, stratégiák és működési mechanizmusok

Szerző: IT Sectr Megjelenés: 2026-06-13 Olvasási idő: 10 perc

Offline Queue egy olyan mechanizmus, amely helyben tárolja a felhasználói műveleteket, amíg az eszköz offline állapotban van, és a kapcsolat helyreállítása után elküldi azokat a szerverre. Offline sor nélkül a felhasználó elveszíti az internet nélkül végzett összes műveletét, ami a mobilalkalmazásokban elfogadhatatlan. A Google Developers (2025) szerint az offline-first architektúra bevezetése 30%-kal növeli a felhasználói retenciót az instabil internettel rendelkező régiókban.

Főbb pontok

  • Offline Queue — a felhasználó által internet nélkül végzett műveletek FIFO sora a későbbi szinkronizáláshoz.
  • Persistent storage — a sor egy helyi adatbázisban (SQLite, Room) tárolódik az alkalmazás újraindításakor történő megőrzéshez.
  • Exponential backoff — az elküldés sikertelensége esetén növekvő időközzel történő újrapróbálkózási stratégia.
  • Conflict resolution — az ütközések feloldásának mechanizmusa, amikor az offline változtatások ütköznek a szerver adataival.
  • Idempotency keys — egyedi műveleti kulcsok a duplikáció megakadályozására a szerveren újraküldéskor.

Mi az offline sor?

Offline Queue egy rendezett gyűjteménye a műveleteknek (létrehozás, frissítés, törlés), amelyeket az alkalmazás helyben tárol, amikor az eszköz nem fér hozzá a hálózathoz. Amint a kapcsolat helyreáll, a sor ugyanabban a sorrendben küldi el a műveleteket a szerverre, ahogy a felhasználó végrehajtotta őket.

Képzeljen el egy forgatókönyvet: egy üzenetküldő alkalmazás felhasználója üzeneteket gépel a metróban internet nélkül. Minden „Küldés” gomb megnyomása hozzáadódik az Offline Queue-hoz. Amikor a vonat kijön az alagútból és megjelenik a hálózat, az összes üzenet automatikusan elküldésre kerül. A felhasználói élmény zökkenőmentes: nem veszi észre, hogy offline volt, csak egy enyhe késést érez a küldés során.

A Uber Engineering (2024) szerint az offline soruk több mint 2 millió műveletet dolgoz fel naponta az alacsony kapcsolati minőségű régiókban. A sor a helyi Room tárolót használja FIFO sorrenddel és exactly-once garantált kézbesítési mechanizmussal.

kotlin
data class QueuedOperation(
    val id: String,
    val type: OperationType,
    val endpoint: String,
    val payload: String,
    val timestamp: Long,
    val retryCount: Int = 0,
    val idempotencyKey: String
)

Minden művelet tartalmazza az újraküldéshez szükséges összes adatot: endpoint, kérés törzse, időbélyeg és idempotencyKey. A Room adatbázis garantálja a sor megőrzését az alkalmazás újraindításakor és operációs rendszer összeomlásakor.

Miért van szükség műveletsorra a mobilalkalmazásban

A kézbesítés garantálása a sor fő feladata. A felhasználónak biztosnak kell lennie abban, hogy a művelete (üzenet küldése, like, rendelés) végrehajtásra kerül, még akkor is, ha a hálózat nem érhető el a végrehajtás pillanatában. Az Offline Queue retry mechanizmussal eventually kézbesítést biztosít.

UX javítása gyenge kapcsolat mellett — a GSMA Mobile Economy Report (2025) szerint a világ mobilfelhasználóinak körülbelül 40%-a rendelkezik instabil internetkapcsolattal. Az Offline Queue használhatóvá teszi az alkalmazást a metróban, liftekben, távoli területeken — mindenhol, ahol a kapcsolat megszakadozik.

Adatveszteség csökkentése — sor nélkül az offline végrehajtott összes művelet elveszik. A felhasználó kitölthet egy hosszú űrlapot, megnyomhatja a „Küldés” gombot, és hálózati hibát láthat — az összes bevitt adat elvőszik. Az Offline Queue elmenti az adatokat, és az első adandó alkalommal elküldi őket. Az automatikus mentés a Google Docsban klasszikus példa az offline sorra dokumentumok esetében.

Aszinkron szinkronizálás — a sor lehetővé teszi az alkalmazás számára, hogy ne blokkolja a felületet a küldés idején. A felhasználó folytatja a munkát, míg a szinkronizáló kezelő a háttérben dolgozza fel a sort. Ez összhangban van a Reaktív Architektúra elveivel és javítja a felület érzékenységét.

Az offline sor architektúrája: tárolás és feldolgozás

A sor három rétege: tároló (persistence), ütemező (scheduler) és feldolgozó (executor). Tároló — Room QueuedOperation táblával. Ütemező — WorkManager (Android) vagy BGTaskScheduler (iOS), amely elindítja a szinkronizálást a hálózat megjelenésekor. Feldolgozó — egy szekvenciális FIFO iterátor, amely egyenként küldi el a műveleteket.

A feldolgozás sorrendje kritikus az adatok konzisztenciája szempontjából. Ha a felhasználó létrehozott egy rekordot, majd szerkesztette azt, mindkét műveletet ugyanabban a sorrendben kell elküldeni. Ellenkező esetben a szerver először egy nem létező rekord frissítését kapja — hiba. Sequential FIFO — szigorú sorrend a műveletek közötti függőségek ellenőrzésével.

Összevonási stratégia — ha a sorban egy objektumhoz CREATE és rögtön utána DELETE található, mindkét művelet törölhető küldés nélkül: a végállapot — az objektum nem jött létre. Hasonlóképpen, a CREATE + UPDATE CREATE összevonható egyetlen CREATE-vé a legújabb adatokkal. A sor optimalizálása csökkenti a HTTP-kérések számát és gyorsítja a szinkronizálást.

A Android Developers (2025) szerint a WorkManager az előnyös módszer az Offline Queue feldolgozására Androidon: garantálja a végrehajtást még az eszköz újraindítása után is, támogatja a hálózati elérhetőségre vonatkozó megszorításokat, és lehetővé teszi az újrapróbálkózási irányelv beállítását a NetworkType.CONNECTED segítségével.

kotlin
class SyncWorker(
    private val context: Context,
    private val params: WorkerParameters
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result = runCatching {
        queueRepository.processNextBatch(batchSize = 10)
        Result.success()
    }.getOrDefault(Result.retry())
}

A CoroutineWorker műveletkötegeket dolgoz fel, és sikertelenség esetén Result.retry()-t ad vissza — a WorkManager automatikusan újraindítja a végrehajtást exponenciális késleltetéssel. Ez a legegyszerűbb mód egy megbízható Offline Queue létrehozására Androidon.

Újrapróbálkózási stratégiák: exponential backoff és retry policy

Exponential Backoff — a szabványos ismétlési stratégia növekvő időközzel: 2 mp, 4 mp, 8 mp, 16 mp és így tovább a maximális küszöbértékig. Ez megakadályozza a szerver túlterhelését, ha az átmenetileg nem érhető el. A Resilience4j (2024) Java könyvtár kész Retry implementációt kínál konfigurálható backoff-fal.

A próbálkozások maximális száma — kritikus paraméter. Ha 5–10 próbálkozás után a művelet nem sikerült, a további próbálkozások hiábavalóak. Dead letter queue javasolt: a próbálkozások kimerülése után a művelet átkerül egy külön táblába kézi elemzéshez. A Microsoft Patterns & Practices (2024) szerint a dead letter queue leegyszerűsíti a szinkronizációs problémák hibakeresését és megakadályozza a sor blokkolását hibás műveletek által.

Jitter — véletlenszerű változtatás — véletlenszerű szám hozzáadása a backoff intervallumhoz. Ha ezer eszköz egyszerre állítja helyre a kapcsolatot a megszakítás után, mindegyik egyszerre kezdi meg a szinkronizálást. A Jitter időben szétszórja őket, megakadályozva a Cache Stampede-t a szerveren. Teljes jitter: delay = random(0, backoff) — az AWS (2024) által ajánlott API ügyfelek számára.

Konfliktusfeloldás: hogyan oldjuk fel az adatütközéseket

Last Write Wins (LWW) — a legegyszerűbb stratégia: ütközés esetén az újabb időbélyeggel rendelkező művelet nyer. Az LWW időszinkronizációt igényel — a timestamp-et a szerveren kell generálni, vagy Logical Clock-ot (Lamport-órákat) kell használni. Hátrány: egy felhasználó adatai figyelmeztetés nélkül felülírásra kerülhetnek egy másik felhasználó adatai által.

OT (Operational Transformation) — a Google Docs által használt algoritmus valós idejű együttes szerkesztéshez, beleértve az offline módot is. Az OT útgy alakítja át a műveleteket, hogy azok a dokumentum bármely állapotára alkalmazhatóak legyenek, biztosítva a konzisztenciát blokkolás nélkül. CRDT (Conflict-Free Replicated Data Types) — az OT alternatívája, amely egyre népszerűbb a mobilalkalmazásokban: az adatok úgy vannak strukturálva, hogy az ütközések matematikailag megoldhatóak legyenek, központi szerver nélkül.

Egyedi összevonás — egyszerű adatmodellel rendelkező alkalmazásokhoz (jegyzetek, névjegyzékek) egyedi összevonási szabályok implementálhatók. Például egy jegyzet esetén: ha a szöveg két változatban módosult, egyesítse őket konkatenációként elválasztójellel. Felhasználó által megoldott konfliktus — ha az automatikus összevonás nem lehetséges, mutassa meg a felhasználónak mindkét verziót, és kínáljon választási lehetőséget. A Dropbox (2024) ezt a megközelítést használja az offline fájlokban keletkező konfliktusokhoz, és másolatokat hoz létre „Conflicted Copy” előtaggal.

Idempotency keys — védelem a duplikáció ellen

Idempotency Key — a művelet egyedi azonosítója, amelyet a szerver a duplikált kérések észlelésére használ. Ha az ügyfél ugyanazt a kérést küldi el ugyanazzal a kulccsal, a szerver visszaadja a már végrehajtott művelet eredményét anélkül, hogy újra végrehajtaná. Ez kritikus fontosságú az Offline Queue számára, ahol az újraküldés hálózati hibák esetén előfordulhat.

Az idempotency key formátuma — UUID vagy a kérés paramétereinek hash-e. A szervernek tárolnia kell a végrehajtott kulcsokat az eredménnyel együtt egy ideig (általában 24 óráig) a duplikátumok észlelése érdekében. Stripe API (2024) — referencia példa: a kulcs az Idempotency-Key fejlécben kerül továbbításra, és az azonos kulccsal újraküldött kérések a gyorsítótárban tárolt választ adják vissza.

Generálás az ügyfél oldalán — a kulcs az ügyfélnél jön létre a művelet elküldése előtt, és a QueuedOperation táblában tárolódik. Újrapróbálkózáskor a kulcs nem változik. Exactly-once architektúra — az ügyfél oldali idempotency key és a szerver oldali deduplikáció kombinációja — az egyetlen mód annak garantálására, hogy egy művelet ne hajtódjon végre kétszer.

kotlin
fun createOperation(type: OperationType, payload: String): QueuedOperation =
    QueuedOperation(
        id = UUID.randomUUID().toString(),
        type = type,
        endpoint = type.endpoint,
        payload = payload,
        timestamp = currentTimeMillis(),
        idempotencyKey = UUID.randomUUID().toString()
    )

Minden művelet két UUID-t kap: egyet — a rekord azonosítóját a sorban, a másikat — idempotency key-t a szerver számára. A szerver oldali deduplikáció idempotencyKey alapján garantálja, hogy még újraküldés esetén sem duplikálódik a rendelés.

Gyakran ismételt kérdések

Miben különbözik az Offline Queue a gyorsítótártól?

A gyorsítótár (cache) adatmásolatokat tárol a gyors offline olvasáshoz. Az Offline Queue a felhasználói műveleteket tárolja a későbbi szerverre íráshoz. A cache olvasásra, a sor írásra működik. Mindkét összetevő együtt létezhet egy offline-first architektúrában.

Mekkora sorméret biztonságos egy mobileszköz számára?

Ajánlott korlát — 100–500 művelet. Több — a memória túlcsordulásának és a hosszú szinkronizálás kockázata a hálózat helyreállításakor. A korlát túllépésekor az alkalmazásnak figyelmeztetnie kell a felhasználót, és prioritásokat kell javasolnia a műveletekhez. Ésszerű korlátozás — 50 művelet frissítéshez + 10 létrehozáshoz.

Hogyan kezeljük az elavult műveleteket a sorban?

A 7 napnál régebbi műveletek nulla sikerességgel átkerülnek a dead letter queue-ba. Elemezze őket kézileg: talán az API megváltozott, és az endpoint már nem létezik. Automatikus takarítás — egy HealthCheck feladat naponta egyszer törli vagy archiválja a lejárt műveleteket.

Mit tegyünk, ha egy művelet függ egy előzőtől, amely még nem került elküldésre?

Használjon függőségi gráfot (DAG): minden művelet tartalmazza azon parentOperationId-k listáját, amelyeknek be kell fejeződniük a küldés előtt. A Room lekérdezés ORDER BY parent-tel a műveleteket a megfelelő sorrendben adja vissza. Kaszkád küldés — minden művelet befejezése után ellenőrizze, hogy a gyermek műveletek feloldásra kerültek-e.

Hogyan teszteljük az Offline Queue-t?

Használja a Network Less Tool eszközt Android Emulatorban vagy a Network Link Conditioner eszközt iOS Simulatorban a hálózatvesztés szimulálására. Írjon teszteket, amelyek offline módban műveleteket adnak a sorhoz, helyreállítják a kapcsolatot, és ellenőrzik, hogy az összes művelet elküldésre és a szerver általi feldolgozásra került-e.

Összefoglalás

  • Offline Queue — FIFO műveletsor, amelyet helyben tárol a kapcsolat helyreállítása utáni elküldéshez.
  • Persistent storage (Room / SQLite) — kötelező a sor megőrzéséhez az alkalmazás újraindításakor.
  • Exponential backoff jitter-rel — a szabványos ismétlési stratégia a szerver túlterhelésének megakadályozására.
  • Conflict resolution — LWW, OT, CRDT vagy egyedi szabályok az offline adatütközések feloldásához.
  • Idempotency key — az egyes műveletek UUID-je az exactly-once kézbesítés biztosításához a szerveren.
  • Dead letter queue — a problémás műveletek elkülönítése a próbálkozások kimerülése után kézi elemzéshez.
  • Legjobb gyakorlat Androidhoz — WorkManager + Room + ExponentialBackoff — a Google által bevált kombináció.

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is