Utilisation de Kafka en tant que magasin d'événements (CQRS). Bonne idée?


219

Bien que j'aie déjà rencontré Kafka auparavant, j'ai récemment réalisé que Kafka peut peut-être être utilisé comme (la base de) un CQRS , événementiel .

L'un des principaux points soutenus par Kafka:

  • Capture / stockage d'événements, tous HA bien sûr.
  • Architecture de pub / sous
  • Possibilité de rejouer le journal des événements, ce qui permet aux nouveaux abonnés de s'enregistrer auprès du système après coup.

Certes, je ne connais pas à 100% le CQRS / Event sourcing mais cela semble assez proche de ce que devrait être un magasin d'événements. Le plus drôle, c'est que je ne trouve vraiment pas grand-chose sur l'utilisation de Kafka comme magasin d'événements, alors peut-être que je manque quelque chose.

Alors, que manque-t-il à Kafka pour que ce soit un bon événement? Cela fonctionnerait-il? Utilisez-vous la production? Intéressé par des informations, des liens, etc.

Fondamentalement, l'état du système est enregistré en fonction des transactions / événements que le système a jamais reçus, au lieu de simplement enregistrer l'état actuel / l'instantané du système, ce qui est généralement le cas. (Considérez-le comme un grand livre de comptabilité: toutes les transactions finissent par atteindre l'état final). Cela permet toutes sortes de choses intéressantes, mais lisez simplement les liens fournis.


Salut Geert-Jan. Rétrospectivement, comment avez-vous traité ce problème? J'ai une question connexe (exposée ici: stackoverflow.com/questions/58763727/… ). La plupart des gens suggérant l'adoption de Kafka semblent s'appuyer sur les points d'imputabilité du journal des ajouts, de débit élevé et de garantie d'ordre de partition. (La garantie de commande à 100% implique l'utilisation d'une seule partition - tuer la concurrence)
tony _008

Je ne l'ai pas poursuivi à la fin parce que j'ai mis fin à ce projet parallèle. Donc, pas de réponse claire, j'ai peur
Geert-Jan

Réponses:


119

Kafka est censé être un système de messagerie qui présente de nombreuses similitudes avec un magasin d'événements, mais pour citer leur introduction:

Le cluster Kafka conserve tous les messages publiés, qu'ils aient été consommés ou non, pendant une période configurable . Par exemple, si la rétention est définie sur deux jours, pendant les deux jours suivant la publication d'un message, il est disponible pour consommation, après quoi il sera rejeté pour libérer de l'espace. Les performances de Kafka sont effectivement constantes en ce qui concerne la taille des données, donc la conservation de nombreuses données n'est pas un problème.

Ainsi, alors que les messages peuvent potentiellement être conservés indéfiniment, on s'attend à ce qu'ils soient supprimés. Cela ne signifie pas que vous ne pouvez pas l'utiliser comme magasin d'événements, mais il peut être préférable d'utiliser autre chose. Jetez un œil à EventStore pour une alternative.

METTRE À JOUR

Documentation Kafka :

Le sourçage d'événements est un style de conception d'application dans lequel les changements d'état sont consignés sous la forme d'une séquence chronologique d'enregistrements. La prise en charge de Kafka pour les très grandes données de journal stockées en fait un excellent backend pour une application construite dans ce style.

MISE À JOUR 2

L'une des préoccupations liées à l'utilisation de Kafka pour la recherche d'événements est le nombre de sujets requis. Généralement, dans le sourcing d'événements, il existe un flux (sujet) d'événements par entité (comme l'utilisateur, le produit, etc.). De cette façon, l'état actuel d'une entité peut être reconstitué en réappliquant tous les événements dans le flux. Chaque rubrique Kafka se compose d'une ou plusieurs partitions et chaque partition est stockée en tant que répertoire sur le système de fichiers. ZooKeeper subira également des pressions à mesure que le nombre de nœuds augmente.


16
Je regardais Kafka et j'avais une autre préoccupation: je n'ai rien remarqué à propos de la concurrence optimiste. Idéalement, je pourrais dire: "Ajoutez cet événement comme élément N + 1 uniquement si l'événement le plus récent de l'objet est toujours N."
Darien

