0
votes

Comment traiter des messages dans le même ordre de la file d'attente en utilisant plusieurs serveurs en Java

Nous avons une file d'attente ActiveMQ qui recevra 100 000 messages de commande de stock (chaque message contient le nom de stock, le prix de vente, le prix de la soumission au format JSON) par seconde. Sur des messages 100K / SEC, il peut y avoir n. N ° de messages de stock unique. Si nous recevons plusieurs messages de même stock, nous devons traiter tous ces messages dans le même ordre en utilisant Java. Nous ne pouvons pas traiter les messages 100k / seconde à l'aide d'un seul auditeur sur un serveur. Besoin de le traiter en utilisant plusieurs auditeurs et serveurs, mais affichez le résultat dans l'interface utilisateur en utilisant le même ordre placé dans la file d'attente.

Lire la file d'attente de stock -> Valider la demande -> Mettre à jour le cours d'actions en UI

exemple de message: - { StockName: "TCS", SellPrix: "102", BIDPRICE: "100" }

Pouvez-vous suggérer une solution pour le problème ci-dessus.


2 commentaires

Le but total de la multi-threading est d'activer Concurrence (c'est-à-dire la capacité de faire des choses dans aucun ordre particulier.) Donc, si vous voulez que certaines choses soient faites dans un certain ordre, le meilleur moyen est de s'assurer qu'ils sont tous faits dans le même fil. La réponse de SharonBenasher est la clé: avoir une file d'attente pour chaque "auditeur" et utilise hachage pour vous assurer que toutes les transactions impliquant le même stock sont envoyées à la même file d'attente.


Oui Salomon lent, mais l'exigence est de traiter le message dans le même ordre. User1 a placé TCS enchère pour 101, User2 a placé la soumission de stock TCS pour 102. Ensuite, dans UI, nous devrions voir 102 pour TCS. Nous recevrons aussi un message / s par stock 10k par stock.


3 Réponses :


1
votes

Voici ma proposition:
Vous devez diviser la file d'attente en sous-files en fonction du nom du stock. Vous pouvez vous diviser en fonction de la première lettre du nom du stock. Cela vous donnera de nombreuses capacités parallèles tout en garantissant que tous les messages du même stock sur une file d'attente. Il aura besoin d'un lecteur de la file d'attente principale, mais tout ce qui est fait transmettre les messages aux sous-files.


2 commentaires

Merci pour votre suggestion. Cela nécessitera 26 files d'attente (A à Z). FYI Nous avons environ 4K stocks. De plus, nous devons ajouter ces nombreux auditeurs / instances bien que peu de stocks auront un volume très élevé (finir par une utilisation élevée de ces auditeurs) et peu de stocks auront moins de messages. Nous pourrions nous retrouver dans moins d'utilisation de ces auditeurs. Par exemple, si nous obtenons des messages / sections de 10k en ce qui concerne la queue commençant par la lettre A, il peut ne pas être possible de traiter tous ces messages utilisant un seul auditeur avec en 1 seconde.


Nous ajoutions également un lecteur de plus à lire de la file d'attente principale et la transmettez-la à la sous-traitance. (Lisez le message, vérifiez le nom du stock, transmettre à une autre file d'attente) Cela ajoutera du temps de traitement supplémentaire. Cela devrait également être fait en utilisant un seul auditeur pour maintenir la commande. Comme nous manipulons 100 000 messages / s, cela serait difficile de traiter tous ces messages avec un seul auditeur.



0
votes

