Este trabajo está licenciado bajo el Acuerdo de Licencia Internacional de Atribución-Uso No Comercial-Compartir 4.0 de Creative Commons de la misma manera .
Este trabajo ( Lizhao Long Bowen por la creación de Li Zhaolong ) por la confirmación de Li Zhaolong , por favor indique los derechos de autor.
Directorio de artículos
- Introducción
-
- Descripción del problema
- Condiciones previas y requisitos del sistema de diseño
- Reducir la carga de obtener el caché
- Reducir la carga del servidor de almacenamiento
- Manejo de fallas
- Fallo clave en la región y el grupo de regiones
- Calentamiento de racimo frío
- Coherencia de la replicación entre regiones
- para resumir
Introducción
Es lógico que no haya tiempo para leer el artículo en tan poco tiempo recientemente, pero por casualidad, volví a ver este artículo y, después de un breve escaneo del contenido del artículo, decidí leerlo de manera intensiva. Comencé a leer este artículo porque miré el tema y pensé que tendría algo que ver con el hash consistente. Porque en los primeros dos días, vi que Dynamo hizo algunas optimizaciones en el hash consistente para mejorar la eficiencia de la anti-entropía. . Si puede comparar el número en este momento. Esta solución es, por supuesto, excelente, pero después de ver el contenido, descubrí que no hay mucha conexión. El artículo describe el uso de Memcache por parte de Facebook. Aunque es contrario al propósito original , el contenido es realmente muy interesante, y debido a que este artículo ha estado en mi línea de tiempo, me decidí a leer este artículo.
Descripción del problema
La siguiente es una imagen resumida dibujada por un bloguero después de leer este artículo. Creo que es muy representativo. Básicamente expliqué el contexto de este artículo con claridad, así que lo pongo aquí.
En este artículo se discutirán los siguientes temas:
- Condiciones previas y requisitos del sistema de diseño
- Reduzca el retraso de la caché y la capa de aplicación concisa, presente mcrouter
- problema de incast
- Reducir la carga del servidor de almacenamiento (arrendamientos, grupo de memcache)
- Manejo de fallas
- Fallo clave en la región y el grupo de regiones
- Calentamiento de racimo frío
- Coherencia de la replicación entre regiones
De hecho, las preguntas anteriores también se pueden considerar como una versión simplificada del catálogo en papel, porque este artículo se parece más a la experiencia de Facebook, por lo que todas las preguntas son muy interesantes, realmente no hay forma de abandonar ninguna de ellas, ¡vamos! ¡Hablemos uno por uno!
Finalmente, quiero hablar sobre la última pregunta antes del texto principal. ¿Por qué se llama el título del artículo? La Scaling Memcache at Facebook
razón se menciona en la primera y segunda sección del artículo, pero es más oscura, es decir, cuando se usa Facebook. , el código abierto es en memcache
realidad una máquina independiente. Entonces, ¿por qué se llama? Scaling
Este artículo describe cómo memcache
extender una máquina única de código abierto a una distribuida. Este es un problema que muchas personas no notaron al leer el artículo por primera vez.
Condiciones previas y requisitos del sistema de diseño
Primero, echemos un vistazo a los antecedentes del nacimiento de esta tecnología. La descripción en la segunda sección es muy clara. En el diseño de Facebook, la operación de lectura del usuario es mucho mayor que la operación de escritura. Esta carga de trabajo significa que la lectura La operación es usar el caché. El mayor beneficio se puede obtener cuando se usa el caché. En segundo lugar, este tipo de almacenamiento en caché necesita sincronizar datos en múltiples sistemas diferentes, porque lo que Facebook necesita es una estrategia de almacenamiento en caché flexible, lo que significa que el caché puede obtener datos de diferentes fuentes y sincronizar.
Obviamente hay dos funciones en este momento. Una es para usarse como caché de consultas . Primero, se solicita en Memcache a través de una clave de cadena. Si no se encuentra, la recuperará de la base de datos o del servicio en segundo plano, y luego usa la clave para recuperar el resultado. Guárdalo de nuevo en Memcache. Para las solicitudes de escritura, el servidor web envía declaraciones SQL a la base de datos y luego envía una solicitud de eliminación a Memcache para invalidar los datos almacenados en caché antiguos.
Por supuesto, Memcache también se puede considerar como una caché indiferenciada más general, porque Memcache en varias máquinas se puede considerar como un todo, por lo que solo necesitamos hacer muy pocas cosas para mantener la coherencia entre varias cachés. Por ejemplo, el servidor A genera una gran cantidad de datos, que son datos intermedios requeridos por algunos programas informáticos. Obviamente, pueden obtener fácilmente los datos que necesitan de Memcache en este momento.
Pero aquí tenemos que tener claro un problema. Aunque se puede usar como caché de propósito general, la versión de Memcache descrita en el documento es en sí misma una tabla hash de memoria independiente, que no tiene la capacidad de almacenamiento distribuido, por lo que en realidad necesita una función como caché de propósito general Cliente potente (y fácil de expandir), este cliente debe admitir el enrutamiento de datos. Por supuesto, la pertenencia al clúster de almacenamiento del cliente también es un método de distribución de eventos en el almacenamiento distribuido, y más adelante se puede escribir un artículo para hablar sobre este tema.
Reducir la carga de obtener el caché
Por lo general, una página grande necesita obtener una gran cantidad de recursos, y estos recursos básicamente no están distribuidos en la misma base de datos o caché, por lo que si todos los recursos se obtienen rápidamente, se convierte en un gran problema.
De acuerdo con investigaciones poco confiables, parece que hay una optimización de que el front-end carga primero los recursos preparados, como texto, imágenes y recursos, como videos, que se pueden llenar primero con imágenes y luego se muestran cuando los datos llegan a una parte. de la misma), lo que puede mejorar en gran medida la velocidad de respuesta de las solicitudes de los clientes y reducir la velocidad de respuesta desde el retraso de solicitud más largo hasta el retraso de solicitud más corto.
nLos recursos se distribuyen en diferentes bases de datos. Para reducir la presión de las solicitudes de bases de datos, algunos recursos se almacenan en caché en varias bases de datos de caché. Los recursos requeridos por una página se procesan y almacenan en diferentes servidores de Memcache. Por lo tanto, el servidor web debe solicitar varios servidores de Memcache para cumplir con la solicitud del usuario. En este momento, el equipo de Facebook ha tomado tres medidas de optimización, a saber:
- Maximice las solicitudes paralelas
- Utilice UDP para reducir la latencia
- Lidiando con problemas de incast
Los dos primeros puntos me hicieron escribir que puedo pensar en ello, pero el tercer punto es difícil de considerar sin una gran cantidad de análisis de datos cuantitativos Esta es también una característica importante de la lectura de este tipo de artículos industriales.
Maximizar las solicitudes paralelas en realidad resuelve el siguiente problema: ¿Cómo reducir el retraso de la solicitud de ida y vuelta de todos los recursos de una página? Este problema depende no solo del retraso de una determinada solicitud, sino también de la relación de dependencia entre los recursos de la página. En este último caso, podemos construir un gráfico acíclico dirigido (DAG) de todos los recursos de la página. Obviamente, puede concluir en este momento El punto es la raíz y la profundidad de este árbol es el número mínimo de RTT.
El uso de UDP para reducir la demora de la solicitud es bien entendido, pero hablemos de uno de los problemas mencionados en esta sección, es decir, nuestra aplicación web no se memcache
comunica directamente con el servidor. La comunicación entre ellos es a través del cliente. Este cliente El final es sin estado, encapsula la complejidad del sistema, proporciona serialización (creación de DAG), compresión, enrutamiento de solicitudes, manejo de errores (base de datos de solicitudes) y procesamiento por lotes de solicitudes , dejando la interfaz simple a las aplicaciones web. Por supuesto, hay dos formas de implementar la lógica del cliente aquí, que puede ser una biblioteca incrustada en la aplicación o como un mcrouter
agente independiente llamado.
Sabemos que TCP es un protocolo de capa de transporte orientado a la conexión, lo que significa que la comunicación entre dos nodos no solo requiere tres paquetes para establecer una conexión (defer_accept puede eliminar el tercer protocolo de enlace), sino que también requiere paquetes de latidos para mantener la conexión durante los datos. Se necesita información y una desconexión elegante (de tres a cuatro paquetes). La sobrecarga aquí es muy grande. Por supuesto, puede ser un poco mejor en el escenario de conexión larga, porque la sobrecarga de los paquetes anteriores se divide en múltiples operaciones en . Pero el costo de mantener la conexión en una conexión corta será muy alto, porque puede que solo haya un paquete de datos.
El uso de UDP en lugar de TCP para optimizar las operaciones de lectura puede reducir la latencia de la operación. Según las estadísticas de Facebook, solo el 0,25% de los paquetes se descartan, de los cuales alrededor del 80% se deben a retrasos o pérdidas de paquetes, y el resto se debe a una entrega fuera de orden. , por supuesto, podemos optar por mantener la pila de protocolos en el modo de usuario para evitar estos problemas, pero no es necesario, porque queremos mejorar la eficiencia. Esto último trae confiabilidad mientras inevitablemente pierde eficiencia, y el costo de fallas es causado por nosotros. Recibir no es más que verificar la base de datos una vez. El uso de UDP para operaciones de lectura trae una reducción del 20% en la latencia en comparación con TCP:
La descripción del problema de la incast es la siguiente [6]:
Una gran cantidad de solicitudes llegan al servidor front-end al mismo tiempo, o el servidor del centro de datos envía una gran cantidad de datos al mismo tiempo, lo que hace que el búfer del conmutador o enrutador se llene y provoque una gran cantidad de pérdida de paquetes. . El mecanismo de retransmisión de TCP también debe esperar la retransmisión a lo largo del tiempo, lo que aumenta el retraso de todo el sistema y reduce en gran medida el rendimiento.
El equipo de Facebook usó inteligentemente el mecanismo de la ventana deslizante para resolver este problema. Esta ventana no se crea en función de una conexión como TCP, pero se aplica a todas las solicitudes de Memcache y no se preocupa por la dirección de destino. A continuación, se muestra el tamaño de la ventana y Relación de retardo de solicitud:
cuando la ventana es relativamente pequeña, la aplicación tendrá que distribuir más conjuntos de solicitudes de Memcache en serie, lo que aumentará la duración de las solicitudes web . Cuando la ventana es demasiado grande, la cantidad de solicitudes procesadas simultáneamente en Memcache provocaría una congestión de incast . El resultado será un error de Memcache y la aplicación degenerará para recuperar datos del almacenamiento persistente , lo que dará como resultado un procesamiento más lento de las solicitudes web. Obviamente, 300 es una muy buena elección de tamaño de ventana cuando la carga es pequeña.
Reducir la carga del servidor de almacenamiento
El problema aquí es en realidad equivalente a cómo reducir el acceso a la base de datos o aumentar la tasa de aciertos de la caché. El documento proporciona tres formas de optimizar este problema:
- mecanismo de arrendamientos
- grupo de memcache
- mecanismo de replicacion
Lo que alquila el mecanismo principal para resolver la configuración obsoleta (conjuntos obsoletos) [9] y el grupo de choque (rebaños atronadores, esto puede deberse a una mayor eficiencia para combatir la solicitud de fusión a la base de datos, de hecho, describir el documento no está claro ).
El grupo de memcache resuelve memcache como una carga general. La capa superior tiene diferentes modos de acceso, uso de memoria y requisitos de calidad de servicio. Esto puede llevar a que: las claves primarias de baja fluctuación que aún son valiosas se eliminen de las primarias de alta fluctuación claves a las que ya no se accede Antes de ser expulsado (después de todo, es una base de datos basada en memoria, que requiere eliminación de memoria), colocar estos elementos de datos con diferentes características de fluctuación en diferentes grupos puede mejorar la tasa de aciertos de la caché.
Sin embargo, replication
puede proporcionar un rendimiento excelente cuando el volumen de solicitudes excede la carga de una sola máquina. Por supuesto, existen dos métodos, uno se basa en la división de la clave principal y el otro es la replicación completa de datos. [7] 3.2 .3 describe la mayoría de las situaciones Razones para elegir copiar.
La descripción en el artículo es simple y fácil de entender, por lo que no la explicaré en detalle aquí.
Manejo de fallas
El manejo de la falla por parte del equipo de Facebook es muy peculiar. En términos generales, en el campo del almacenamiento distribuido, el manejo de fallas generalmente se divide en los siguientes puntos:
- Descubrimiento de fallas (partición, nodo inactivo o fluctuación de la red, el comportamiento general es el tiempo de espera de recuperación de paquetes de latidos)
- Recuperación de fallas (existen muchos métodos, principalmente dependiendo de cómo hacer la redundancia de datos, que incluyen, entre otros: posición superior del nodo esclavo, reasignación del nodo maestro (arrendamientos))
- Sincronización de datos (no detallada)
A los ojos del equipo de Facebook, las fallas en este sistema se dividen en dos categorías:
- Debido a una falla en la red o en el servidor, una pequeña cantidad de hosts no puede acceder
- Tiempo de inactividad extenso que afecta a un gran porcentaje de servidores en el clúster.
A este último se le puede determinar que el clúster está fuera de línea y transferimos la solicitud web del usuario a otro clúster. Este último puede considerarse un problema menor. En este momento, habrá máquinas parcialmente redundantes, que se denominan Gutter
la función de reemplazar nodos fallidos. En un clúster, la cantidad de Gutter es aproximadamente el 1% de los servidores memcached.
Cuando el cliente de Memcached no recibe una respuesta a su solicitud de obtención, el cliente asume que el servidor ha fallado y luego envía la solicitud nuevamente al grupo de Gutter específico. Si no se recibe la segunda solicitud, el cliente insertará el par clave-valor apropiado en la máquina de Gutter después de consultar la base de datos .
De esta manera, cuando algunos nodos de caché de Memcache están inactivos, la carga de la base de datos se puede reducir en gran medida, porque Gutter
habrá una gran cantidad de accesos de caché en este momento. Para algunos servidores Memcached a los que no se puede acceder debido a fallas o accidentes de red a pequeña escala, Gutter protegerá el almacenamiento de back-end de un aumento en el tráfico .
Fallo clave en la región y el grupo de regiones
Aquí primero debemos delinear la relación entre los diversos términos en este diagrama de arquitectura del sistema que es el siguiente:
Claramente WebServer
y Memcache
maquillaje Front-end Clusters
, aunque no en el mapa, pero creo que Mcrouter
pertenece a la memcache
parte, y Front-end Clusters
con Storage Cluster
maquillaje region
.
Obviamente, los Storage Cluster
datos autorizados se almacenan en el clúster anterior , y una operación de escritura memcache
invalidará todos los datos en él. ¿Cómo actualizar los datos en múltiples cachés en este momento? En primer lugar, la elección de la coherencia es la elección de la coherencia fuerte. Obviamente, una consistencia fuerte reducirá en gran medida el rendimiento, por lo que el proceso de actualización debe ser asincrónico, así que ¿deberíamos usar la WebServer
transmisión o buscar otra forma?
El equipo de Facebook decidió presentar mcsqueal
:
mcsqueal
Es esencialmente un proceso demonio.Cada proceso demonio verifica las declaraciones SQL enviadas por la base de datos y extrae cualquier comando de eliminación.En este momento, se puede enviar una pequeña cantidad de paquetes a cada servidor designado que ejecute mcrouter en el clúster anterior. Luego, mcrouter descompone una operación de eliminación separada de cada lote de paquetes y enruta el comando no válido al servidor Memcached correcto en el clúster de front-end. Esto puede reducir significativamente la carga en la máquina que ejecuta el proceso de la base de datos.
La WebServer
principal razón por la que no se puede ejecutar la clave sin pasarla es porque se supone que el comando de eliminación está enrutado incorrectamente debido a un error de configuración, y web server
los datos para esta operación no se pueden aterrizar (¿por qué no aterrizar? Duda), en este Una vez que se pierde el comando y el registro es confiable, puede seguir intentándolo. Por supuesto, existen algunos problemas entre múltiples clústeres, de eso hablaremos más adelante.
Se llama a una colección de varios servidores Front-end Clusters
compartidos .memcache
region池
Debido a que memcache
los datos se modifican en función de las solicitudes web, si las solicitudes de los usuarios se enrutan de forma aleatoria a todos los clústeres de front-end disponibles, la probabilidad de que haya datos en estos clústeres es aproximadamente la misma. Para los conjuntos de datos con pocas modificaciones y poco tráfico , se pueden ser Front-end Clusters
compartida memcache
. Esto puede reducir significativamente el número de máquinas en algunos casos.
Calentamiento de racimo frío
Cuando se agrega un nuevo clúster, la tasa de aciertos de la caché será muy baja en este momento, lo que debilitará la capacidad de aislar los servicios de back-end. Por lo tanto, podemos permitir que el cliente de este nuevo clúster recupere datos del cliente del clúster que se ha estado ejecutando durante mucho tiempo, de modo que el tiempo para que este clúster frío alcance la carga completa se acortará considerablemente. Por supuesto, esto puede causar problemas de coherencia. Por supuesto, esto no satisface la coherencia de lectura y escritura [8], porque es muy posible que la caché no se haya actualizado después de la escritura y se lean los datos antiguos, pero esto es en la aplicación de Facebook El problema no es grande, consulte [7] 4.3 para obtener más detalles.
Coherencia de la replicación entre regiones
Primero, señale las ventajas de los centros de datos interregionales:
- Colocar el servidor web cerca del usuario final puede reducir en gran medida el retraso .
- La diversificación geográfica puede aliviar el impacto de los desastres naturales y los cortes de energía a gran escala .
- La nueva ubicación puede proporcionar electricidad más barata y otros incentivos económicos .
Se 3-2-1原则
aclaró también que lo mejor es tener una copia de seguridad remota.
La coherencia aquí es principalmente la coherencia de la caché, es decir, el problema de coherencia entre los clústeres activos y en espera.
Escribir desde la región principal puede causar algunos problemas de actualización, pero estos problemas se mcsqueal
evitan Por supuesto, esta es también WebServer
la razón por la que la caché no es válida si no se utiliza la actualización. Dado que es posible que los cambios en la base de datos principal no se propaguen a la base de datos de réplica, la invalidación de la caché ya ha llegado. La siguiente consulta de datos en la región de réplica hará que memcache
aparezcan datos sucios en ella. Úselo mcsqueal
para evitar este problema.
Esta sección muestra que la región es en realidad una arquitectura de nodo sin propietario, porque se puede no-master
escribir desde ella , pero la descripción es muy breve y básicamente no tiene valor de referencia. Más interesante es el remote marker
mecanismo para reducir la probabilidad de leer datos antiguos. De hecho, el retraso adicional (comunicación entre regiones) cuando falla la memoria caché se usa a cambio de una disminución en la probabilidad de leer datos desactualizados. Para obtener más información, consulte [7] 5.
para resumir
Muchos problemas en este documento son impresionantes, incast
problemas, problemas de coherencia de caché, 故障处理
problemas , etc. Y, de hecho, es una buena guía para nosotros para la aplicación del almacenamiento en caché Es difícil encontrar problemas en muchos lugares sin pozos de minería. Leer más, escribir más código, que así sea.
referencia:
- " Escalar Memcache en las notas de lectura de Facebook "
- 《Escalar Memcache en Facebook》
- " Mejora de la escalabilidad de Memcache de Facebook "
- " Introducción básica y principio de funcionamiento de MemCache "
- " Soluciones TCP INCAST "
- " Problema de transmisión de aplicaciones web de PICC-Data Center "
- Escalando Memcache en Facebook
- " Habla sobre un poco de comprensión de la coherencia distribuida "
- " Análisis del esquema de coherencia de escritura doble de caché y base de datos distribuida "