2
@ Darien: Je vais probablement avec une configuration où Redis alimente Kafka (en utilisant les notifications Redis ). Étant donné que Redis permet une concurrence optimiste (en utilisant Watch / multi-exec), cela devrait fonctionner
Geert-Jan

2
@Darien Je ne suis pas un expert en matière de recherche d'événements, mais je croyais qu'en règle générale, vous n'auriez pas besoin d'une concurrence optimiste, car les événements sont par définition des enregistrements de choses qui se sont déjà produites par le passé.
John

4
@John Je pense que si vous avez déjà un ordre faisant autorité d'événements non conflictuels, cela implique que partout où ils vivent est votre technologie réelle de magasin d'événements, et Kafka est simplement utilisé comme système secondaire pour les distribuer.
Darien

1
Vous trouverez également des informations précieuses ici: groups.google.com/forum/#!topic/dddcqrs/rm02iCfffUY
manuc66

283

Je suis l'un des auteurs originaux de Kafka. Kafka fonctionnera très bien comme journal pour la recherche d'événements. Il tolère les pannes, s'adapte à d'énormes tailles de données et possède un modèle de partitionnement intégré.

Nous l'utilisons pour plusieurs cas d'utilisation de ce formulaire sur LinkedIn. Par exemple, notre système de traitement de flux open source, Apache Samza, est livré avec une prise en charge intégrée pour la recherche d'événements.

Je pense que vous n'entendez pas beaucoup parler de l'utilisation de Kafka pour la recherche d'événements principalement parce que la terminologie de la recherche d'événements ne semble pas être très répandue dans l'espace Web grand public où Kafka est le plus populaire.

J'ai écrit un peu sur ce style d'utilisation de Kafka ici .


2
J'allais publier ce lien :) Article de blog génial. Cela aurait été bien de pouvoir le commenter car j'ai beaucoup de questions. @ Geert-Jan jette également un œil à "l'architecture Lambda", c'est assez similaire et le nom est donné par l'auteur de Storm, utilisant principalement une sorte de journal des événements basé sur hadoop dans de nombreux exemples
Sebastien Lorber

6
@Jay: Puisque j'ai renouvelé mon intérêt pour ce sujet, pourriez-vous s'il vous plaît développer un peu le fait que Kafka semble être conçu pour que ses messages publiés expirent après une période de temps définie? Si vous utilisez Kafka comme source d'événements, les messages doivent être stockés indéfiniment. Il est probablement configurable, mais cela poserait-il un problème?
Geert-Jan

2
Y a-t-il des comparaisons entre kafka et eventstore? Plus précisément, j'aime l'accent mis sur FRP dans le magasin d'événements appelé Projections. Y a-t-il quelque chose comme ça à Kafka / Samza?
CMCDragonkai du

4
Je suis également intéressé par la question de @ Geert-Jan à Jay. Kafka n'est pas adapté au côté transactionnel de l'approvisionnement en événements, car il nécessite un flux d'événements (sujet) par agrégat de domaine (pensez à des millions). Cependant, il est idéalement adapté pour recevoir des événements à partir de GetEventStore par exemple. Mais cela ne fonctionnera qu'avec des événements infiniment conservés (dans notre cas), et à part quelques brefs commentaires, cela ne semble pas être un cas d'utilisation pris en charge de Kafka? Je me trompe ici? Samza, par exemple, suppose qu'il n'y a que deux scénarios: la rétention basée sur le temps ou la rétention basée sur les clés. Il y en a d'autres ..
Stephen Drew

3
@eulerfx En supposant que nous aimerions utiliser Kafka comme stockage pour un système source d'événements, comment mettre en œuvre un verrouillage / concurrence optimiste?
Krzysztof Branicki

51

Je reviens toujours à ce QA. Et je n'ai pas trouvé les réponses existantes suffisamment nuancées, alors j'ajoute celle-ci.

TL; DR. Oui ou non, en fonction de l'utilisation de votre source d'événements.

Il y a deux types principaux de systèmes issus d'événements dont je suis au courant.

Processeurs d'événements en aval = Oui

