Sdílet prostřednictvím


Vytvořte vlastní stavovou aplikaci

Důležitý

Tato funkce je ve verzi Public Preview v Databricks Runtime 16.2 a novějších verzích.

Aplikace streamování můžete vytvářet pomocí vlastních stavových operátorů k implementaci řešení s nízkou latencí a téměř v reálném čase, která používají libovolnou stavovou logiku. Vlastní stavové operátory odemykají nové operační případy použití a vzory, které nejsou dostupné prostřednictvím tradičního zpracování ve strukturovaném streamování.

Poznámka

Databricks doporučuje používat integrované funkce strukturovaného streamování pro podporované stavové operace, jako jsou agregace, odstranění duplicitních dat a spojení streamování. Pro více informací viz Co je stavové streamování?.

Databricks doporučuje používat transformWithState u starších operátorů pro libovolné transformace stavu. Dokumentaci ke starším operátorům flatMapGroupsWithState a mapGroupsWithState najdete v tématu Starší libovolné stavové operátory.

Požadavky

Operátor transformWithState a související rozhraní API a třídy mají následující požadavky:

  • K dispozici v Databricks Runtime 16.2 a novějších.
  • Výpočetní prostředky musí používat vyhrazený režim přístupu nebo režim přístupu bez izolace, kromě standardního režimu přístupu se podporuje pro Python (transformWithStateInPandas) v Databricks Runtime 16.3 a novější a pro Scala (transformWithState) v Databricks Runtime 17.3 a vyšší.
  • Musíte použít poskytovatele úložiště stavů RocksDB. Databricks doporučuje povolit RocksDB jako součást konfigurace výpočetních prostředků.

Poznámka

Pokud chcete pro aktuální relaci povolit poskytovatele úložiště stavů RocksDB, spusťte následující příkaz:

spark.conf.set("spark.sql.streaming.stateStore.providerClass", "org.apache.spark.sql.execution.streaming.state.RocksDBStateStoreProvider")

Co je transformWithState?

Operátor transformWithState použije vlastní stavový procesor na dotaz strukturovaného streamování. Je nutné implementovat vlastní stavový procesor pro použití transformWithState. Strukturované streamování zahrnuje rozhraní API pro vytváření stavového procesoru pomocí Pythonu, Scaly nebo Javy.

Pomocí transformWithState použijete vlastní logiku pro seskupovací klíč pro záznamy zpracovávané přírůstkově pomocí strukturovaného streamování. Následující informace popisují návrh vysoké úrovně:

  • Definujte jednu nebo více proměnných stavu.
  • Informace o stavu se uchovávají pro každý klíč seskupení a můžou být přístupné pro každou proměnnou stavu podle uživatelem definované logiky.
  • Pro každou zpracovanou mikrodávku jsou všechny záznamy pro daný klíč k dispozici jako iterátor.
  • Pomocí vestavěných manipulátorů můžete řídit, kdy a jak se záznamy emitují na základě časovačů a uživatelsky definovaných podmínek.
  • Hodnoty stavu podporují jednotlivé definice TTL (Time to Live), což umožňuje flexibilitu při správě vypršení platnosti stavu a velikosti stavu.

Vzhledem k tomu, že transformWithState podporuje vývoj schématu v úložišti stavů, můžete iterovat a aktualizovat produkční aplikace bez ztráty historických informací o stavu nebo nutnosti znovu zpracovat záznamy, což poskytuje flexibilitu pro vývoj a snadnou údržbu. Viz vývoj schématu v úložišti stavů.

Důležitý

PySpark používá operátor transformWithStateInPandas místo transformWithState. Dokumentace ke službě Azure Databricks používá transformWithState k popisu funkcí pro implementace Pythonu i Scala.

Implementace jazyka Scala a Pythonu transformWithState a souvisejících rozhraní API se liší kvůli specifikám jazyka, ale poskytují stejné funkce. Projděte si příklady specifické pro jazyk a dokumentaci k rozhraní API pro preferovaný programovací jazyk.

Vestavěné zpracovatelské mechanismy

Základní logiku vlastní stavové aplikace implementujete implementací obslužných rutin pomocí integrovaných popisovačů .

  • Popisovače poskytují metody pro interakci se stavovými hodnotami a časovači, zpracování příchozích záznamů a odesílání záznamů.
  • Obslužné rutiny definují vaši vlastní logiku řízenou událostmi.

Popisovače pro každý typ stavu jsou implementovány na základě podkladové datové struktury, přičemž každý obsahuje funkce pro získání, vložení, aktualizaci a odstranění záznamů.

