
Hola Habr!
No es ningún secreto que grandes cantidades de datos están involucrados en el trabajo de las aplicaciones modernas, y su flujo está en constante crecimiento. Estos datos deben almacenarse y procesarse, a menudo desde una gran cantidad de máquinas, y esta no es una tarea fácil. Para resolverlo, hay tiendas de objetos en la nube. Por lo general, son una implementación de la tecnología de almacenamiento definido por software.
A principios de 2018, lanzamos (¡y lanzamos!) Nuestro propio almacenamiento 100% compatible con S3 basado en Cloudian HyperStore. Al final resultó que, la red tiene muy pocas publicaciones en ruso sobre Cloudian, y menos aún sobre la aplicación real de esta solución.
Hoy, con base en la experiencia de DataLine, le contaré sobre la arquitectura y la estructura interna del software Cloudian, incluida la implementación de SDS Cloudian basada en una serie de soluciones arquitectónicas de Apache Cassandra. Por separado, consideramos lo más interesante en cualquier almacenamiento SDS: la lógica de garantizar la tolerancia a fallos y la distribución de objetos.
Si está creando su almacenamiento S3 o está ocupado manteniéndolo, este artículo le será útil.
En primer lugar, explicaré por qué nuestra elección recayó en Cloudian. Es simple: hay muy pocas opciones valiosas en este nicho. Por ejemplo, hace un par de años, cuando estábamos pensando en construir, solo había tres opciones:
- CEHP + RADOS Gateway;
- Minio
- Cloudian HyperStore.
Para nosotros, como proveedor de servicios, los factores decisivos fueron: un alto nivel de correspondencia entre la API de almacenamiento y el Amazon S3 original, la disponibilidad de facturación incorporada, la escalabilidad con soporte multirregional y la presencia de una tercera línea de soporte de proveedores. Cloudian tiene todo esto.
Y sí, lo más importante (¡sin duda!) Lo más importante es que DataLine y Cloudian tienen colores corporativos similares. Debes admitir que no podríamos resistirnos a tanta belleza.

Desafortunadamente, Cloudian no es el software más común, y prácticamente no hay información al respecto en RuNet. Hoy corregiremos esta injusticia y hablaremos con usted sobre las características de la arquitectura HyperStore, examinaremos sus componentes más importantes y trataremos los principales matices arquitectónicos. Comencemos con lo más básico, a saber: ¿qué es Cloudian bajo el capó?
Cómo funciona Cloudian HyperStore Storage
Echemos un vistazo al diagrama y veamos cómo funciona la solución Cloudian.
El esquema de almacenamiento del componente principal.Como podemos ver, el sistema consta de varios componentes principales:
- Cloudian Management Control - consola de gestión ;
- Servicio de administración: módulo de administración interna ;
- Servicio S3 : el módulo responsable de soportar el protocolo S3 ;
- Servicio HyperStore : el servicio de almacenamiento real ;
- Apache Cassandra - un repositorio centralizado de datos de servicio ;
- Redis : para los datos leídos con más frecuencia .
De gran interés para nosotros será el trabajo de los servicios principales, el Servicio S3 y el Servicio HyperStore, luego consideraremos cuidadosamente su trabajo. Pero primero, tiene sentido averiguar cómo se organiza la distribución de servicios en el clúster y cuál es la tolerancia a fallas y la confiabilidad del almacenamiento de datos de esta solución en su conjunto.

Por
servicios comunes en el diagrama anterior nos referimos a los
servicios S3, HyperStore, CMC y Apache Cassandra . A primera vista, todo es hermoso y ordenado. Pero después de un examen más detallado, resulta que solo un fallo de un nodo se resuelve de manera efectiva. Y la pérdida simultánea de dos nodos a la vez puede ser fatal para la disponibilidad del clúster: Redis QoS (en el nodo 2) tiene solo 1 esclavo (en el nodo 3). La misma imagen con el riesgo de perder la administración del clúster: Puppet Server solo está en dos nodos (1 y 2). Sin embargo, la probabilidad de falla de dos nodos a la vez es muy baja, y puede vivir con ella.
Sin embargo, para aumentar la confiabilidad del almacenamiento, utilizamos 4 nodos en la línea de datos en lugar de los tres mínimos. Se obtiene la siguiente distribución de recursos:

