Versionado, listado y almacenamiento en caché de datos

*Este contenido se traduce usando la IA (Beta) y puede contener errores. Para ver esta página en inglés, haz clic en aquí.

Gestiona tus datos utilizando versionado, listado y almacenamiento en caché.

Versionado

El versionado ocurre cuando configuras, actualizas e incrementas datos. Las funciones SetAsync(), UpdateAsync(), y IncrementAsync() crean copias de seguridad versionadas de tus datos utilizando la primera escritura a cada clave en cada hora UTC. Las escrituras sucesivas a una clave en la misma hora UTC sobrescriben permanentemente los datos anteriores.

Las copias de seguridad versionadas expiran 30 días después de que una nueva escritura las sobrescriba. La última versión nunca expira.

Las siguientes funciones realizan operaciones de versionado:

FunciónDescripción

ListVersionsAsync()

Lista todas las versiones para una clave devolviendo una instancia de DataStoreVersionPages que puedes usar para enumerar todos los números de versión. Puedes filtrar versiones utilizando un rango de tiempo.

GetVersionAsync()

Recupera una versión específica de una clave utilizando el número de versión de la clave.

RemoveVersionAsync()

Elimina una versión específica de una clave.

Esta función también crea una versión de tumba mientras retiene la versión anterior. Por ejemplo, si llamas a RemoveAsync("User_1234") y luego intentas llamar a GetAsync("User_1234"), obtienes nil de vuelta. Sin embargo, aún puedes usar ListVersionsAsync() y GetVersionAsync() para recuperar versiones anteriores de los datos.

Puedes usar el versionado para manejar solicitudes de usuarios. Si un usuario informa que ocurrió un problema a las 2020-10-09T01:42, puedes revertir los datos a una versión anterior utilizando el siguiente ejemplo:

local DataStoreService = game:GetService("DataStoreService")
local gameStore = DataStoreService:GetDataStore("PlayerGame")
local DATA_STORE_KEY = "User_1234"
local maxDate = DateTime.fromUniversalTime(2020, 10, 09, 01, 42)
-- Obtiene la versión más cercana al tiempo dado
local listSuccess, pages = pcall(function()
return gameStore:ListVersionsAsync(DATA_STORE_KEY, Enum.SortDirection.Descending, nil, maxDate.UnixTimestampMillis)
end)
if listSuccess then
local items = pages:GetCurrentPage()
if #items > 0 then
-- Lee la versión más cercana
local closestEntry = items[1]
local success, value, info = pcall(function()
return gameStore:GetVersionAsync(DATA_STORE_KEY, closestEntry.Version)
end)
-- Restaura el valor actual sobrescribiéndolo con la versión más cercana
if success then
local setOptions = Instance.new("DataStoreSetOptions")
setOptions:SetMetadata(info:GetMetadata())
gameStore:SetAsync(DATA_STORE_KEY, value, nil, setOptions)
end
else
-- No se encontraron entradas
end
end

Instantáneas

La API de Open Cloud de Instantáneas de Almacenes de Datos te permite tomar una instantánea de todos los almacenes de datos en un juego una vez al día. Antes de publicar cualquier actualización del juego que cambie tu lógica de almacenamiento de datos, asegúrate de tomar una instantánea. Tomar una instantánea garantiza que tienes los datos más recientes disponibles de la versión anterior del juego.

Por ejemplo, sin una instantánea, si publicas una actualización a las 3:30 UTC que causa corrupción de datos, los datos corruptos sobrescriben cualquier dato escrito entre las 3:00 y las 3:30 UTC. Sin embargo, si tomas una instantánea a las 3:29 UTC, los datos corruptos no sobrescriben nada escrito antes de las 3:29 UTC, y los datos más recientes para todas las claves escritas entre las 3:00 y las 3:29 UTC se preservan.

Listado y prefijos

Los almacenes de datos te permiten listar por prefijo. Por ejemplo, listar por los primeros n caracteres de un nombre, como "d", "do" o "dog" para cualquier clave o almacén de datos con un prefijo de "dog".

Puedes especificar un prefijo al listar todos los almacenes de datos o claves, y obtener solo objetos que coincidan con ese prefijo. Tanto ListDataStoresAsync() como ListKeysAsync() devuelven un objeto DataStoreListingPages que puedes usar para enumerar la lista.

FunciónDescripción
ListDataStoresAsync()Lista todos los almacenes de datos.
ListKeysAsync()Lista todas las claves en un almacén de datos.

Alcances

Puedes organizar aún más las claves en un almacén de datos estableciendo una cadena única como un alcance para el segundo parámetro de GetDataStore(). El alcance predeterminado (si no se da un alcance) es global. El alcance se antepone automáticamente al principio de todas las claves en todas las operaciones realizadas en el almacén de datos.

ClaveAlcance
houses/User_1234houses
pets/User_1234pets
inventory/User_1234inventory

La combinación del nombre del almacén de datos, el alcance y la clave identifica de manera única una clave. Los tres valores son necesarios para identificar una clave con un alcance. Por ejemplo, puedes leer una clave con alcance global llamada User_1234 como:

local DataStoreService = game:GetService("DataStoreService")
local inventoryStore = DataStoreService:GetDataStore("PlayerInventory")
local success, currentGold = pcall(function()
return inventoryStore:GetAsync("User_1234")
end)

Si la clave User_1234 tiene un alcance de gold, sin embargo, solo puedes leerla como:

local DataStoreService = game:GetService("DataStoreService")
local inventoryStore = DataStoreService:GetDataStore("PlayerInventory", "gold")
local success, currentGold = pcall(function()
return inventoryStore:GetAsync("User_1234")
end)