Obslužné programy se implementují na bázi událostí pozorovaných ve vstupních záznamech nebo na základě časovačů pomocí následující sémantiky:

  • Definujte obslužnou rutinu pomocí metody handleInputRows pro řízení způsobu zpracování dat, aktualizaci stavu a emitování záznamů pro každou zpracovanou mikrosávku záznamů skupinového klíče. Viz Zpracování vstupních řádků.
  • Definujte obslužnou rutinu pomocí metody handleExpiredTimer pro použití prahových hodnot založených na čase ke spuštění logiky, zda se pro klíč seskupení zpracovávají další záznamy. Viz Časované události programu.

Následující tabulka obsahuje porovnání funkčních chování podporovaných těmito obslužnými rutinami:

Chování handleInputRows handleExpiredTimer
Získání, vložení, aktualizace nebo vymazání hodnot stavu Ano Ano
Vytvoření nebo odstranění časovače Ano Ano
Vydání záznamů Ano Ano
Procházet záznamy v aktuální mikrodávce Ano Ne
Logika triggeru založená na uplynulé době Ne Ano

Pomocí kombinace handleInputRows a handleExpiredTimer můžete podle potřeby implementovat složitou logiku.

Můžete například implementovat aplikaci, která používá handleInputRows k aktualizaci hodnot stavu pro každou mikrodávku a nastavit časovač 10 sekund v budoucnu. Pokud se nezpracují žádné další záznamy, můžete použít handleExpiredTimer k vygenerování aktuálních hodnot v úložišti stavů. Pokud se pro klíč seskupení zpracovávají nové záznamy, můžete vymazat existující časovač a nastavit nový časovač.

vlastní typy stavů

V jednom stavovém operátoru můžete implementovat více stavových objektů. Názvy, které dáte každému objektu stavu, se zachovají v úložišti stavů, ke kterému máte přístup pomocí čtečky úložiště stavů. Pokud váš stavový objekt používá StructType, zadáte názvy pro každé pole ve struktuře při předávání schématu. Tyto názvy jsou také viditelné při čtení stavového úložiště. Viz Informace o stavu strukturovaného streamování.

Funkce poskytované integrovanými třídami a operátory mají poskytovat flexibilitu a rozšiřitelnost a volby implementace by měly být informovány úplnou logikou, kterou vaše aplikace potřebuje ke spuštění. Můžete například implementovat téměř identickou logiku pomocí ValueState seskupených podle polí user_id a session_id nebo MapState seskupených podle user_id, kde session_id je klíčem pro MapState. V tomto případě může být upřednostňovanou implementací MapState, pokud logika potřebuje vyhodnotit podmínky napříč několika session_ids.

Následující části popisují typy stavů podporované transformWithState.

ValueState

Pro každý klíč seskupení je přidružená hodnota.

Stav hodnoty může zahrnovat komplexní typy, například strukturu nebo řazenou kolekci členů. Při aktualizaci ValueStateimplementujete logiku, která nahradí celou hodnotu. TTL pro stav hodnoty se resetuje, když se hodnota aktualizuje, ale není resetován, pokud je zpracován zdrojový klíč odpovídající ValueState bez aktualizace uloženého ValueState.

ListState

Pro každý klíč seskupení je přidružený seznam.

Stav seznamu je kolekce hodnot, z nichž každý může obsahovat složité typy. Každá hodnota v seznamu má vlastní hodnotu TTL. Položky můžete přidat do seznamu tak, že připojíte jednotlivé položky, připojíte seznam položek nebo přepíšete celý seznam pomocí put. Za aktualizaci pro resetování hodnoty TTL se považuje pouze operace put.

Stav mapy

Pro každý klíč seskupení je přidružená mapa. Mapy jsou funkčním ekvivalentem Apache Sparku k dict Pythonu.

Důležitý

Klíče seskupení popisují pole zadaná v klauzuli GROUP BY dotazu strukturovaného streamování. Stavy mapy obsahují libovolný počet párů klíč-hodnota pro seskupující klíč.

Pokud například seskupíte podle user_id a chcete definovat mapu pro každý session_id, klíč seskupení je user_id a klíč v mapě je session_id.

Stav mapy je kolekce jedinečných klíčů, které každý mapuje na hodnotu, která může obsahovat komplexní typy. Každý pár klíč-hodnota v mapě má vlastní hodnotu TTL. Můžete aktualizovat hodnotu konkrétního klíče nebo odebrat klíč a jeho hodnotu. Jednotlivou hodnotu můžete vrátit pomocí klíče, zobrazit seznam všech klíčů, zobrazit seznam všech hodnot nebo vrátit iterátor pro práci s úplnou sadou párů klíč-hodnota v mapě.

