HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

A próxima conferencia HighLoad++ celebrarase os días 6 e 7 de abril de 2020 en San Petersburgo.
Detalles e entradas по ссылке. HighLoad++ Siberia 2019. Salón "Krasnoyarsk". 25 de xuño, 12:00 h. Teses e presentación.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Ocorre que os requisitos prácticos entran en conflito coa teoría, onde non se teñen en conta aspectos importantes para un produto comercial. Esta charla presenta un proceso para seleccionar e combinar diferentes enfoques para crear compoñentes de consistencia causal baseados na investigación académica baseada nos requisitos dun produto comercial. Os oíntes aprenderán sobre os enfoques teóricos existentes para os reloxos lóxicos, o seguimento de dependencias, a seguridade do sistema, a sincronización de reloxos e por que MongoDB optou por certas solucións.

Mikhail Tyulenev (en diante MT): – Falarei sobre a coherencia causal: esta é unha función na que traballamos en MongoDB. Traballo nun grupo de sistemas distribuídos, fixémolo hai uns dous anos.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

No proceso, tiven que familiarizarme con moitas investigacións académicas, porque esta característica foi estudada bastante ben. Resultou que nin un só artigo encaixa no que se require nunha base de datos de produción debido a requisitos moi específicos que probablemente estean presentes en calquera aplicación de produción.

Falarei de como nós, como consumidores de Investigación académica, preparamos algo a partir del que podemos presentar aos nosos usuarios como un prato preparado que sexa cómodo e seguro de usar.

Consistencia causal. Definamos os conceptos

Para comezar, quero dicir en termos xerais o que é a coherencia causal. Hai dous personaxes: Leonard e Penny (serie de televisión "The Big Bang Theory"):

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Digamos que Penny está en Europa e Leonard quere facerlle unha festa sorpresa. E non se lle ocorre nada mellor que botala da súa lista de amigos, enviando a todos os seus amigos unha actualización sobre o feed: "Imos facer feliz a Penny!" (está en Europa, mentres dorme, non ve todo isto e non pode velo, porque non está). En definitiva, ela elimina esta publicación, bórraa do Feed e restablece o acceso para que non se decate de nada e non haxa escándalo.
Todo isto está ben, pero supoñamos que o sistema está distribuído e as cousas saíron un pouco mal. Pode, por exemplo, ocorrer que a restrición de acceso de Penny ocorrese despois de aparecer esta publicación, se os eventos non están relacionados por causa e efecto. En realidade, este é un exemplo de cando se require a coherencia causal para realizar unha función comercial (neste caso).

De feito, estas son propiedades non triviais da base de datos: moi poucas persoas as admiten. Pasemos aos modelos.

Modelos de consistencia

Que é exactamente un modelo de coherencia nas bases de datos? Estas son algunhas das garantías que dá un sistema distribuído sobre que datos pode recibir o cliente e en que secuencia.

En principio, todos os modelos de coherencia redúcense ao parecido que é un sistema distribuído a un sistema que se executa, por exemplo, nun nodo dun portátil. E así de parecido é un sistema que funciona en miles de "Nodos" xeodistribuídos a un portátil, no que todas estas propiedades realízanse en principio automaticamente.

Polo tanto, os modelos de coherencia aplícanse só a sistemas distribuídos. Todos os sistemas que existían anteriormente e funcionaban coa mesma escala vertical non experimentaron tales problemas. Había un Buffer Cache, e sempre se lía todo del.

Modelo Strong

En realidade, o primeiro modelo é Strong (ou a liña de capacidade de ascenso, como se adoita chamar). Trátase dun modelo de coherencia que garante que cada cambio, unha vez confirmado que se produciu, sexa visible para todos os usuarios do sistema.

Isto crea unha orde global de todos os eventos da base de datos. Esta é unha propiedade de consistencia moi forte e, en xeral, é moi cara. Non obstante, está moi ben apoiado. É moi caro e lento, só se usa raramente. Isto chámase capacidade de subida.

Hai outra propiedade máis forte que se admite en Spanner, chamada coherencia externa. Falarémolo un pouco máis tarde.

Causal

O seguinte é Causal, que é exactamente do que falaba. Hai varios sub-niveis máis entre Forte e Causal dos que non vou falar, pero todos se reducen a Causal. Este é un modelo importante porque é o máis forte de todos os modelos, a consistencia máis forte na presenza dunha rede ou particións.

As causas son en realidade unha situación na que os acontecementos están conectados por unha relación causa-efecto. Moitas veces percíbense como Lea os seus dereitos desde o punto de vista do cliente. Se o cliente observou algúns valores, non pode ver valores que estaban no pasado. Xa comeza a ver lecturas de prefixos. Todo se reduce ao mesmo.
Causals como modelo de coherencia é unha ordenación parcial dos eventos no servidor, na que se observan eventos de todos os clientes na mesma secuencia. Neste caso, Leonard e Penny.

Eventual

