Go-cache: Solicitud de función: tamaño máximo y / o objetos máximos

Creado en 18 nov. 2012  ·  11Comentarios  ·  Fuente: patrickmn/go-cache

Para que go-cache sea tan útil como Memcache, necesita un límite superior en la cantidad de memoria que puede usar, de lo contrario, es fácil almacenar en caché demasiadas cosas y explotar el uso de memoria.

Idealmente, tendría un límite de memoria como lo hace Memcache. Podría ser algo aproximado, ya que estoy seguro de que no es particularmente fácil contabilizar la memoria utilizada en el caché.

Un límite máximo de objetos también probablemente sería útil.

enhancement

Comentario más útil

También voy a votar por esta función. Seguiré usando esto, pero con mucha precaución. Un ataque de bot mataría mi servicio sin el límite superior.

Iba a usar esto para almacenar en caché los objetos de usuario en relación con las claves de sesión para no tener que presionar mi base de datos en cada solicitud. Así que el tiempo de expiración es genial para esto. Estaría bien con la caída aleatoria de entradas si fuera de tamaño. Sería incluso mejor si simplemente arrojara el objeto más antiguo, pero imagino que habría un éxito de rendimiento en eso.

Todos 11 comentarios

Estoy de acuerdo en que sería útil, pero tal como está, sería bastante difícil como sugiere. go-cache, a diferencia de Memcached, no procesa / serializa la mayoría de los datos, sino que mantiene un puntero hacia ellos. Por supuesto, si bien esto hace que go-cache sea más rápido en órdenes de magnitud, también significa que no se distribuye de ninguna manera (como Memcached) y, desafortunadamente, no puede saber el tamaño de lo que está almacenando sin algunos Reflexión grave / magia insegura / sobrecarga.

La mejor solución probablemente sería crear un nuevo tipo de caché que almacene elementos que satisfagan una interfaz Sizeable donde foo.Size () representa su tamaño relativo como un número entero. Así es como lo hace el caché LRU de Vitess: https://code.google.com/p/vitess/source/browse/go/cache/lru_cache.go Esto transferiría esa responsabilidad al usuario. No estoy totalmente seguro de si los usuarios pueden determinar esto fácilmente en muchos casos, es decir, cuando están almacenando algo más complejo que, por ejemplo, una estructura con un campo de bytes [] o algo, como un mapa de estructuras o sectores.

Otra solución sería simplemente limitar la cantidad de elementos en la caché en un momento dado, pero eso supone que cada elemento de la caché tiene aproximadamente el mismo tamaño. El mayor problema con esto es elegir los elementos correctos para eliminarlos cuando sea necesario. Tal caché probablemente terminaría convirtiéndose en un clon de LRU (es decir, realiza un seguimiento de cuándo se accedió a los elementos por última vez y usa algo diferente a / además de un mapa para el almacenamiento) donde cada elemento tiene el mismo tamaño, por ejemplo, 1.

Seguiré pensando en la mejor manera de abordar esto en go-cache, pero mi intuición en este momento:

  • Si está agotando la memoria, ¿quizás la duración de la expiración debería ser más corta?
  • Si la duración de la expiración ya es corta y el uso de la memoria aún se dispara, ¿es seguro asumir que hay varias interfaces / interfaces de aplicaciones para este sistema? En ese caso, ¿tal vez sería preferible usar cajas memcached dedicadas? Una gran ventaja aquí es que puede almacenar elementos en caché durante mucho tiempo, pero aún así caducar de manera confiable los elementos de un clúster de caché grande de forma manual, incluso si muchas interfaces están usando la caché.

Gracias por la respuesta detallada y el enlace al caché de Vitess.

Creo que tiene razón en que el dimensionamiento de los objetos requeriría la ayuda del usuario. Pensé ingenuamente que podría introspectarse, pero tiene razón, los objetos pueden ser indicadores de estructuras arbitrariamente complicadas que pueden o no necesitar ser contabilizadas en la caché. El usuario podría intentar estimar el tamaño con una interfaz Sizeable como sugirió.