Inicializovat vlastní proměnnou stavu

Při inicializaci StatefulProcessorvytvoříte místní proměnnou pro každý objekt stavu, který umožňuje interakci se stavovými objekty ve vlastní logice. Stavové proměnné jsou definovány a inicializovány přepsáním integrované metody init ve třídě StatefulProcessor.

Pomocí getValueState, getListStatea getMapState metod při inicializaci StatefulProcessordefinujete libovolné množství stavových objektů .

Každý objekt stavu musí mít následující:

  • Jedinečný název
  • Zadané schéma
    • V Pythonu je schéma explicitně zadáno.
    • V jazyce Scala předejte Encoder k určení schématu stavu.

Můžete také zadat volitelnou dobu trvání TTL (Time to Live) v milisekundách. Pokud implementujete stav mapování, musíte zadat samostatnou definici schématu pro klíče mapování a hodnoty.

Poznámka

Logika pro dotazování, aktualizaci a vygenerování informací o stavu se zpracovává samostatně. Viz Použijte vaše stavové proměnné.

Příklad stavové aplikace

Následující příklad ukazuje základní syntaxi pro definování a použití vlastního stavového procesoru s transformWithState, včetně ukázkových stavových proměnných pro každý podporovaný typ. Další příklady najdete v tématu Příklad stavových aplikací.

Poznámka

Python používá řazené kolekce členů pro všechny interakce se stavovými hodnotami. To znamená, že kód Pythonu by měl předávat hodnoty pomocí řazených kolekcí členů při použití operací, jako jsou put a update, a při použití getočekává zpracování řazených kolekcí členů.

Pokud je například schéma pro váš stav hodnoty jen jedno celé číslo, implementovali byste kód podobný tomuto:

current_value_tuple = value_state.get() # Returns the value state as a tuple
current_value = current_value_tuple[0]  # Extracts the first item in the tuple
new_value = current_value + 1           # Calculate a new value
value_state.update((new_value,))        # Pass the new value formatted as a tuple

To platí také pro položky v ListState nebo hodnoty v MapState.

Python

import pandas as pd
from pyspark.sql import Row
from pyspark.sql.streaming import StatefulProcessor, StatefulProcessorHandle
from pyspark.sql.types import StructType, StructField, IntegerType, StringType
from typing import Iterator

spark.conf.set("spark.sql.streaming.stateStore.providerClass","org.apache.spark.sql.execution.streaming.state.RocksDBStateStoreProvider")

output_schema = StructType(
    [
        StructField("id", StringType(), True),
        StructField("countAsString", StringType(), True),
    ]
)

class SimpleCounterProcessor(StatefulProcessor):
  def init(self, handle: StatefulProcessorHandle) -> None:
    value_state_schema = StructType([StructField("count", IntegerType(), True)])
    list_state_schema = StructType([StructField("count", IntegerType(), True)])
    self.value_state = handle.getValueState(stateName="valueState", schema=value_state_schema)
    self.list_state = handle.getListState(stateName="listState", schema=list_state_schema)
    # Schema can also be defined using strings and SQL DDL syntax
    self.map_state = handle.getMapState(stateName="mapState", userKeySchema="name string", valueSchema="count int")

  def handleInputRows(self, key, rows, timerValues) -> Iterator[pd.DataFrame]:
    count = 0
    for pdf in rows:
      list_state_rows = [(120,), (20,)] # A list of tuples
      self.list_state.put(list_state_rows)
      self.list_state.appendValue((111,))
      self.list_state.appendList(list_state_rows)
      pdf_count = pdf.count()
      count += pdf_count.get("value")
    self.value_state.update((count,)) # Count is passed as a tuple
    iter = self.list_state.get()
    list_state_value = next(iter1)[0]
    value = count
    user_key = ("user_key",)
    if self.map_state.exists():
      if self.map_state.containsKey(user_key):
        value += self.map_state.getValue(user_key)[0]
    self.map_state.updateValue(user_key, (value,)) # Value is a tuple
    yield pd.DataFrame({"id": key, "countAsString": str(count)})

q = (df.groupBy("key")
  .transformWithStateInPandas(
    statefulProcessor=SimpleCounterProcessor(),
    outputStructType=output_schema,
    outputMode="Update",
    timeMode="None",
  )
  .writeStream...
)