Un matiz más llama la atención de inmediato: las
credenciales de Redis no se colocan en todos los nodos (como podría suponerse del esquema oficial anterior), sino solo en 3 de ellos. En este caso,
Redis Credentials se usa para cada solicitud entrante. Resulta que debido a la necesidad de ir al Redis de otra persona, existe un desequilibrio en el rendimiento del cuarto nodo.
Para nosotros, esto aún no es significativo. Durante las pruebas de estrés, no se notaron desviaciones significativas en la velocidad de respuesta de los nodos, pero en grandes grupos de docenas de nodos de trabajo, tiene sentido corregir este matiz.
Así es como se ve el esquema de migración en 6 nodos:
El diagrama muestra cómo se implementa la migración del servicio en caso de falla de un nodo. Solo se tiene en cuenta la falla de un servidor de cada rol. Si ambos servidores caen, se requerirá intervención manual.Aquí, también, el negocio no estuvo exento de algunas sutilezas. La migración de roles utiliza Puppet. Por lo tanto, si lo pierde o lo rompe accidentalmente, la conmutación por error automática puede no funcionar. Por el mismo motivo, no debe editar manualmente el manifiesto del Puppet incorporado. Esto no es del todo seguro, los cambios pueden deshilacharse repentinamente, ya que los manifiestos se editan utilizando el panel de administración del clúster.
Desde el punto de vista de la seguridad de los datos, todo es mucho más interesante. Los metadatos del objeto se almacenan en Apache Cassandra, y cada registro se replica en 3 de los 4 nodos. El factor de replicación 3 también se usa para almacenar datos, pero puede configurar uno más grande. Esto garantiza la seguridad de los datos incluso en caso de falla simultánea de 2 de 4 nodos. Y si tiene tiempo para reequilibrar el clúster, no puede perder nada con un nodo restante. Lo principal es tener suficiente espacio.
Esto es lo que sucede cuando fallan dos nodos. El diagrama muestra claramente que incluso en esta situación, los datos permanecen segurosAl mismo tiempo, la disponibilidad de datos y almacenamiento dependerá de la estrategia para garantizar la coherencia. Para datos, metadatos, lectura y escritura, se configura por separado.
Las opciones válidas son al menos un nodo, quórum o todos los nodos.
Esta configuración determina cuántos nodos deben confirmar escritura / lectura para que la solicitud se considere exitosa. Usamos el quórum como un compromiso razonable entre el tiempo que lleva procesar una solicitud y la confiabilidad de la escritura / inconsistencia de lectura. Es decir, de los tres nodos involucrados en la operación, para una operación libre de errores, es suficiente obtener una respuesta consistente de 2. En consecuencia, para mantenerse a flote en caso de falla de más de un nodo, deberá cambiar a una sola estrategia de escritura / lectura.
Procesamiento de consultas en Cloudian
A continuación consideraremos dos esquemas para procesar solicitudes entrantes en Cloudian HyperStore, PUT y GET. Esta es la tarea principal para S3 Service e HyperStore.
Comencemos con cómo se procesa la solicitud de escritura:

Seguramente notó que cada solicitud genera muchas comprobaciones y recuperaciones de datos, al menos 6 visitas de componente a componente. Es a partir de aquí que aparecen retrasos en la grabación y un alto consumo de tiempo de CPU al trabajar con archivos pequeños.
Los archivos grandes se transmiten por fragmentos. Los fragmentos separados no se consideran solicitudes separadas y algunas comprobaciones no se llevan a cabo.
El nodo que recibió la solicitud inicial además determina independientemente dónde y qué escribir, incluso si no está escrito directamente en él. Esto le permite ocultar la organización interna del clúster del cliente final y usar equilibradores de carga externos. Todo esto afecta positivamente la facilidad de mantenimiento y la tolerancia a fallas del almacenamiento.