O terceiro modelo é a coherencia eventual. Isto é o que admiten absolutamente todos os sistemas distribuídos, o modelo mínimo que ten sentido. Significa o seguinte: cando temos algúns cambios nos datos, nalgún momento vólvense consistentes.

Nese momento non di nada, se non, converteríase en coherencia externa; sería unha historia completamente diferente. Non obstante, este é un modelo moi popular, o máis común. De forma predeterminada, todos os usuarios de sistemas distribuídos usan Eventual Consistency.

Quero poñer algúns exemplos comparativos:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Que significan estas frechas?

  • Latencia. A medida que aumenta a forza de consistencia, faise máis grande por razóns obvias: cómpre facer máis rexistros, obter a confirmación de todos os hosts e nodos que participan no clúster de que os datos xa están alí. En consecuencia, Eventual Consistency ten a resposta máis rápida, porque alí, por regra xeral, incluso podes recordala e isto, en principio, será suficiente.
  • Dispoñibilidade. Se entendemos isto como a capacidade do sistema para responder en presenza de roturas de rede, particións ou algún tipo de fallo, a tolerancia a fallos aumenta a medida que diminúe o modelo de consistencia, xa que é suficiente para nós que viva un servidor e ao mesmo tempo. o tempo produce algúns datos. A coherencia eventual non garante nada sobre os datos, pode ser calquera cousa.
  • Anomalías. Ao mesmo tempo, por suposto, aumenta o número de anomalías. En Strong Consistency case non deberían existir en absoluto, pero en Eventual Consistency poden ser calquera cousa. Xorde a pregunta: por que a xente elixe a coherencia eventual se contén anomalías? A resposta é que os modelos de coherencia eventual son aplicables e as anomalías existen, por exemplo, nun curto período de tempo; é posible utilizar o asistente para ler e ler datos máis ou menos consistentes; Moitas veces é posible utilizar modelos de consistencia forte. Na práctica isto funciona, e moitas veces o número de anomalías é limitado no tempo.

Teorema CAP

Cando ves as palabras coherencia, dispoñibilidade, que se che ocorre? É certo - teorema CAP! Agora quero disipar o mito... Non son eu, son Martin Kleppmann, quen escribiu un artigo marabilloso, un libro marabilloso.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

O teorema CAP é un principio formulado na década de 2000 de que Consistencia, Dispoñibilidade, Particións: toma dúas calquera e non podes escoller tres. Era un certo principio. Foi probado como un teorema uns anos máis tarde por Gilbert e Lynch. Entón isto comezou a usarse como mantra: os sistemas comezaron a dividirse en CA, CP, AP, etc.

Este teorema foi realmente probado para os seguintes casos... En primeiro lugar, a dispoñibilidade non se considerou como un valor continuo de cero a centenas (0 - o sistema está "morto", 100 - responde rapidamente; estamos afeitos a consideralo así) , senón como unha propiedade do algoritmo , que garante que para todas as súas execucións devolve datos.

Non hai unha palabra sobre o tempo de resposta! Hai un algoritmo que devolve datos despois de 100 anos, un algoritmo dispoñible absolutamente marabilloso, que forma parte do teorema CAP.
Segundo: o teorema demostrouse para os cambios nos valores da mesma clave, a pesar de que estes cambios son redimensionables. Isto significa que en realidade non se usan practicamente, porque os modelos son diferentes Consistencia Eventual, Consistencia Forte (quizais).

Para que serve todo isto? Ademais, o teorema CAP exactamente na forma na que se demostrou é practicamente inaplicable e úsase raramente. Na forma teórica, dalgunha maneira limita todo. Resulta que un certo principio é intuitivamente correcto, pero que en xeral non se demostrou.

A consistencia causal é o modelo máis forte

O que está a suceder agora é que podes obter as tres cousas: coherencia, dispoñibilidade mediante particións. En particular, a coherencia causal é o modelo de coherencia máis forte, que aínda funciona en presenza de particións (roturas na rede). Por iso é de tan grande interese, e por iso asumimos.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

En primeiro lugar, simplifica o traballo dos desenvolvedores de aplicacións. En particular, a presenza dun gran soporte do servidor: cando todos os rexistros que se producen dentro dun cliente están garantidos para chegar na mesma secuencia a outro cliente. En segundo lugar, soporta particións.

Cociña Interior MongoDB

Lembrando que é xantar, pasamos á cociña. Falarei sobre o modelo do sistema, é dicir, o que é MongoDB para aqueles que están escoitando falar desta base de datos por primeira vez.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

MongoDB (en diante denominado "MongoDB") é un sistema distribuído que admite a escala horizontal, é dicir, a fragmentación; e dentro de cada fragmento tamén admite a redundancia de datos, é dicir, a replicación.

Sharding en MongoDB (non unha base de datos relacional) realiza un equilibrio automático, é dicir, cada colección de documentos (ou "táboa" en termos de datos relacionais) divídese en anacos e o servidor móvese automaticamente entre fragmentos.