Je suggérerais d'utiliser une publication non persistante aux sujets au lieu des files d'attente. Les sujets vous donnent la flexibilité de

  1. Choisir des caractères génériques d'abonnement et
  2. éventuellement ajouter d'autres services plus tard à cette architecture. Vous n'aurez peut-être pas besoin de cela maintenant, mais peut-être dans 5 ans, vous aurez besoin d'une autre interface graphique ou d'un service de surveillance ou de replay. Si vous avez utilisé des sujets, vous pouvez simplement pliger de nouveaux abonnés - vous n'avez pas à modifier votre côté de la publication pour ceux qui ...

    Vous pouvez utiliser des abonnements durables si vous avez besoin de plus de persistance.

    La commande de message est garantie dans le même sujet de publication, vous devez donc faire une partie du nom du sujet du sujet. Vous pouvez publier sur quelque chose comme ordct.stock.tcs.

    Mais avoir une charge équilibrée basée sur des noms de stock est délicate car certaines lettres comme Z sont très rares, tandis que d'autres sont fréquents. Ainsi, en plus du nom du stock, ajoutez le hachage de nom de la bourse 100 au sujet. Par exemple, si le hashcode de TCS est 12357 et que vous faites MODULO 100, vous publiez ceci sur commande.stock.tcs.57

    Disons que vous avez 10 abonnés, chaque abonné pourrait alors faire 10 abonnements. Par exemple, l'abonné 1 s'abonnerait à commander.stock. *. 0, commander.stock. *. 1, ... ordre.stock. *. 9

    L'abonné 2 s'abonnerait à commander.stock. *. 10, commander.stock. *. 11, ... ordre.stock. *. 19

    Si vous avez 5 abonnés, chacun fait 20 abonnements (vous obtenez l'idée). La raison en est que


4 commentaires

Merci pour votre suggestion. L'approche ci-dessus créera des sujets de 400k lorsque nous avons des stocks de 4k. Lorsque nous utilisons le nom de stock Hash% 100 Comment assurer l'ordre des messages. Il ne devrait également y avoir que l'auditeur chaque sujet, sinon chaque auditeur aura le même message (puisqu'il s'agit de sujet).


Non - Pour un stock, comme MSFT, vous publiez uniquement sur un sujet: order.stock.msft.31, par exemple. Ce sera des sujets de 4k pour les stocks 4K. L'astuce est que vous avez environ 4000/100 = 40 stocks se terminant dans '31' de sorte qu'un abonné écoute sur . . *. 31 obtiendront ces 40 stocks. Tous les messages dans la commande originale.


Tous les stocks de MSFT iront à commande.stock.msft.31 correct. Comme c'est sujet, nous pouvons ajouter plusieurs auditeurs / abonnés à augmenter la vitesse de traitement. Si oui comment assurer la commande. À la fin, nous devons afficher le même ordre entrant dans UI.


N'ajoutez pas plusieurs auditeurs par sujet. Juste un. Et pour celui-ci, l'ordre est assuré. Mais vous pouvez également utiliser des files d'attente si vous le souhaitez: l'idée de première commande est d'utiliser la première lettre dans le cadre du nom de la file d'attente: Stock.m, Stock.n ,. - et votre premier consommateur de file d'attente recevrait des messages de files d'attente AG, par example. Votre deuxième consommateur de la queue H-m. Mais comment vous distribuer de la charge uniformément? Certaines lettres ont beaucoup plus de trafic que d'autres .. Donc, la meilleure variation de ceci est d'utiliser le hachage du nom de stock dans le nom de la file d'attente. First Consumer Processes Stock.0-10 Par exemple.



0
votes

Nous avons eu une exigence similaire et nous avons utilisé un cadre open source appelé Lmax perturbatrice, un cadre de concurrence supposément performant. Vous pouvez expérimenter autour de cela, https://github.com/lmax-exchange/ perturbateur / wiki / obtention du démarrage .

à très haut niveau:

  1. Mettez les stocks reçus dans un Ringbuffer [Structure de données de base qui Le cadre repose sur], ce serait le consommateur pour Activemq et producteur pour la Ringbuffer.

  2. Les consommateurs / travailleurs [dans votre cas multiple - Mulltiple Voici un Fil travailleur pour chaque nom-store unique] Prenez les stocks de Ringbuffer en mode commandité. Dans le travailleur / auditeur, vous pouvez manipuler l'événement basé sur la condition.

    Je viens de vous engager un code d'échantillon en essayant de démontrer votre cas d'utilisation, pour votre référence: https://github.com/reddy73/disrupturier-example


2 commentaires

Merci pour le code d'échantillon, je l'ai vérifié. Comment l'échelle d'utilisation à l'aide de plusieurs serveurs. Cela fonctionnera-t-il lorsque nous utilisons plus d'un serveur.


Lorsque j'utilise 4 travailleurs et 4 Ringbuffersize, l'ordre est manquant (2,4,8 & 6 au lieu de 2,4,6 et 8). Est-ce toujours 2 travailleurs et 2 Ringbuffersize? Travailleur [2] consommé [1] stock où stock [ID: 2, StockName: TCS. Ouvrier [3] consommé [1] Stock où Stock [Id: 4, StockName: TCS. Travailleur [2] consommé [2] stock où stock [ID: 8, StockName: TCS. Travailleur [1] consommé [1] Stock où Stock [ID: 6, StockName: TCS.