Como puede ver, la lógica de lectura no es muy diferente de la escritura. En él, se observa la misma alta sensibilidad de rendimiento al tamaño de los objetos procesados. Por lo tanto, debido a los ahorros significativos en el trabajo con metadatos, es mucho más fácil extraer un objeto finamente cortado que muchos objetos separados del mismo volumen total.
Almacenamiento de datos y duplicación
Como puede ver en los diagramas anteriores, Cloudian admite varios esquemas de almacenamiento y duplicación de datos:
Replicación : mediante la replicación, es posible mantener un número personalizado de copias de cada objeto de datos en el sistema y almacenar cada copia en diferentes nodos. Por ejemplo, usando la replicación 3X, se crean 3 copias de cada objeto, y cada copia "se encuentra" en su propio nodo.
Codificación de borrado: con la codificación de borrado, cada objeto se codifica en una cantidad personalizada (conocida como número K) de fragmentos de datos más una cantidad personalizada de código de redundancia (número M). Cada fragmento K + M de un objeto es único y cada fragmento se almacena en su propio nodo. Un objeto se puede decodificar usando cualquier fragmento de K. En otras palabras, el objeto sigue siendo legible, incluso si M nodos son inaccesibles.
Por ejemplo, en la codificación de borrado, de acuerdo con la fórmula 4 + 2 (4 fragmentos de datos más 2 fragmentos de código de redundancia), cada objeto se divide en 6 fragmentos únicos almacenados en seis nodos diferentes, y este objeto puede restaurarse y leerse si hay 4 de 6 fragmentos disponibles. .
La ventaja de Erasure Coding en comparación con la replicación es que ahorra espacio, aunque a costa de un aumento significativo en la carga del procesador, el empeoramiento de la velocidad de respuesta y la necesidad de procedimientos en segundo plano para controlar la consistencia de los objetos. En cualquier caso, los metadatos se almacenan por separado de los datos (en Apache Cassandra), lo que aumenta la flexibilidad y la fiabilidad de la solución.
Brevemente sobre otras funciones de HyperStore
Como escribí al principio de este artículo, varias herramientas útiles están integradas en HyperStore. Entre ellos están:
- Facturación flexible con soporte para cambiar el precio de un recurso según el volumen y el plan de tarifas;
- Monitoreo incorporado
- La capacidad de limitar el uso de recursos para usuarios y grupos de usuarios;
- La configuración de QoS y los procedimientos integrados para equilibrar el uso de recursos entre nodos, así como los procedimientos regulares para reequilibrar entre nodos y discos en los nodos o al ingresar nuevos nodos en un clúster.
Sin embargo, Cloudian HyperStore todavía no es perfecto. Por ejemplo, por alguna razón, no puede transferir una cuenta existente a otro grupo o asignar múltiples grupos a un registro. No es posible generar informes de facturación provisionales: recibirá todos los informes solo después de cerrar el período de informe. Por lo tanto, ni los clientes ni nosotros podemos averiguar cuánto ha crecido la cuenta en tiempo real.
Cloudian HyperStore Logic
Ahora profundizaremos aún más y veremos lo más interesante en cualquier almacenamiento SDS: la lógica de la distribución de objetos por nodos. En el caso del almacenamiento en Cloudian, los metadatos se almacenan por separado de los datos en sí. Para los metadatos, Cassandra se utiliza, para los datos, la solución patentada HyperStore.
Desafortunadamente, hasta ahora no hay una traducción oficial de la documentación de Cloudian al ruso en Internet, así que a continuación publicaré mi traducción de las partes más interesantes de esta documentación.
El papel de Apache Cassandra en HyperStore
En HyperStore, Cassandra se usa para almacenar metadatos de objetos, información de cuenta de usuario y datos de uso del servicio. En una implementación típica en cada HyperStore, los datos de Cassandra se almacenan en la misma unidad que el sistema operativo. El sistema también admite datos Cassandra en una unidad dedicada en cada nodo. Los datos de Cassandra no se almacenan en discos de datos de HyperStore. Cuando se asignan vNodes al host, se distribuyen solo a los nodos de almacenamiento HyperStore. Los vNodos no están asignados a la unidad donde se almacenan los datos de Cassandra.
Dentro del clúster, los metadatos en Cassandra se replican de acuerdo con la política (estrategia) de su repositorio. Cassandra Data Replication usa vNodes de esta manera:
- Cuando se crea un nuevo objeto Cassandra (clave primaria y sus valores correspondientes), se convierte en hash y el hash se usa para asociar el objeto con un vNode específico. El sistema verifica a qué host está asignado este vNode, y luego la primera réplica del objeto Cassandra se almacena en la unidad Cassandra en ese host.
- Por ejemplo, suponga que a un host se le asignan 96 vNodos distribuidos en varios discos de datos de HyperStore. Los objetos Cassandra cuyos valores hash se encuentran dentro de los rangos de token de cualquiera de estos 96 vNodes se escribirán en la unidad Cassandra en este host.
- Las réplicas adicionales del objeto Cassandra (el número de réplicas depende de su configuración) se asocian con vNodes con el siguiente número de secuencia y se almacenan en el nodo al que se asignan estos vNodes, siempre que se omitan vNodes si es necesario, de modo que cada réplica del objeto Cassandra se almacene en otro máquina host
Cómo funciona el almacenamiento HyperStore
La ubicación y la replicación de los objetos S3 en un clúster HyperStore se basa en un esquema de almacenamiento en caché consistente que utiliza espacio de token entero en el rango de 0 a 2
127 -1. Los tokens enteros se asignan a los nodos HyperStore. Para cada objeto S3, se calcula un hash a medida que se carga en el almacenamiento. El objeto se almacena en el nodo al que se le asignó el valor más bajo del token, mayor o igual que el valor hash del objeto. La replicación también se implementa almacenando el objeto en los nodos a los que se han asignado tokens, que tienen un valor mínimo.
En un almacenamiento basado en hash coherente "clásico", se asigna un token a un nodo físico. El sistema Cloudian HyperStore usa y amplía la funcionalidad del "nodo virtual" (vNode) introducido en Cassandra en la versión 1.2: se asigna una gran cantidad de tokens a cada host físico (máximo 256). De hecho, el clúster de almacenamiento consta de una gran cantidad de "nodos virtuales" con una gran cantidad de nodos virtuales (tokens) en cada host físico.
El sistema HyperStore asigna un conjunto separado de tokens (nodos virtuales) a cada disco en cada host físico. Cada disco en el host es responsable de su propio conjunto de réplicas de objetos. Un fallo de disco solo afecta a las réplicas de los objetos que están en él. Otras unidades en el host continuarán funcionando y llevando a cabo sus responsabilidades de almacenamiento de datos.
Damos un ejemplo y consideramos un clúster de 6 hosts HyperStore, cada uno de los cuales tiene 4 discos de almacenamiento S3. Suponga que se asignan 32 tokens a cada host físico y que hay un espacio de tokens simplificado de 0 a 960, y el valor de 192 tokens en este sistema (6 hosts de 32 tokens) es 0, 5, 10, 15, 20, y así sucesivamente hasta 955.
El siguiente diagrama muestra una posible distribución de tokens en todo el clúster. 32 tokens de cada host se distribuyen uniformemente en 4 discos (8 tokens por disco), y los tokens se distribuyen aleatoriamente en todo el clúster.