O Query Router, que distribúe as solicitudes, para un cliente é algún cliente a través do cal funciona. Xa sabe onde e que datos se atopan e dirixe todas as solicitudes ao fragmento correcto.

Outro punto importante: MongoDB é un único mestre. Hai unha primaria: pode levar rexistros que admitan as claves que contén. Non podes facer a escritura multimaster.

Fixemos a versión 4.2: apareceron novas cousas interesantes. En concreto, inseriron Lucene -busca-, ou sexa, o executable java directamente en Mongo, e alí se fixo posible realizar buscas a través de Lucene, o mesmo que en Elastica.

E fixeron un novo produto - Charts, tamén está dispoñible en Atlas (a propia nube de Mongo). Teñen un nivel gratuíto: podes xogar con el. Gustoume moito Charts: visualización de datos, moi intuitiva.

Ingredientes Consistencia causal

Contei uns 230 artigos que se publicaron sobre este tema, de Leslie Lampert. Agora da miña memoria vouvos transmitir algunhas partes destes materiais.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Todo comezou cun artigo de Leslie Lampert, que foi escrito na década de 1970. Como podes ver, algunhas investigacións sobre este tema aínda están en curso. Agora a coherencia causal está a experimentar interese en relación co desenvolvemento de sistemas distribuídos.

Restricións

Que restricións hai? Este é en realidade un dos puntos principais, porque as restricións que un sistema de produción impón son moi diferentes ás restricións que existen nos artigos académicos. Moitas veces son bastante artificiais.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

  • En primeiro lugar, "MongoDB" é un único mestre, como xa dixen (isto simplifica moito).
  • Cremos que o sistema debería soportar uns 10 mil fragmentos. Non podemos tomar ningunha decisión arquitectónica que limite explícitamente este valor.
  • Temos unha nube, pero supoñemos que unha persoa aínda debería ter a oportunidade cando descarga binario, execútao no seu portátil e todo funciona moi ben.
  • Asumimos algo que Research raramente asume: os clientes externos poden facer o que queiran. MongoDB é de código aberto. En consecuencia, os clientes poden ser tan intelixentes e enfadados, poden querer romper todo. Especulamos que os feilors bizantinos poden orixinarse.
  • Para os clientes externos que están fóra do perímetro, hai unha limitación importante: se esta función está desactivada, non se debe observar ningunha degradación do rendemento.
  • Outro punto é xeralmente antiacadémico: a compatibilidade de versións anteriores e futuras. Os controladores antigos deben admitir novas actualizacións e a base de datos debe admitir controladores antigos.

En xeral, todo isto impón restricións.

Compoñentes de consistencia causal

Agora vou falar dalgúns dos compoñentes. Se consideramos a coherencia causal en xeral, podemos seleccionar bloques. Escollemos entre obras que pertencen a un determinado bloque: seguimento de dependencias, elección de reloxos, como se poden sincronizar estes reloxos entre si e como garantimos a seguridade. Este é un esbozo do que vou falar:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Seguimento completo da dependencia

Por que é necesario? De xeito que cando se replican os datos, cada rexistro, cada cambio de datos contén información sobre os cambios dos que depende. O primeiro e inxenuo cambio é cando cada mensaxe que contén un rexistro contén información sobre mensaxes anteriores:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Neste exemplo, o número entre corchetes son os números de rexistro. Ás veces, estes rexistros con valores incluso transfírense na súa totalidade, ás veces transfírense algunhas versións. A conclusión é que cada cambio contén información sobre o anterior (obviamente leva todo isto dentro de si).

Por que decidimos non utilizar este enfoque (seguimento completo)? Obviamente, porque este enfoque non é práctico: calquera cambio nunha rede social depende de todos os cambios anteriores a esa rede social, transferindo, por exemplo, Facebook ou VKontakte en cada actualización. Non obstante, hai moita investigación sobre o seguimento da dependencia total: estas son redes pre-sociais; para algunhas situacións realmente funciona.

Seguimento explícito de dependencias

O seguinte é máis limitado. Aquí tamén se considera a transferencia de información, pero só a que é claramente dependente. O que depende do que, por regra xeral, determine a Aplicación. Cando se replican os datos, a consulta só devolve respostas cando se cumpriron as dependencias anteriores, é dicir, se mostran. Esta é a esencia de como funciona a consistencia causal.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Ela ve que o rexistro 5 depende dos rexistros 1, 2, 3, 4; polo tanto, espera antes de que o cliente teña acceso aos cambios realizados pola decisión de acceso de Penny, cando todos os cambios anteriores xa pasaron pola base de datos.

Isto tampouco nos convén, porque aínda hai demasiada información, e ralentizará as cousas. Hai outro enfoque...

Reloxo Lampport

Son moi vellos. Reloxo Lamport significa que estas dependencias están dobradas nunha función escalar, que se chama Reloxo Lamport.