Dans ce type de système, les événements se produisent dans le monde réel et sont enregistrés comme des faits. Comme un système d'entrepôt pour garder une trace des palettes de produits. Il n'y a fondamentalement aucun événement conflictuel. Tout s'est déjà passé, même si c'était faux. (C'est-à-dire que la palette 123456 a été placée sur le camion A, mais était prévue pour le camion B.) Ensuite, les faits sont vérifiés pour les exceptions via des mécanismes de rapport. Kafka semble bien adapté à ce type d'application de traitement d'événements en aval.

Dans ce contexte, il est compréhensible que les gens de Kafka le préconisent en tant que solution de sourçage d'événements. Parce qu'il est assez similaire à la façon dont il est déjà utilisé, par exemple, dans les flux de clics. Cependant, les personnes qui utilisent le terme Event Sourcing (par opposition au Stream Stream) font probablement référence à la deuxième utilisation ...

Source de vérité contrôlée par l'application = Non

Ce type d'application déclare ses propres événements à la suite de demandes d'utilisateurs passant par la logique métier. Kafka ne fonctionne pas bien dans ce cas pour deux raisons principales.

Manque d'isolement d'entité

Ce scénario doit pouvoir charger le flux d'événements pour une entité spécifique. La raison courante en est de créer un modèle d'écriture transitoire pour la logique métier à utiliser pour traiter la demande. Cela n'est pas pratique à Kafka. L'utilisation d'un sujet par entité pourrait permettre cela, sauf qu'il ne s'agit pas d'un démarreur lorsqu'il peut y avoir des milliers ou des millions d'entités. Cela est dû aux limites techniques de Kafka / Zookeeper.

L'une des principales raisons d'utiliser un modèle d'écriture transitoire de cette manière est de rendre les changements de logique métier bon marché et faciles à déployer.

L'utilisation de rubrique par type est recommandée à la place pour Kafka, mais cela nécessiterait de charger des événements pour chaque entité de ce type juste pour obtenir des événements pour une seule entité. Puisque vous ne pouvez pas dire par position de journal quels événements appartiennent à quelle entité. Même en utilisant des instantanés pour démarrer à partir d'une position de journal connue, cela peut représenter un nombre important d'événements à effectuer.

Absence de détection des conflits

Deuxièmement, les utilisateurs peuvent créer des conditions de concurrence critique en raison de demandes simultanées contre la même entité. Il peut être tout à fait indésirable de sauvegarder des événements conflictuels et de les résoudre après coup. Il est donc important de pouvoir prévenir les événements conflictuels. Pour mettre à l'échelle la charge des demandes, il est courant d'utiliser des services sans état tout en évitant les conflits d'écriture à l'aide d'écritures conditionnelles (écriture uniquement si le dernier événement d'entité était #x). Aka Optimistic Concurrency. Kafka ne prend pas en charge la concurrence optimiste. Même s'il la soutenait au niveau du sujet, il faudrait que ce soit jusqu'au niveau de l'entité pour être efficace. Pour utiliser Kafka et éviter les événements conflictuels, vous devez utiliser un rédacteur sérialisé avec état au niveau de l'application. Il s'agit d'une exigence / restriction architecturale importante.

Plus d'informations


Mise à jour par commentaire

Le commentaire a été supprimé, mais la question était quelque chose comme: qu'utilisent les gens pour le stockage des événements alors?

Il semble que la plupart des gens déploient leur propre implémentation de stockage d'événements sur une base de données existante. Pour les scénarios non distribués, comme les back-ends internes ou les produits autonomes, il est bien documenté comment créer un magasin d'événements basé sur SQL. Et il y a des bibliothèques disponibles sur des bases de données de différents types. Il existe également EventStore , qui est conçu à cet effet.

Dans les scénarios distribués, j'ai vu quelques implémentations différentes. Le projet Panther de Jet utilise Azure CosmosDB , avec la fonctionnalité Change Feed pour informer les auditeurs. Une autre implémentation similaire dont j'ai entendu parler sur AWS utilise DynamoDB avec sa fonction Streams pour informer les auditeurs. La clé de partition devrait probablement être l'ID de flux pour la meilleure distribution de données (pour réduire la quantité de surprovisionnement). Cependant, une relecture complète à travers les flux dans Dynamo coûte cher (lecture et coût). Cet implément a donc également été configuré pour Dynamo Streams pour vider les événements vers S3. Lorsqu'un nouvel auditeur arrive en ligne, ou qu'un auditeur existant veut une relecture complète, il lit S3 pour rattraper son retard en premier.

Mon projet actuel est un scénario multi-locataire, et j'ai roulé le mien sur Postgres. Quelque chose comme Citus semble approprié pour l'évolutivité, le partitionnement par stream + tentant.

Kafka est toujours très utile dans les scénarios distribués. C'est un problème non trivial d'exposer les événements de chaque service à d'autres services. Un magasin d'événements n'est généralement pas construit pour cela, mais c'est précisément ce que Kafka fait bien. Chaque service a sa propre source de vérité interne (peut être le stockage d'événements ou autre), mais écoute Kafka pour savoir ce qui se passe "à l'extérieur". Le service peut également publier des événements à Kafka pour informer "l'extérieur" des choses intéressantes que le service a faites.


1
@Dominik J'ai mentionné EventStore dans la section Mise à jour (2ème paragraphe). Je vais revenir en arrière et le lier. Je l'ai essayé et il a des performances impressionnantes. Pour notre petite équipe, ne pas introduire une autre base de données a été jugé plus important pour le moment, d'où Postgres (qui est également utilisé pour les vues). Il est possible que nous passions à EventStore dans le futur ou dans de futurs produits.
Kasey Speakman

2
@KaseySpeakman Les sujets ne sont pas les mêmes que les partitions. Un sujet a une ou plusieurs partitions. Les partitions sont garanties d'avoir un seul consommateur par groupe à un moment donné. Cloisonnez vos entités de manière à en profiter. Vous n'avez pas besoin d'un sujet par entité ou même d'une partition par entité. Il vous suffit de les partitionner de manière à garantir que toutes les commandes adressées à la même entité vont sur la même partition.
Andrew Larsson

1
@KaseySpeakman De nombreuses entités peuvent partager une seule partition. Qui a dit que vous devez toujours charger l'état de l'entité directement à partir du magasin d'événements en rejouant les événements? Il existe d'autres façons de réaliser le même concept sans suivre strictement l'implémentation de Greg Young ligne par ligne.
Andrew Larsson

1
@AndrewLarsson Si vous ne partitionnez pas par entité, comment allez-vous empêcher les événements conflictuels au niveau de l'entité? Puisque nous avons bouclé la boucle sur les conflits de concurrence, alors vous devriez peut-être publier votre propre article sur un support ou quelque chose sur la façon dont vous avez utilisé Kafka pour la recherche d'événements (et non le traitement de flux) en production. Comment vous l'accomplissez avec une partition par type et sans contrôle de concurrence au niveau de l'entité. Je le lirais et je ne vous tromperais même pas dans les commentaires si je n'étais pas d'accord.
Kasey Speakman

2
@KaseySpeakman L'utilisation de Kafka de cette façon n'est en aucun cas facile. Mais si vous êtes à l'échelle où vous avez sérieusement envisagé CQRS et Event Sourcing, vous êtes à l'échelle où vous ne pouvez pas vous permettre de faire les choses facilement. Votre modèle de concurrence a un impact direct sur votre échelle - n'en choisissez pas arbitrairement. De plus, HTTP n'est pas un moyen de transport fiable, et encore une fois, si vous êtes à cette échelle, vous ne pouvez pas vous permettre de passer du temps à résoudre les problèmes de messages perdus et / ou en double. Tout cela peut être résolu en utilisant Kafka entre le client et le processeur de commande, mais oui, cela se fait au détriment de la complexité.
Andrew Larsson

20

Vous pouvez utiliser Kafka comme magasin d'événements, mais je ne le recommande pas, même si cela peut sembler un bon choix:

  • Kafka ne garantit qu'au moins une fois la livraison et il y a des doublons dans le magasin d'événements qui ne peuvent pas être supprimés. Mise à jour: ici, vous pouvez lire pourquoi il est si difficile avec Kafka et quelques dernières nouvelles sur la façon de finalement parvenir à ce comportement: https://www.confluent.io/blog/exactly-once-semantics-are-possible-heres-how -apache-kafka-le-fait /
  • En raison de l'immuabilité, il n'y a aucun moyen de manipuler le magasin d'événements lorsque l'application évolue et que les événements doivent être transformés (il existe bien sûr des méthodes comme l'upcasting, mais ...). Une fois pourrait dire que vous n'avez jamais besoin de transformer les événements, mais ce n'est pas une hypothèse correcte, il peut y avoir une situation où vous effectuez une sauvegarde de l'original, mais vous les mettez à niveau vers les dernières versions. C'est une exigence valable dans les architectures événementielles.
  • Aucun endroit pour conserver les instantanés des entités / agrégats et la relecture deviendra de plus en plus lente. La création d'instantanés est une fonctionnalité indispensable pour le magasin d'événements dans une perspective à long terme.
  • Étant donné que les partitions Kafka sont distribuées et qu'elles sont difficiles à gérer et à comparer avec les bases de données. Les bases de données sont tout simplement plus simples :-)

Donc, avant de faire votre choix, vous réfléchissez à deux fois. Le magasin d'événements en tant que combinaison d'interfaces de couche application (surveillance et gestion), le magasin SQL / NoSQL et Kafka en tant que courtier est un meilleur choix que de laisser Kafka gérer les deux rôles pour créer une solution complète et complète.

Le magasin d'événements est un service complexe qui nécessite plus que ce que Kafka peut offrir si vous souhaitez sérieusement appliquer le sourcing d'événements, le CQRS, les Sagas et d'autres modèles dans une architecture événementielle et rester performant.

N'hésitez pas à contester ma réponse! Vous n'aimez peut-être pas ce que je dis à propos de votre courtier préféré avec de nombreuses capacités qui se chevauchent, mais Kafka n'a pas été conçu comme un magasin d'événements, mais plutôt comme un courtier haute performance et un tampon en même temps pour gérer les scénarios de producteurs rapides contre les consommateurs lents, par exemple.

Veuillez consulter le framework open source eventuate.io microservices pour en savoir plus sur les problèmes potentiels: http://eventuate.io/

Mise à jour au 8 février 2018

Je n'intègre pas les nouvelles informations des commentaires, mais je suis d'accord sur certains de ces aspects. Cette mise à jour concerne davantage certaines recommandations pour la plate-forme événementielle de microservice. Si vous êtes sérieux au sujet de la conception robuste des microservices et des meilleures performances possibles en général, je vous fournirai quelques conseils qui pourraient vous intéresser.

  1. N'utilisez pas Spring - c'est génial (je l'utilise beaucoup moi-même), mais c'est lourd et lent en même temps. Et ce n'est pas du tout une plateforme de microservices. C'est "juste" un framework pour vous aider à en implémenter un (beaucoup de travail derrière ça ..). Les autres frameworks sont "juste" légers REST ou JPA ou des frameworks à focalisation différente. Je recommande probablement la meilleure plateforme de microservices open source complète disponible qui revient aux racines Java pures: https://github.com/networknt

Si vous vous interrogez sur les performances, vous pouvez vous comparer à la suite de benchmark existante. https://github.com/networknt/microservices-framework-benchmark

  1. N'utilisez pas du tout Kafka :-)) C'est à moitié blague. Je veux dire que même si Kafka est génial, c'est un autre système centré sur les courtiers. Je pense que l'avenir est dans les systèmes de messagerie sans courtier. Vous pourriez être surpris, mais il existe des systèmes plus rapides que Kafka :-), bien sûr, vous devez descendre à un niveau inférieur. Regardez Chronicle.

  2. Pour le magasin d'événements, je recommande une extension Postgresql supérieure appelée TimescaleDB, qui se concentre sur le traitement de données de série temporelle hautes performances (les événements sont des séries temporelles) en grand volume. Bien sûr, CQRS, Event sourcing (replay, etc.) sont intégrés dans le framework light4j prêt à l'emploi qui utilise Postgres comme stockage faible.

  3. Pour la messagerie, essayez de regarder Chronicle Queue, Map, Engine, Network. Je veux dire, débarrassez-vous de ces solutions centrées sur le courtier à l'ancienne et optez pour un système de micro-messagerie (intégré). Chronicle Queue est en fait encore plus rapide que Kafka. Mais je suis d'accord, ce n'est pas tout dans une seule solution et vous devez faire un peu de développement sinon vous allez acheter la version Enterprise (payante). En fin de compte, l'effort de construire à partir de Chronicle votre propre couche de messagerie sera payé en supprimant la charge de la maintenance du cluster Kafka.


Vue intéressante. Vous souhaitez développer quelques points? > Kafka ne garantit qu'au moins une fois la livraison et il y a des doublons dans le magasin d'événements qui ne peuvent pas être supprimés. Vous semblez impliquer qu'il existe une chose telle qu'exactement une fois la livraison. afaik (et j'en suis presque sûr), il n'y a rien de tel dans un système distribué. 2) Quant à votre point 2: l'école classique de la pensée (sourcing d'événements / jjj) est que les événements sont intrinsèquement immuables. C'est à dire: ils sont arrivés, aucun moyen de changer le passé. Quelle est l'utilité réelle de les changer rétrospectivement? Merci!
Geert-Jan

1.) Hazelcast pour garantir que chaque message sera traité une seule fois. 2.) Je n'aime rien comme _V2 dans le code de service, donc soit vous sauvegardez pour archiver et recréez les anciens événements vers leurs nouvelles versions (vous avez toujours la vérité d'origine), soit vous pouvez cacher / construire cette fonctionnalité directement dans Event Stockez la fonctionnalité d'instantané, il n'y a donc qu'un seul point de conversion ascendante -> le magasin d'événements. Quelles sont vos solutions à cela?
kensai