Sigo pensando que un límite total de objetos sería útil. Supongamos que está almacenando sesiones de usuario durante 24 horas. Sin embargo, te encuentras en el extremo equivocado de una red de bots que hace muchas sesiones en un período de tiempo muy corto. Ese es el tipo de escenario en el que el uso de la memoria se dispara. Vaciar las sesiones de usuario no sería ideal en este caso, pero mantendría el servidor en funcionamiento en lugar de quedarse sin memoria.

Memcached ciertamente podría hacer el trabajo en este caso, pero me gusta la idea de hacerlo de manera realmente eficiente con go-cache .

Me gustaría señalar que yo también creo que un límite de número total de objetos sería útil.

Pido disculpas por la demora. Todavía estoy pensando en cómo hacer esto bien, es decir, cómo desalojar elementos de la mejor manera sin implementar una copia de Vitess (y la sobrecarga de mantener una lista adicional de elementos / elementos de actualización en Get). Estoy de acuerdo en que es problemático si alguien explota su número de artículos.

¿No redis simplemente desaloja cosas del caché al azar? Creo que me importa más que mi caché esté limitada a la memoria que desalojar el elemento "incorrecto". Tal vez podamos hacer que el algoritmo real para desalojar se pueda conectar y comenzar con el desalojo aleatorio si no necesita una contabilidad elegante.

Me gusta más el enfoque LRU, pero con eso la preocupación es la sobrecarga para las cargas pesadas de lectura y el uso de memoria de Ctime / Atime para cada elemento en caché.

El desalojo aleatorio podría funcionar, pero no sé si hay una forma confiable de implementarlo, dado que el almacenamiento subyacente es map. El recorrido del mapa es impredecible pero no realmente aleatorio, por lo que no puede simplemente atravesar, elegir la primera clave y eliminarla: https://play.golang.org/p/lUw_1oPTLB Pero quizás eso sea menos preocupante para mapas más grandes ...

El desalojo aleatorio está bien para los cachés perezosos, pero cuando su caché es de lectura intensa, los objetos son costosos de generar y termina desalojando algunos elementos calientes (y, por lo tanto, inmediatamente pierde el caché), duele.

Momento interesante; esto acaba de llegar a HN: https://danluu.com/2choices-eviction/

Posiblemente podríamos tener ambas opciones, pero LRU todavía parece mejor dado que no tenemos una buena forma de seleccionar elementos aleatorios de la caché sin mantener alguna estructura de datos paralela.

También voy a votar por esta función. Seguiré usando esto, pero con mucha precaución. Un ataque de bot mataría mi servicio sin el límite superior.

Iba a usar esto para almacenar en caché los objetos de usuario en relación con las claves de sesión para no tener que presionar mi base de datos en cada solicitud. Así que el tiempo de expiración es genial para esto. Estaría bien con la caída aleatoria de entradas si fuera de tamaño. Sería incluso mejor si simplemente arrojara el objeto más antiguo, pero imagino que habría un éxito de rendimiento en eso.

buena idea, error Creo que la memoria máxima de límite de diseño es mejor.

Esto parece una característica importante que falta. Hay casos de uso en los que los tiempos de desalojo grandes tienen mucho sentido, pero la memoria caché debe estar limitada a la memoria; de lo contrario, el servicio eventualmente se quedará sin memoria y morirá. Cualquier tipo de limitación en ese sentido es mucho mejor que nada en mi opinión. Agregué este caché a nuestro sistema con gran facilidad, pero probablemente intentaré reemplazarlo con otro que admita esta característica vital.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

bramp picture bramp  ·  3Comentarios

rnix picture rnix  ·  3Comentarios

superwf picture superwf  ·  3Comentarios

karellm picture karellm  ·  3Comentarios

gplume picture gplume  ·  3Comentarios