Unha función escalar é un número abstracto. Adóitase chamar tempo lóxico. Con cada evento, este contador aumenta. O contador, que actualmente coñece o proceso, envía cada mensaxe. Está claro que os procesos poden estar dessincronizados, poden ter tempos completamente diferentes. Non obstante, o sistema equilibra dalgunha maneira o reloxo con esa mensaxe. Que pasa neste caso?

Divide ese gran fragmento en dous para que quede claro: os amigos poden vivir nun nodo, que contén unha parte da colección, e Feed pode vivir noutro nodo, que contén unha parte desta colección. Está claro como poden saír da liña? O primeiro feed dirá: "Replicado" e despois Amigos. Se o sistema non ofrece algún tipo de garantía de que o feed non se mostrará ata que tamén se entreguen as dependencias de Friends na colección Friends, teremos exactamente a situación que mencionei.

Ves como o tempo do contador en Feed aumenta loxicamente:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Polo tanto, a principal propiedade deste reloxo de Lamport e a consistencia causal (explicada a través do reloxo de Lamport) é a seguinte: se temos eventos A e B, e o evento B depende do evento A*, dedúcese que o tempo lóxico do evento A é menor que Tempo lóxico do evento B.

* Ás veces tamén din que A sucedeu antes de B, é dicir, A sucedeu antes de B - esta é unha determinada relación que ordena parcialmente todo o conxunto de acontecementos que ocorreron en xeral.

O contrario é incorrecto. Esta é en realidade unha das principais desvantaxes de Lamport Clock - orde parcial. Existe un concepto sobre sucesos simultáneos, é dicir, sucesos nos que nin (A sucedeu antes de B) nin (A sucedeu antes de B). Un exemplo sería a incorporación paralela de Leonard a outra persoa como amigo (nin sequera Leonard, pero Sheldon, por exemplo).
Esta é a propiedade que se usa a miúdo cando se traballa con reloxos de Lamport: miran especificamente a función e diso conclúen que quizais estes eventos sexan dependentes. Porque un xeito é verdade: se o Tempo lóxico A é menor que o Tempo lóxico B, entón B non pode ocorrer antes que A; e se máis, quizais.

Reloxo Vectorial

O desenvolvemento lóxico do reloxo de Lamport é o reloxo vectorial. Diferéncianse en que cada nodo que está aquí contén o seu propio reloxo separado e transmítense como un vector.
Neste caso, ves que o índice cero do vector é responsable de Feed, e o primeiro índice do vector é de Friends (cada un destes nodos). E agora aumentarán: o índice cero de "Feed" aumenta ao escribir - 1, 2, 3:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Por que é mellor o reloxo vectorial? Porque permiten descubrir que eventos son simultáneos e cando ocorren en diferentes nodos. Isto é moi importante para un sistema de fragmentación como MongoDB. Non obstante, non escollemos isto, aínda que é unha cousa marabillosa, funciona moi ben, e probablemente nos conveña...

Se temos 10 mil fragmentos, non podemos transferir 10 mil compoñentes, aínda que os comprimamos ou creamos outra cousa: a carga útil aínda será varias veces menor que o volume de todo este vector. Por iso, apretando o corazón e os dentes, abandonamos este enfoque e pasamos a outro.

Chave TrueTime. Reloxo atómico

Dixen que habería unha historia sobre Spanner. Isto é unha cousa xenial, directamente do século XXI: reloxos atómicos, sincronización GPS.

Cal é a idea? "Spanner" é un sistema de Google que recentemente chegou a estar dispoñible para as persoas (engadíronlle SQL). Cada transacción ten algún selo de tempo. Dado que o tempo está sincronizado*, a cada evento pódese asignar unha hora específica: os reloxos atómicos teñen un tempo de espera, despois do cal se garante que "ocorrerá" un tempo diferente.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Así, simplemente escribindo na base de datos e esperando un período de tempo, a Serialización do evento está garantida automaticamente. Teñen o modelo de coherencia máis forte que se pode imaxinar en principio: é a coherencia externa.

* Este é o principal problema dos reloxos Lampart: nunca son sincrónicos en sistemas distribuídos. Poden diverxer; mesmo con NTP, aínda non funcionan moi ben. "Spanner" ten un reloxo atómico e a sincronización, ao parecer, é de microsegundos.

Por que non escollemos? Non asumimos que os nosos usuarios teñan un reloxo atómico incorporado. Cando aparezan, integradas en todos os portátiles, haberá algún tipo de sincronización GPS súper chula, entón si... Pero polo momento o mellor posible é Amazon, Base Stations, para os fanáticos... Así que usamos outros reloxos. .

Reloxo Híbrido

Isto é realmente o que marca MongoDB cando se garante a coherencia causal. Como son híbridos? O híbrido é un valor escalar, pero ten dous compoñentes:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

  • A primeira é a época de Unix (cantos segundos pasaron desde o “comezo do mundo da informática”).
  • O segundo é algún incremento, tamén un int sen signo de 32 bits.