1) au moins une fois + idempotence sur le consommateur. C'est-à-dire: vérifiez si l'événement a déjà été vu. Si c'est le cas, sautez. Ou mieux encore, ayez des actions idempotentes. Bien sûr, ce n'est pas toujours possible. 2) Je n'ai jamais rencontré de besoin de versionner des événements. Je traite toujours les événements eux-mêmes comme la source de vérité et j'inclus toutes les informations dont j'aurais besoin sur eux. Ce faisant, je n'ai jamais rencontré de situation où j'avais besoin d'une structure d'événements et / ou de données différentes sur un événement. Mais peut-être ymmv. Intéressé à entendre dans quelles situations vous auriez réellement besoin d'avoir des événements mis à jour.
Geert-Jan

1.) peut être un moyen de choix .. 2.) alors vos structures de données étaient parfaites depuis le début :-) vous chanceux, haha. Je n'en ai peut-être pas besoin sur mon projet actuel, mais je construis toute une plate-forme sur des fourches de eventuate.io fusionné avec des approches JEE hautes performances uniquement prises à partir de light eventuate 4j ... toute cette discussion n'est pas un lieu de commentaires sur stackoverflow , mais si vous êtes intéressé à plonger plus profondément, je recommande cet article: leanpub.com/esversioning/read
kensai

1
Soit dit en passant, Kafka ne prend en charge qu'une seule livraison. Mise à jour bullet 1
OneCricketeer

8

Oui, vous pouvez utiliser Kafka comme magasin d'événements. Cela fonctionne assez bien, en particulier avec l'introduction de Kafka Streams , qui fournit un moyen natif de Kafka pour traiter vos événements dans un état accumulé que vous pouvez interroger .

En ce qui concerne:

Possibilité de rejouer le journal des événements, ce qui permet aux nouveaux abonnés de s'enregistrer auprès du système après coup.

Cela peut être délicat. J'ai couvert cela en détail ici: https://stackoverflow.com/a/48482974/741970


0

Oui, Kafka fonctionne bien dans le modèle de sourcing d'événements spécialement CQRS, cependant vous devez faire attention lors de la définition des TTL pour les sujets et gardez toujours à l'esprit que Kafka n'a pas été conçu pour ce modèle, mais nous pouvons très bien l'utiliser.


0

Je pense que vous devriez regarder le framework axone avec leur support pour Kafka

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.