Propiedad AllScopes

DataStoreOptions contiene una propiedad AllScopes que te permite devolver claves de todos los alcances en una lista. Luego puedes usar la propiedad KeyName de un elemento de la lista para operaciones comunes de almacén de datos como leer datos con GetAsync() y eliminar datos con RemoveAsync().

Cuando usas la propiedad AllScopes, el segundo parámetro de GetDataStore() debe ser una cadena vacía ("").

local DataStoreService = game:GetService("DataStoreService")
local options = Instance.new("DataStoreOptions")
options.AllScopes = true
local ds = DataStoreService:GetDataStore("DS1", "", options)

Si habilitas la propiedad AllScopes y creas una nueva clave en el almacén de datos, siempre debes especificar un alcance para esa clave en el formato de alcance/nombreclave. Si no lo haces, las API lanzan un error. Por ejemplo, gold/player_34545 es aceptable con gold como el alcance, pero player_34545 lleva a un error.

global/K1house/K1
global/L2house/L2
global/M3house/M3

Almacenamiento en caché

Utiliza el almacenamiento en caché para almacenar temporalmente datos de los almacenes de datos para mejorar el rendimiento y reducir el número de solicitudes realizadas al servidor. Por ejemplo, un juego puede almacenar en caché una copia de sus datos para que pueda acceder a esos datos rápidamente sin tener que hacer otra llamada al almacén de datos.

El almacenamiento en caché se aplica a las modificaciones que realizas en las claves del almacén de datos utilizando:

GetVersionAsync(), ListVersionsAsync(), ListKeysAsync(), y ListDataStoresAsync() no implementan almacenamiento en caché y siempre obtienen los datos más recientes del backend del servicio.

Por defecto, el motor utiliza GetAsync() para almacenar valores que recuperas del backend en una caché local durante cuatro segundos. También por defecto, las solicitudes de GetAsync() para claves en caché devuelven el valor en caché en lugar de continuar hacia el backend. Tus solicitudes de GetAsync() que devuelven un valor en caché no cuentan hacia tus límites de servidor y límites de rendimiento.

Todas las llamadas a GetAsync() que recuperan un valor que no está siendo almacenado en caché desde el backend actualizan la caché inmediatamente y reinician el temporizador de cuatro segundos.

Deshabilitar almacenamiento en caché

Para deshabilitar el almacenamiento en caché y optar por no usar la caché para recuperar el valor más actualizado de los servidores, agrega el parámetro DataStoreGetOptions a tu llamada a GetAsync() y establece la propiedad UseCache en false para hacer que tu solicitud ignore cualquier clave en la caché.

Deshabilitar el almacenamiento en caché es útil si tienes múltiples servidores escribiendo en una clave con alta frecuencia y necesitas obtener el valor más reciente de los servidores. Sin embargo, puede hacer que consumas más de tus límites y cuotas de almacenes de datos, ya que las solicitudes de GetAsync() que evitan el almacenamiento en caché siempre cuentan hacia tus límites de rendimiento y de servidor.

Para lecturas de verificación inmediatas después de una escritura, utiliza GetAsync() con DataStoreGetOptions.UseCache = false. Por defecto, GetAsync() utiliza una caché local de cuatro segundos, por lo que una lectura de verificación normal puede devolver datos obsoletos.

Esto es especialmente importante después de operaciones de escritura como UpdateAsync(), SetAsync(), IncrementAsync(), o RemoveAsync() que devuelven un error. En estos casos, tu código necesita determinar si debe reintentar, reembolsar o tomar otra acción correctiva.

El siguiente ejemplo muestra cómo evitar la caché al verificar el resultado de una escritura:

local ok = pcall(function()
store:UpdateAsync(key, transform)
end)
if not ok then
local options = Instance.new("DataStoreGetOptions")
options.UseCache = false
local success, value = pcall(function()
return store:GetAsync(key, options)
end)
if success then
-- decidir basado en el estado del backend, no en el estado en caché
end
end

Serialización

El DataStoreService almacena datos en formato JSON. Cuando guardas datos de Luau en Studio, Roblox utiliza un proceso llamado serialización para convertir esos datos en JSON para guardarlos en los almacenes de datos. Luego, Roblox convierte tus datos de nuevo a Luau y te los devuelve en otro proceso llamado deserialización.

La serialización y deserialización admiten los siguientes tipos de datos de Luau:

  • Números
    • No debes almacenar los valores numéricos especiales inf, -inf y nan, porque estos valores no se ajustan a los estándares JSON. Cuando recuperas una entrada que contiene estos valores a través de Open Cloud, la respuesta los representa como objetos JSON etiquetados. Para más detalles, consulta Números no finitos.
  • Tablas
    • Las tablas solo deben contener otros tipos de datos admitidos
    • Las claves numéricas se traducen en cadenas si la longitud de la tabla es 0

Si intentas almacenar un tipo de dato que la serialización no admite, puedes:

  • Fallar al almacenar ese tipo de dato y recibir un mensaje de error.
  • Tener éxito al almacenar ese tipo de dato como nil.

Para depurar por qué tu tipo de dato se está almacenando como nil, puedes usar la función JSONEncode. Cuando pasas tu tipo de dato de Luau a esta función, lo recibes de vuelta en el formato que Roblox habría almacenado con los almacenes de datos, lo que te permite previsualizar e investigar los datos devueltos.

©2026 Roblox Corporation. Roblox, el logotipo de Roblox y "Powering Imagination" son algunas de nuestras marcas registradas y no registradas en los Estados Unidos y otros países.