Iso é todo, en realidade. Existe este enfoque: a parte responsable do tempo está sincronizada co reloxo todo o tempo; cada vez que se produce unha actualización, esta parte sincronízase co reloxo e resulta que a hora é sempre máis ou menos correcta, e o incremento permite distinguir entre eventos que ocorreron no mesmo momento no tempo.

Por que é importante para MongoDB? Porque permite facer algún tipo de restaurantes de reserva nun momento determinado, é dicir, o evento está indexado por tempo. Isto é importante cando se necesitan certos eventos; Para unha base de datos, os eventos son cambios na base de datos que ocorreron en determinados intervalos de tempo.

Vouche dicir a razón máis importante só para ti (por favor, non llo digas a ninguén)! Fixemos isto porque así se ven os datos organizados e indexados en MongoDB OpLog. OpLog é unha estrutura de datos que contén absolutamente todos os cambios na base de datos: primeiro van a OpLog e despois aplícanse ao propio Almacenamento no caso de que se trate dunha data ou fragmento replicado.

Esta foi a razón principal. Aínda así, tamén hai requisitos prácticos para desenvolver unha base de datos, o que significa que debe ser sinxelo: pouco código, o menor número posible de cousas rotas que deben ser reescritas e probadas. O feito de que os nosos oplogs estivesen indexados por reloxos híbridos axudou moito e permitiunos facer a elección correcta. Realmente pagou a pena e, dalgún xeito, funcionou máxicamente no primeiro prototipo. Foi moi chulo!

Sincronización do reloxo

Existen varios métodos de sincronización descritos na literatura científica. Falo de sincronización cando temos dous fragmentos diferentes. Se hai un conxunto de réplicas, non hai necesidade de ningunha sincronización: este é un "mestre único"; temos un OpLog, no que todos os cambios caen; neste caso, todo xa está ordenado secuencialmente no propio "Oplog". Pero se temos dous fragmentos diferentes, aquí é importante a sincronización horaria. Aquí é onde o reloxo vectorial axudou máis! Pero non os temos.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

O segundo é adecuado: este é "Heartbeats". É posible intercambiar algúns sinais que ocorren cada unidade de tempo. Pero os latexos son demasiado lentos, non podemos proporcionarlle latencia ao noso cliente.

O tempo verdadeiro é, por suposto, unha cousa marabillosa. Pero, de novo, este é probablemente o futuro... Aínda que xa se pode facer en Atlas, xa hai sincronizadores de tempo "Amazon" rápidos. Pero non estará dispoñible para todos.

Cotillear é cando todas as mensaxes inclúen o tempo. Isto é aproximadamente o que usamos. Cada mensaxe entre nodos, un controlador, un enrutador de nodos de datos, absolutamente todo para MongoDB é algún tipo de elemento, un compoñente de base de datos que contén un reloxo que se executa. Teñen o significado de tempo híbrido en todas partes, transmítese. 64 bits? Isto permite, isto é posible.

Como funciona todo xunto?

Aquí estou mirando un conxunto de réplicas para facelo un pouco máis fácil. Hai Primaria e Secundaria. O secundario fai a replicación e non sempre está completamente sincronizado co primario.

Prodúcese unha inserción no "Primary" cun determinado valor de tempo. Esta inserción aumenta o reconto interno en 11, se este é o máximo. Ou comprobará os valores do reloxo e sincronizarase co reloxo se os valores do reloxo son maiores. Isto permítelle organizar por tempo.

Despois de que fai a gravación, ocorre un momento importante. O reloxo está en "MongoDB" e só se incrementa en caso de escribir en "Oplog". Este é o evento que cambia o estado do sistema. En absolutamente todos os artigos clásicos, considérase un evento cando unha mensaxe chega a un nodo: a mensaxe chegou, o que significa que o sistema cambiou o seu estado.

Isto débese a que durante a investigación non está do todo claro como se interpretará esta mensaxe. Sabemos con certeza que se non se reflicte no "Oplog", non se interpretará de ningún xeito, e un cambio no estado do sistema é só unha entrada no "Oplog". Isto simplifícanos todo: o modelo simplifícao e permítenos organizalo nun conxunto de réplicas e moitas outras cousas útiles.

Devólvese o valor que xa está escrito no "Oplog"; sabemos que o "Oplog" xa contén este valor e o seu tempo é 12. Agora, digamos, a lectura comeza desde outro nodo (Secundario) e transmite despois de ClusterTime en a mensaxe. El di: "Necesito todo o que pasou polo menos despois das 12 ou durante as doce" (ver imaxe superior).

Isto é o que se chama Causal a consistente (CAT). Hai un concepto tal en teoría que este é unha porción de tempo, que é consistente en si mesmo. Neste caso, podemos dicir que este é o estado do sistema que se observou no momento 12.