Scala

import org.apache.spark.sql.streaming._
import org.apache.spark.sql.{Dataset, Encoder, Encoders , DataFrame}
import org.apache.spark.sql.types._
import org.apache.spark.sql.functions._

spark.conf.set("spark.sql.streaming.stateStore.providerClass","org.apache.spark.sql.execution.streaming.state.RocksDBStateStoreProvider")

class SimpleCounterProcessor extends StatefulProcessor[String, (String, String), (String, String)] {
  @transient private var countState: ValueState[Int] = _
  @transient private var listState: ListState[Int] = _
  @transient private var mapState: MapState[String, Int] = _

  override def init(
      outputMode: OutputMode,
      timeMode: TimeMode): Unit = {
    countState = getHandle.getValueState[Int]("countState",
      Encoders.scalaLong, TTLConfig.NONE)
    listState = getHandle.getListState[Int]("listState",
      Encoders.scalaInt, TTLConfig.NONE)
    mapState = getHandle.getMapState[String, Int]("mapState",
      Encoders.STRING, Encoders.scalaInt, TTLConfig.NONE)
  }

  override def handleInputRows(
      key: String,
      inputRows: Iterator[(String, String)],
      timerValues: TimerValues): Iterator[(String, String)] = {
    var count = countState.getOption().getOrElse(0)
    for (row <- inputRows) {
      val listData = Array(120, 20)
      listState.put(listData)
      listState.appendValue(count)
      listState.appendList(listData)
      count += 1
    }
    val iter = listState.get()
    var listStateValue = 0
    if (iter.hasNext) {
      listStateValue = iter.next()
    }
    countState.update(count)
    var value = count
    val userKey = "userKey"
    if (mapState.exists()) {
      if (mapState.containsKey(userKey)) {
        value += mapState.getValue(userKey)
      }
    }
    mapState.updateValue(userKey, value)
    Iterator((key, count.toString))
  }
}

val q = spark
        .readStream
        .format("delta")
        .load("$srcDeltaTableDir")
        .as[(String, String)]
        .groupByKey(x => x._1)
        .transformWithState(
            new SimpleCounterProcessor(),
            TimeMode.None(),
            OutputMode.Update(),
        )
        .writeStream...

StatefulProcessorHandle

PySpark obsahuje třídu StatefulProcessorHandle, která poskytuje přístup k funkcím, které řídí způsob interakce uživatelem definovaného kódu Pythonu s informacemi o stavu. Vždy musíte importovat StatefulProcessorHandle a předat ho proměnné handle při inicializaci StatefulProcessor.

Proměnná handle propojuje místní proměnnou ve vaší třídě Pythonu s proměnnou stavu.

Poznámka

Scala používá metodu getHandle.

Zadání počátečního stavu

Volitelně můžete zadat počáteční stav pro použití s první mikrodávkou. To může být užitečné při migraci existujícího pracovního postupu do nové vlastní aplikace, upgradu stavového operátora na změnu schématu nebo logiky nebo při opravě selhání, které nelze automaticky opravit a vyžaduje ruční zásah.

Poznámka

Pomocí čtečky úložiště stavů můžete dotazovat informace o stavu z existujícího kontrolního bodu. Viz Informace o stavu strukturovaného streamování.

Pokud převádíte existující tabulku Delta na stavovou aplikaci, přečtěte si tabulku pomocí spark.read.table("table_name") a předejte výsledný datový rámec. Volitelně můžete vybrat nebo upravit pole tak, aby odpovídala vaší nové stavové aplikaci.

Počáteční stav zadáte pomocí datového rámce se stejným schématem klíče seskupení jako vstupní řádky.

Poznámka

Python používá handleInitialState k určení počátečního stavu při definování StatefulProcessor. Scala používá odlišnou třídu StatefulProcessorWithInitialState.

Použití stavových proměnných

Podporované stavové objekty poskytují metody pro získání stavu, aktualizaci existujících informací o stavu nebo vymazání aktuálního stavu. Každý podporovaný typ stavu má jedinečnou implementaci metod, které odpovídají implementované datové struktuře.