Ahora suponga que configuró HyperStore para replicar 3X objetos S3. Acordemos que el objeto S3 se carga en el sistema, y el algoritmo hash aplicado a su nombre nos da el valor hash 322 (en este espacio hash simplificado). El siguiente diagrama muestra cómo se almacenarán tres instancias o réplicas de un objeto en un clúster:
- Con su valor hash de nombre 322, la primera réplica del objeto se almacena en el token 325, porque Este es el valor de token más pequeño que es mayor o igual que el valor hash del objeto. Se asignan 325 tokens (resaltados en rojo en el diagrama) a hyperstore2: Disk2. En consecuencia, la primera réplica del objeto se almacena allí.
- La segunda réplica se almacena en el disco al que se le asigna el siguiente token (330, resaltado en naranja), es decir, en hyperstore4: Disk2.
- La tercera réplica se guarda en el disco, al que se le asigna el siguiente token después de 330 - 335 (amarillo), en hyperstore3: Disk3.

Agregaré un comentario: desde un punto de vista práctico, esta optimización (la distribución de tokens no solo entre nodos físicos, sino también entre discos individuales) es necesaria no solo para garantizar la accesibilidad, sino también para garantizar una distribución uniforme de los datos entre los discos. En este caso, la matriz RAID no se utiliza, toda la lógica de asignación de datos en los discos está controlada por el propio HyperStore. Por un lado, es conveniente y controlado; si se pierde un disco, todo se reequilibrará por sí solo. Por otro lado, personalmente confío en más controladores RAID buenos, después de todo, su lógica se ha optimizado durante muchos años. Pero estas son todas mis preferencias personales, en jambas y problemas reales, nunca descubrimos HyperStore, si seguimos las recomendaciones del proveedor al instalar el software en servidores físicos. Pero el intento de usar la virtualización y los discos virtuales en la parte superior de la misma luna en el sistema de almacenamiento falló, cuando sobrecargó el sistema de almacenamiento durante las pruebas de carga, HyperStore se volvió loco y dispersó los datos de manera completamente desigual, obstruyendo algunos discos y sin tocar otros.
Dispositivo de accionamiento dentro de un clúster
Recuerde que cada host tiene 32 tokens, y los tokens de cada host se distribuyen uniformemente entre sus discos. Echemos un vistazo más de cerca a hyperstore2: Disk2 (en el diagrama a continuación). Vemos que los tokens 325, 425, 370 y demás están asignados a este disco.
Dado que el clúster está configurado para la replicación 3X, lo siguiente se almacenará en hyperstore2: Disco2:
De acuerdo con el token de disco 325:
- Las primeras réplicas de objetos con un valor hash de 320 (exclusivamente) a 325 (inclusive);
- Segundas réplicas de objetos con un valor hash de 315 (exclusivamente) a 320 (inclusive);
- Terceras réplicas de objetos con un valor hash de 310 (exclusivamente) a 315 (inclusive).
Según el token de disco 425:
- Las primeras réplicas de objetos con un valor hash de 420 (exclusivamente) a 425 (inclusive);
- Segundas réplicas de objetos con un valor hash de 415 (exclusivamente) a 420 (inclusive);
- Terceras réplicas de objetos con un valor hash de 410 (exclusivamente) a 415 (inclusive).
Y así sucesivamente.
, HyperStore , . hyperstore2:disk2 .

2 1, 3 4 , 2 , .. .
: , / HyperStore Cassandra. , , , , «» . . . , : , , .
, HyperStore . - . . () , .
, , ,
«Multi-Data Center Deployments».HyperStore -. DC1 DC2. - 3 . , , 32 (vNodes), 0 960. -, 192 — 32 6 . .
, S3 -.
, S3 942 2 -:
- vNode 945 ( ), DC2, hyperstore5:Disk3.
- vNode 950 ( ) DC2, hyperstore6:Disk4.
- vNode 955 DC2, , vNode .
- vNode 0 () — DC1, hyperstore2:Disk3. , (955) (0).
- vNode (5) DC2, , vNode .
- vNode 10 () — DC1, hyperstore3:Disk3.

: , , , , . , .
Cloudian. , , . , , , , .
S3 DataLine, , !