Agora non hai nada aquí aínda, porque este tipo de simula a situación na que necesitas o secundario para replicar os datos do primario. El espera... E agora chegaron os datos: devolve estes valores.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Así é practicamente como funciona todo. Case.

Que significa "case"? Supoñamos que hai algunha persoa que leu e entendeu como funciona todo isto. Decateime de que cada vez que se produce ClusterTime, actualiza o reloxo lóxico interno e, a continuación, a seguinte entrada aumenta nun. Esta función ocupa 20 liñas. Digamos que esta persoa transmite o maior número de 64 bits, menos un.

Por que "menos un"? Debido a que o reloxo interno substituirase neste valor (obviamente, este é o maior posible e maior que a hora actual), entón producirase unha entrada en "Oplog" e o reloxo incrementarase noutra unidade, e xa haberá ser un valor máximo (simplemente hai todas as unidades, non hai ningún outro lugar a onde ir), unsaint ints).

Está claro que despois disto o sistema vólvese absolutamente inaccesible para nada. Só se pode descargar e limpar - moito traballo manual. Dispoñibilidade total:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Ademais, se isto é replicado noutro lugar, entón todo o clúster simplemente cae. Unha situación absolutamente inaceptable que calquera pode organizar de xeito rápido e sinxelo! Por iso, consideramos este momento como un dos máis importantes. Como evitalo?

O noso xeito é asinar clusterTime

Así se transmite na mensaxe (antes do texto azul). Pero tamén comezamos a xerar unha sinatura (texto azul):

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

A sinatura é xerada por unha clave que se almacena dentro da base de datos, dentro dun perímetro seguro; xérase e actualízase en si (os usuarios non ven nada ao respecto). Xérase un hash e cada mensaxe asinase cando se crea e validase cando se recibe.
Probablemente xorde na mente das persoas: "Canto retarda isto?" Díxenche que debería funcionar rapidamente, especialmente en ausencia desta función.

Que significa usar a coherencia causal neste caso? Isto é para mostrar o parámetro afterClusterTime. Sen isto, simplemente pasará os valores de todos os xeitos. As fofocas, a partir da versión 3.6, sempre funcionan.

Se deixamos a xeración constante de sinaturas, ralentizará o sistema aínda que non exista unha función que non cumpra os nosos enfoques e requisitos. Entón, que fixemos?

Faino rapidamente!

É algo bastante sinxelo, pero o truco é interesante: compartireino, quizais a alguén lle interese.
Temos un hash que almacena os datos asinados. Todos os datos pasan pola caché. A caché non asina a hora específica, senón o intervalo. Cando chega algún valor, xeramos un intervalo, enmascaramos os últimos 16 bits e asinamos este valor:

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Ao recibir tal sinatura, aceleramos o sistema (relativamente) 65 mil veces. Funciona moi ben: cando realizamos experimentos, o tempo realmente diminuíu 10 mil veces cando tiñamos unha actualización secuencial. Está claro que cando están en desacordo, isto non funciona. Pero na maioría dos casos prácticos funciona. A combinación da sinatura Range xunto coa sinatura resolveu o problema de seguridade.

Que aprendemos?

Leccións que aprendemos disto:

  • Necesitamos ler materiais, contos, artigos, porque temos moitas cousas interesantes. Cando traballamos nalgunha función (especialmente agora, cando fixemos transaccións, etc.), necesitamos ler e comprender. Leva tempo, pero en realidade é moi útil porque deixa claro onde estamos. Non parecíamos chegar a nada novo: só tomamos os ingredientes.

    En xeral, hai unha certa diferenza de pensamento cando hai unha conferencia académica (Sigmon, por exemplo) - todo o mundo céntrase en novas ideas. Que hai de novo sobre o noso algoritmo? Non hai nada especialmente novo aquí. A novidade reside máis ben na forma en que combinamos os enfoques existentes. Polo tanto, o primeiro é ler os clásicos, comezando por Lampart.

  • Na produción, os requisitos son completamente diferentes. Estou seguro de que moitos de vostedes non se enfrontan a bases de datos “esféricas” nun baleiro abstracto, senón a cousas normais e reais que teñen problemas de dispoñibilidade, latencia e tolerancia a fallos.
  • O último é que tivemos que mirar ideas diferentes e combinar varios artigos completamente diferentes nun enfoque, xuntos. A idea de asinar, por exemplo, xurdiu en xeral dun artigo que consideraba o protocolo de Paxos, que para os fracasantes non bizantinos está dentro do protocolo de autorización, para os bizantinos -fóra do protocolo de autorización... En xeral, isto é exactamente o que nós acabou facendo.

    Non hai absolutamente nada novo aquí! Pero en canto o mesturamos todo... É o mesmo que dicir que a receita da ensalada Olivier é unha tontería, porque xa se inventaron os ovos, a maionesa e os pepinos... É da mesma historia.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Rematarei con isto. Grazas!

preguntas