Každý zjištěný klíč seskupení obsahuje vyhrazené informace o stavu.

  • Záznamy se vygenerují na základě logiky, kterou implementujete, a pomocí zadaného výstupního schématu. Podívejte se na Emit záznamy.
  • K hodnotám v úložišti stavů můžete přistupovat pomocí čtečky statestore. Tato čtečka má dávkové funkce a není určená pro úlohy s nízkou latencí. Viz Informace o stavu strukturovaného streamování.
  • Logika zadaná pomocí handleInputRows se aktivuje pouze tehdy, když jsou v mikrodávce přítomny záznamy pro daný klíč. Viz Zpracování vstupních řádků.
  • Použijte handleExpiredTimer pro implementaci logiky založené na čase, která nezávisí na pozorování záznamů. Viz Časované události programu.

Poznámka

Objekty stavu jsou izolované pomocí seskupení klíčů s následujícími důsledky:

  • Hodnoty stavu nemohou být ovlivněny záznamy přidruženými k jinému klíči seskupení.
  • nemůžete implementovat logiku, která závisí na porovnávání hodnot nebo aktualizaci stavu napříč klíči seskupení.

Hodnoty v rámci klíče seskupení můžete porovnat. Použijte MapState k implementaci logiky s druhým klíčem, který může vaše vlastní logika použít. Například seskupení podle user_id a vytvoření klíče MapState pomocí IP adresy vám umožní implementovat logiku, která sleduje souběžné uživatelské relace.

Pokročilé aspekty práce se stavem

Zápis do stavové proměnné aktivuje zápis do RocksDB. Pro optimalizaci výkonu doporučuje Databricks zpracovávat všechny hodnoty v iterátoru pro daný klíč a provádět aktualizace v rámci jednoho zápisu, kdykoli je to možné.

Poznámka

Aktualizace stavu jsou odolné proti chybám. Pokud se úloha chybově ukončí před dokončením zpracování mikrodávkové dávky, použije se hodnota z poslední úspěšné mikrodávky při opakování.

Hodnoty stavu nemají žádné předdefinované výchozí hodnoty. Pokud vaše logika vyžaduje čtení existujících informací o stavu, použijte při implementaci logiky metodu exists.

Poznámka

MapState proměnné mají další funkce ke kontrole jednotlivých klíčů nebo výpisu všech klíčů pro implementaci logiky pro stav null.

Vydání záznamů

Uživatelsky definovaná logika řídí, jak transformWithState generuje záznamy. Záznamy se vydávají podle klíče seskupení.

Vlastní stavové aplikace nepředpokládají, jak se informace o stavu používají při určování způsobu generování záznamů a vrácený počet záznamů pro danou podmínku může být žádný, jeden nebo mnoho.

Implementujete logiku pro generování záznamů pomocí handleInputRows nebo handleExpiredTimer. Viz Zpracování vstupních řádků a programování časovaných událostí.

Poznámka

Můžete implementovat více hodnot stavu a definovat více podmínek pro generování záznamů, ale všechny vygenerované záznamy by měly používat stejné schéma.

Python

V Pythonu definujete výstupní schéma pomocí klíčového slova outputStructType při volání transformWithStateInPandas.

Vysíláte záznamy pomocí objektu pandas DataFrame a yield.

Volitelně můžete yield prázdný datový rámec. Při kombinaci s update výstupním režimem emitování prázdného datového rámce nastaví hodnoty klíče seskupení na null.

Scala

V jazyce Scala generujete záznamy pomocí objektu Iterator. Schéma výstupu je odvozeno z vygenerovaných záznamů.

Volitelně můžete emitovat prázdný element Iterator. Když se kombinuje s výstupním režimem update, vydání prázdného Iterator aktualizuje hodnoty klíče seskupení na null.

Zpracování vstupních řádků

Pomocí metody handleInputRows definujte logiku, jak záznamy pozorované ve streamovacím dotazu pracují s hodnotami stavu a aktualizují se. Obslužná rutina, kterou definujete pomocí metody handleInputRows, se spustí pokaždé, když se všechny záznamy zpracovávají prostřednictvím dotazu strukturovaného streamování.

Pro většinu stavových aplikací implementovaných s transformWithStateje základní logika definována pomocí handleInputRows.

Pro každou zpracovanou aktualizaci mikrodávkové dávky jsou všechny záznamy v mikrodávce pro daný klíč seskupení k dispozici pomocí iterátoru. Uživatelsky definovaná logika může pracovat se všemi záznamy z aktuálního mikrobatchu a hodnot v úložišti stavů.

Časované události programu

Pomocí časovačů můžete implementovat vlastní logiku založenou na uplynulém čase ze zadané podmínky.

S časovači pracujete implementací metody handleExpiredTimer.

V rámci klíče seskupení jsou časovače jednoznačně identifikovány jejich časovým razítkem.

