MemoryStoreService es un servicio de datos de alto rendimiento y baja latencia que proporciona almacenamiento de datos en memoria rápido accesible desde todos los servidores en una sesión en vivo. Los almacenes de datos son adecuados para datos frecuentes y efímeros que cambian rápidamente y no necesitan ser duraderos, porque son más rápidos de acceder y desaparecer cuando alcanzan la vida útil máxima. Para los datos que necesitan persistir a través de las sesiones, use Almacenes de datos .
Estructuras de datos
En lugar de acceder directamente a los datos brutos, los almacenes de almacenamiento tienen tres estructuras de datos primitivas compartidas entre los servidores para un procesamiento rápido: mapa ordenado, cola y mapa hash. Cada estructura de datos es adecuada para ciertos casos de uso:
- Emparejamiento basado en habilidades - Guarde la información del usuario, como el nivel de habilidad, en una cola compartida entre los servidores, y use los servidores del lobby para ejecutar el emparejamiento periódicamente.
- Comercio y subasta entre servidores - Habilita el comercio universal entre diferentes servidores, donde los usuarios pueden pujar por artículos con precios cambiantes en tiempo real, con un mapa ordenado de pares de valores clave.
- Tablas de clasificación globales - Almacena y actualiza las clasificaciones de los usuarios en una tabla de clasificación compartida dentro de un mapa clasificado **** .
- Inventarios compartidos - Guarda los artículos de inventario y las estadísticas en un mapa hash compartido , donde los usuarios pueden utilizar los artículos de inventario simultáneamente entre sí.
- Cache para datos persistentes - Sincroniza y copia tus datos persistentes en un almacén de datos a un almacén de memória mapa de hash que puede actuar como un caché y mejorar el ejecuciónde tu experiencia.
En general, si necesita acceder a datos basados en una clave específica, use un mapa hash. Si necesita que se ordenen esos datos, use un mapa ordenado. Si necesita procesar sus datos en un orden específico, use una cola.
Límites y Cuotas
Para mantener la escalabilidad y el ejecuciónsistema, los almacenes de memoria tienen cuotas de uso de datos para el tamaño de la memoria, las solicitudes de API y el tamaño de la estructura de datos.
Las tiendas de almacenamiento tienen una política de desalojo basada en el tiempo de expiración, también conocido como tiempo de vida (TTL). Los elementos se desalojan después de que expiren, y la cuota de almacenamiento se libera para nuevas entradas. Cuando alcanzas el límite de almacenamiento, todas las solicitudes de escritura subsiguientes fallan hasta que los elementos expiren o los elimines manualmente.
Cuota de tamaño de memoria
La cuota de almacenamiento limita la cantidad total de almacenamiento que una experiencia puede consumir. No es un valor fijo. En cambio, cambia con el tiempo dependiendo del número de usuarios en la experiencia según la siguiente fórmula: 64KB + 1KB * [número de usuarios] . La cuota se aplica al nivel de experiencia en lugar del nivel de servidor.
Cuando los usuarios se unen a la experiencia, la cuota de almacenamiento adicional está disponible inmediatamente. Cuando los usuarios salen de la experiencia, la cuota no se reduce inmediatamente. Hay un período de retroceso de ocho días antes de que la cuota se vuelva a evaluar a un valor más bajo.
Después de que tu experiencia alcance la cuota de tamaño de almacenamiento, cualquier solicitud de API que aumente el tamaño de almacenamiento siempre fallará. Las solicitudes que disminuyen o no cambian el tamaño de almacenamiento aún tienen éxito.
Con el panel de observabilidad, puedes ver la cuota de tamaño de almacenamiento de tu experiencia en tiempo real usando el gráfico de Uso de almacenamiento .
Límites de solicitudes de API
Para los límites de solicitudes de API, hay una cuota de Unidad de Solicitud que se aplica a todas las MemoryStoreService llamadas de API, que es 1000 + 100 * [número de usuarios concurrentes] unidades de solicitud por minuto. Además, la tasa de solicitudes a cualquier cola, mapa ordenado o mapa hash está limitada a 100,000 unidades de solicitud por minuto.
La mayoría de las llamadas de API solo consumen una unidad de solicitud, con las excepciones de MemoryStoreSortedMap:GetRangeAsync() para mapas ordenados y MemoryStoreQueue:ReadAsync() para colas. Estos dos métodos consumen unidades según el número de elementos devueltos con al menos una unidad de solicitud. Por ejemplo, si MemoryStoreSortedMap:GetRangeAsync() devuelve 10 elementos, la cuota total cuenta según 10 unidades de solicitud. Si devuelve una respuesta vacía sin elementos, la cuota cuenta según una sola unidad de solicitud. Además, MemoryStoreQueue:ReadAsync() consume una unidad adicional cada dos segundos mientras se lee. El tiempo máximo de lectura se especifica utilizando el parámetro waitTimeout.
La cuota de solicitudes también se aplica al nivel de experiencia en lugar del nivel de servidor. Esto proporciona flexibilidad para asignar las solicitudes entre los servidores siempre que la tasa total de solicitudes no exceda la cuota. Si excede la cuota, recibirá una respuesta de error cuando el servicio reduzca sus solicitudes.
Con la función observabilidad disponible, puedes ver la cuota de unidades de solicitud de tu experiencia en tiempo real.
Límites de tamaño de estructura de datos
Para un solo mapa o cola clasificada, se aplican los siguientes límites de tamaño y número de elementos:
- Número máximo de artículos: 1,000,000
- Tamaño total máximo (incluidas las teclas para el mapa clasificado): 100 MB
Límites por partición
Vea Límites por partición .
Mejores Prácticas
Para mantener tu patrón de uso de memoria óptimo y evitar alcanzar los límites , sigue estas mejores prácticas:
Elimina los elementos procesados. Limpiando consistentemente los elementos leídos usando el método MemoryStoreQueue:RemoveAsync() para colas y MemoryStoreSortedMap:RemoveAsync() para mapas ordenados puede liberar almacenamiento y mantener actualizada la estructura de datos.
Establece el tiempo de expiración en el menor marco de tiempo posible al agregar datos. Aunque el tiempo de expiración predeterminado es de 45 días para MemoryStoreQueue:AddAsync() y MemoryStoreSortedMap:SetAsync(), establecer el menor tiempo posible puede limpiar automáticamente los datos antiguos para evitar que llenen su cuota de uso de almacenamiento.
- No almacene una gran cantidad de datos con una expiración larga, ya que corre el riesgo de exceder su cuota de almacenamiento y potencialmente causar problemas que pueden romper toda su experiencia.
- Siempre elimine explícitamente los elementos no necesarios o establezca una expiración corta del elemento.
- En general, debe usar la eliminación explícita para liberar el almacenamiento y la expiración de los elementos como mecanismo de seguridad para evitar que los elementos no utilizados ocupen el almacenamiento durante un período prolongado de tiempo.
Mantén solo los valores necesarios en memoria.
Por ejemplo, para una experiencia en una casa de subastas, solo necesitas mantener la oferta más alta. Puedes usar MemoryStoreQueue:UpdateAsync() en una tecla para mantener la oferta más alta en lugar de mantener todas las ofertas en tu estructura de datos.
Use respaldo exponencial para ayudar a mantenerse por debajo de los límites de solicitudes de API.
Por ejemplo, si recibes un DataUpdateConflict, podrías volver a intentarlo después de dos segundos, luego cuatro, ocho, etc. en lugar de enviar solicitudes constantemente a MemoryStoreService para obtener la respuesta correcta.
Divida estructuras de datos gigantes en múltiples estructuras más pequeñas fragmentando .
A menudo es más fácil administrar datos en estructuras más pequeñas que almacenar todo en una gran estructura de datos. Este enfoque también puede ayudar a evitar los límites de uso y velocidad. Por ejemplo, si tiene un mapa ordenado que usa prefijos para sus teclas, considere separar cada prefijo en su propio mapa ordenado. Para una experiencia especialmente popular, incluso puede separar a los usuarios en múltiples mapas según los primeros dígitos de sus ID de usuario.
Comprimir valores guardados.
Por ejemplo, considera usar el algoritmo LZW para reducir el tamaño del valor almacenado.
Observabilidad
El Panel de Observabilidad proporciona información y análisis para monitorear y solucionar problemas de uso de almacenamiento. Con gráficos actualizados en tiempo real sobre diferentes aspectos del uso de almacenamiento y solicitudes de API, puede rastrear el patrón de uso de almacenamiento de su experiencia, ver las cuotas asignadas actualmente, monitorear el estado de la API e identificar posibles problemas para la optimización del rendimiento.
La siguiente tabla enumera y describe todos los códigos de estado de las respuestas de API disponibles en las tablas Request Count by Status y Requests by API x Status de Observability Dashboard. Para obtener más información sobre cómo resolver estos errores, consulte Troubleshooting. Para obtener la cuota o límite específico al que se refiere un error, consulte Limits and Quotas.
Código de estado | Descripción |
---|---|
Éxito | Éxito. |
Superlímite de memoria de estructura de datos | Excede el límite de tamaño de almacenamiento a nivel de estructura de datos (100 MB). |
Conflicto de Actualización de Datos | Conflicto debido a una actualización concurrente. |
Acceso denegado | No está autorizado a acceder a los datos de la experiencia. Esta solicitud no consume unidades de solicitud ni usa cuota. |
Error interno | Error interno. |
Solicitud inválida | La solicitud no tiene la información requerida o tiene información incorrecta. |
DataStructureItemsSobreLímite | Excede el límite de conteo de elementos de nivel de estructura de datos (1M). |
NoObjetoEncontrado | No se encontró ningún artículo en MemoryStoreQueue:ReadAsync() o MemoryStoreSortedMap:UpdateAsync() . ReadAsync() vota cada 2 segundos y devuelve este código de estado hasta que encuentre elementos en la cola. |
Límite de solicitudes de estructura de datos | Excede el límite de unidades de solicitud de nivel de estructura de datos (100,000 unidades de solicitud por minuto). |
Límite de solicitudes de particiones | Excede el límite de unidades de solicitud de partición. |
Solicitudes TotalesSobreLímite | Excede el límite de unidades de solicitud de nivel universal. |
Sobrelímite de memoria total | Excede la cuota de memoria de nivel universal. |
ItemValueSizeTooLarge | El tamaño del valor excede el límite (32KB). |
La siguiente tabla enumera los códigos del lado del cliente, que actualmente no están disponibles en el Panel de Observabilidad.
Código de estado | Descripción |
---|---|
Error interno | Error interno. |
Lugar no publicado | Debes publicar este lugar para usar MemoryStoreService. |
Acceso de cliente inválido | MemoryStoreService debe ser llamado desde el servidor. |
Tiempo de expiración inválido | El tiempo de expiración del campo debe estar entre 0 y 3.888.000. |
Solicitud inválida | No se pudo convertir el valor a json. |
Solicitud inválida | No se ha podido convertir la tecla de clasificación a un número o una cadena válidos. |
Transformación de devolución de llamada fallida | No se pudo invocar la función de devolución de llamada de transformación. |
Solicitud restringida | Las solicitudes recientes de MemoryStores han alcanzado uno o más límites. |
ActualizaciónConflicto | Excediste el número máximo de intentos. |
Solución de problemas
La siguiente tabla enumera y describe la solución recomendada para cada código de estado de respuesta:
Error | Opciones de solución de problemas |
---|---|
DataStructureRequestsOverLimit / PartitionRequestsOverLimit |
|
Solicitudes TotalesSobreLímite | |
DataStructureItemsSobreLímite |
|
Superlímite de memoria de estructura de datos | |
Sobrelímite de memoria total | |
Conflicto de Actualización de Datos |
local MemoryStoreService = juego:GetService ("MemoryStoreService") mapa local = MemoryStoreService:GetSortedMap ("AuctionItems") función placeBid (itemKey, bidAmount) mapa:UpdateAsync(itemKey, function (objeto) item = item o si objeto.highestBid < bidAmount entonces objeto.highestBid = bidAmount return end item print ("item es "..objeto.highestBid) return nil finalizar, 1000 placeBid |
Error interno |
|
Solicitud inválida |
|
ItemValueSizeTooLarge |
|
Prueba y depuración en Studio
Los datos en MemoryStoreService están aislados entre Studio y producción, por lo que cambiar los datos en Studio no afecta el comportamiento de producción. Esto significa que sus llamadas de API de Studio no acceden a los datos de producción, lo que le permite probar con seguridad las tiendas de almacenamiento y las nuevas funciones antes de ir a la producción.
Las pruebas de estudio tienen los mismos límites y cuotas que la producción. Para las cuotas calculadas en función del número de usuarios, la cuota resultante puede ser muy pequeña ya que eres el único usuario para las pruebas de estudio. Al realizar pruebas desde Studio, también puede notar una latencia ligeramente mayor y tasas de error elevadas en comparación con el uso en producción debido a algunas comprobaciones adicionales que se realizan para verificar el acceso y los permisos.
Para obtener información sobre cómo depurar un almacén de almacenamiento en experiencias en vivo o al realizar pruebas en el estudio, use Developer Console .