Pregunta da audiencia (en diante B): – Grazas, Mikhail, pola reportaxe! O tema do tempo é interesante. Estás a usar Gossiping. Dicían que cada un ten o seu tempo, cada un sabe a súa hora local. Segundo teño entendido, temos un controlador: pode haber moitos clientes con controladores, query-planners tamén, fragmentos tamén... E a que se reduce o sistema se de súpeto temos unha discrepancia: alguén decide que é para un minuto por diante, alguén un minuto atrás? Onde imos parar?

MT: - ¡Gran pregunta! Só quería falar de cacos. Se entendo correctamente a pregunta, temos a seguinte situación: hai fragmento 1 e fragmento 2, a lectura prodúcese a partir destes dous fragmentos: teñen unha discrepancia, non interactúan entre si, porque o tempo que coñecen é diferente, especialmente o tempo que existen en oplogs.
Digamos que o fragmento 1 fixo un millón de rexistros, o fragmento 2 non fixo nada e a solicitude chegou a dous fragmentos. E o primeiro ten un afterClusterTime de máis dun millón. En tal situación, como expliquei, o fragmento 2 nunca responderá en absoluto.

EN: – Quería saber como se sincronizan e escoller unha hora lóxica?

MT: - Moi fácil de sincronizar. Shard, cando despois de ClusterTime chega a el e non atopa tempo no "Oplog", non inicia ningún aprobado. É dicir, eleva o seu tempo coas mans a este valor. Isto significa que non ten ningún evento que coincida con esta solicitude. El crea este evento de forma artificial e, polo tanto, faise coherente causal.

EN: – E se despois disto lle chegan outros acontecementos que se perderon nalgún lugar da rede?

MT: – Shard está deseñada de tal xeito que non volverán a vir, xa que é un único mestre. Se xa se inscribiu, entón non virán, pero virán máis tarde. Non pode ocorrer que algo quede atascado nalgún lugar, entón non escribe, e despois chegan estes eventos, e a consistencia causal rómpese. Cando non escribe, deberían vir todos a continuación (esperaraos).

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

EN: – Teño varias preguntas sobre as colas. A coherencia causal supón que hai unha cola específica de accións que se deben realizar. Que pasa se un dos nosos paquetes desaparece? Aquí chega o 10, 11... o 12 desapareceu, e todos agardan que se faga realidade. E de súpeto o noso coche morreu, non podemos facer nada. Existe unha lonxitude máxima da cola que se acumula antes de ser executada? Que fallo fatal ocorre cando se perde un estado? Ademais, se anotamos que hai algún estado anterior, entón deberíamos partir dalgún xeito? Pero non o afastaron!

MT: - Tamén unha gran pregunta! Que estamos facendo? MongoDB ten o concepto de escritura de quórum, lectura de quórum. En que casos se pode perder unha mensaxe? Cando unha escritura non é quórum ou cando unha lectura non é quórum (tamén pode quedar algún tipo de lixo).
En canto á coherencia causal, realizouse unha gran proba experimental, cuxo resultado foi que no caso de que as escrituras e lecturas non sexan quórum, prodúcense violacións da coherencia causal. Exactamente o que dis!

O noso consello: use polo menos a lectura de quórum cando use a coherencia causal. Neste caso non se perderá nada, aínda que se perda o rexistro de quórum... Esta é unha situación ortogonal: se o usuario non quere que se perdan datos, ten que utilizar un rexistro de quórum. A consistencia causal non garante a durabilidade. A durabilidade está garantida pola replicación e a maquinaria asociada á replicación.

EN: – Cando creamos unha instancia que realiza fragmentos por nós (non mestre, senón escravo, respectivamente), depende do tempo Unix da súa propia máquina ou do tempo do “mestre”; Sincronizase por primeira vez ou periodicamente?

MT: - Vou aclarar agora. Fragmento (é dicir, partición horizontal): sempre hai un Primario alí. E un fragmento pode ter un "mestre" e pode haber réplicas. Pero o fragmento sempre admite a gravación, porque debe admitir algún dominio (o fragmento ten Primario).

EN: – Entón, todo depende puramente do “mestre”? Emprégase sempre o tempo mestre?

MT: - Si. Podes dicir en sentido figurado: o reloxo corre cando se produce unha entrada no "mestre", no "Oplog".

EN: – Temos un cliente que se conecta e non precisa saber nada do tempo?

MT: - Non necesitas saber nada! Se falamos de como funciona no cliente: cando o cliente quere utilizar a coherencia causal, ten que abrir unha sesión. Agora todo está aí: transaccións na sesión, e recuperar dereitos... Unha sesión é a ordenación dos eventos lóxicos que ocorren co cliente.

Se abre esta sesión e di alí que quere coherencia causal (se a sesión admite a coherencia causal por defecto), todo funciona automaticamente. O condutor lembra este tempo e aumenta cando recibe unha nova mensaxe. Lembra que resposta devolveu o anterior do servidor que devolveu os datos. A seguinte solicitude conterá afterCluster ("tempo maior que este").