Když vyprší platnost časovače, výsledek se určuje logikou implementovanou ve vaší aplikaci. Mezi běžné vzory patří:

  • Vysílání informací uložených v proměnné stavu
  • Vyřazení uložených informací o stavu
  • Vytvoření nového časovače

Časovače s vypršenou platností se aktivují, i když se v mikrodávce nezpracují žádné záznamy pro jejich přidružený klíč.

Určení časového modelu

Při předávání StatefulProcessor k transformWithStateje nutné zadat časový model. Podporují se následující možnosti:

  • ProcessingTime
  • EventTime
  • NoTime nebo TimeMode.None()

Zadání NoTime znamená, že časovače nejsou pro váš procesor podporovány.

Předdefinované hodnoty časovače

Databricks doporučuje nevyvolání systémových hodin ve vlastní stavové aplikaci, protože to může vést k nespolehlivému opakování při selhání úlohy. Metody ve třídě TimerValues použijte, když potřebujete získat přístup k času zpracování nebo vodoznaku:

TimerValues Popis
getCurrentProcessingTimeInMs Vrátí časové razítko času zpracování aktuální dávky v milisekundách od počátku epochy.
getCurrentWatermarkInMs Vrátí časové razítko vodotisku pro aktuální dávku v milisekundách od počátku epochy.

Poznámka

Doba zpracování popisuje čas, kdy je mikrodávka zpracována Apache Sparkem. Mnoho streamovacích zdrojů, jako je Kafka, zahrnuje také dobu zpracování systému.

Vodoznaky u streamovaných dotazů se často definují proti času události nebo času zpracování zdroje streamování. Viz Použití vodoznaků k řízení prahových hodnot zpracování dat.

Vodoznaky i okna lze použít v kombinaci s transformWithState. Ve své vlastní stavové aplikaci můžete podobné funkce implementovat s využitím TTL, časovačů a funkce MapState nebo ListState.

Jaký je stav tTL (State Time to Live)?

Hodnoty stavu používané transformWithState každá podporují volitelnou specifikaci doby životnosti (TTL). Po vypršení platnosti hodnoty TTL se hodnota vyřadí z úložiště stavů. TTL interaguje pouze s hodnotami v úložišti stavů, což znamená, že můžete implementovat logiku pro odstranění informací o stavu, ale nemůžete přímo spustit logiku, jelikož TTL odstraňuje stavové hodnoty.

Důležitý

Pokud neimplementujete TTL, musíte zpracovat odstranění stavu pomocí jiné logiky, abyste se vyhnuli nekonečnému růstu stavu.

TTL se uplatňuje pro každý stav s různými pravidly pro každý typ stavu.

  • Stavové proměnné jsou vztaženy ke seskupovacím klíčům.
  • Pro ValueState objekty je uložena pouze jedna hodnota na klíč seskupení. Hodnota TTL se vztahuje na tuto hodnotu.
  • Pro ListState objekty může seznam obsahovat mnoho hodnot. Hodnota TTL se vztahuje na každou hodnotu v seznamu nezávisle.
  • Pro MapState objekty má každý klíč mapy přidruženou hodnotu stavu. TTL se použije nezávisle na každém páru klíč-hodnota v mapě.

Pro všechny typy stavů se hodnota TTL resetuje, pokud se aktualizují informace o stavu.

Poznámka

Zatímco hodnota TTL je vymezena na jednotlivé hodnoty v ListState, jediným způsobem, jak aktualizovat hodnotu v seznamu, je použít metodu put k přepsání celého obsahu proměnné ListState.

Jaký je rozdíl mezi časovači a TTL?

Existuje určitý překryv mezi časovači a časem života (TTL) pro stavové proměnné, ale časovače poskytují širší škálu funkcí než hodnota TTL.

TTL odstraní informace o stavu, které nebyly aktualizovány během uživatelem stanovené doby. To umožňuje uživatelům zabránit nezaškrtnutému růstu stavu a odebrat zastaralé položky stavu. Vzhledem k tomu, že mapy a seznamy implementují hodnotu TTL pro každou hodnotu, můžete implementovat funkce, které zvažují pouze hodnoty stavu, které byly nedávno aktualizovány nastavením hodnoty TTL.

Časovače umožňují definovat vlastní logiku, která přesahuje odstranění datového stavu, včetně vydávání záznamů. Volitelně můžete použít časovače k vymazání informací o stavu pro danou hodnotu stavu s větší flexibilitou pro generování hodnot nebo aktivaci jiné podmíněné logiky na základě časovače.