O cliente non precisa saber absolutamente nada! Isto é completamente opaco para el. Se as persoas usan estas funcións, que poden facer? En primeiro lugar, podes ler con seguridade secundarias: podes escribir en Primaria e ler desde secundarias replicadas xeograficamente e asegurarte de que funciona. Ao mesmo tempo, as sesións que se gravaron en Primaria poden incluso transferirse a Secundaria, é dicir, podes usar non unha sesión, senón varias.

EN: – Unha nova capa de ciencia da computación – tipos de datos CRDT (Tipos de datos replicados sen conflitos) – está moi relacionada co tema da coherencia eventual. Considerou integrar este tipo de datos na base de datos e que pode dicir ao respecto?

MT: - Boa pregunta! CRDT ten sentido para conflitos de escritura: en MongoDB, mestre único.

EN: – Teño unha pregunta dos devops. No mundo real, hai tales situacións xesuíticas nas que se produce o fracaso bizantino e as persoas malvadas dentro do perímetro protexido comezan a meterse no protocolo, enviar paquetes de artesanía dun xeito especial?

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

MT: – As persoas malvadas dentro do perímetro son como un cabalo de Troia! As persoas malvadas dentro do perímetro poden facer moitas cousas malas.

EN: – Está claro que deixando, grosso modo, un burato no servidor polo que podes poñer un zoolóxico de elefantes e colapsar todo o cúmulo para sempre... A recuperación manual levará tempo... Isto, por dicilo suavemente, é mal. Por outra banda, isto é interesante: na vida real, na práctica, hai situacións nas que se producen ataques internos de xeito natural?

MT: - Dado que raramente atopo violacións de seguridade na vida real, non podo dicir se ocorren. Pero se falamos da filosofía de desenvolvemento, pensamos así: temos un perímetro que proporciona aos mozos que fan seguridade: isto é un castelo, unha muralla; e dentro do perímetro podes facer o que queiras. Está claro que hai usuarios con capacidade de só ver, e hai usuarios con capacidade de borrar o directorio.

Segundo os dereitos, o dano que poden facer os usuarios pode ser un rato ou un elefante. Está claro que un usuario con plenos dereitos pode facer calquera cousa. Un usuario con dereitos limitados pode causar moito menos danos. En particular, non pode romper o sistema.

EN: – No perímetro protexido, alguén intentou crear protocolos inesperados para o servidor co fin de destruír completamente o servidor e, se tes sorte, todo o clúster... ¿Algunha vez consegue iso de “ben”?

MT: "Nunca escoitei falar de tales cousas". O feito de que poida fallar un servidor deste xeito non é ningún segredo. Fallar dentro, ser do protocolo, ser un usuario autorizado que pode escribir algo así na mensaxe... De feito, é imposible, porque aínda así se comprobará. É posible desactivar esta autenticación para os usuarios que non a queiran; entón ese é o seu problema; eles, grosso modo, destruíron os propios muros e podes empuxar un elefante alí dentro, que pisará... Pero, en xeral, podes disfrazarte de reparador, ven tiralo!

EN: - Grazas polo informe. Sergey (Yandex). Hai unha constante en Mong que limita o número de membros votantes no conxunto de réplicas, e esta constante é 7 (sete). Por que isto é unha constante? Por que este non é algún tipo de parámetro?

MT: – Temos réplicas con 40 nodos. Sempre hai maioría. Non sei que versión...

EN: – No conxunto de réplicas podes executar membros sen dereito a voto, pero hai un máximo de membros con dereito a voto 7. Como podemos sobrevivir ao peche neste caso se o noso conxunto de réplicas está repartido en 3 centros de datos? Un centro de datos pódese apagar facilmente e outra máquina pode caer.

MT: – Isto xa está un pouco fóra do alcance do informe. Esta é unha pregunta xeral. Quizais podo falarche máis tarde.

HighLoad++, Mikhail Tyulenev (MongoDB): Consistencia causal: da teoría á práctica

Algúns anuncios 🙂

Grazas por estar connosco. Gústanche os nosos artigos? Queres ver máis contido interesante? Apóyanos facendo un pedido ou recomendando a amigos, Cloud VPS para desenvolvedores desde 4.99 $, un análogo único de servidores de nivel de entrada, que inventamos nós para ti: Toda a verdade sobre VPS (KVM) E5-2697 v3 (6 núcleos) 10 GB DDR4 480 GB SSD 1 Gbps desde 19 dólares ou como compartir un servidor? (dispoñible con RAID1 e RAID10, ata 24 núcleos e ata 40 GB DDR4).

Dell R730xd 2 veces máis barato no centro de datos Equinix Tier IV en Amsterdam? Só aquí 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV desde $199 nos Países Baixos! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - desde $ 99! Ler sobre Como construír a infraestrutura corp. clase co uso de servidores Dell R730xd E5-2650 v4 por valor de 9000 euros por un centavo?

Fonte: www.habr.com

Engadir un comentario