recherche

Maison  >  Questions et réponses  >  le corps du texte

MongoDB + Redis 任务队列性能瓶颈

问题背景: 近期在重构公司内部一个重要的任务系统,由于原来的任务系统使用了MongoDB来保存任务,客户端从MongoDB来取,至于为什么用MongoDB,是一个历史问题,也是因为如果使用到MongoDB的数组查询可以减少任务数量很多次,假设这样的情况,一个md5需要针对N种情况做任务处理,如果用到MongoDB的数组,只需要将一个md5作为一条任务,其中包含一个长度为N的待处理任务列表(只有N个子任务都处理完后整个任务才算处理完毕),这样整个任务系统的数量级就变为原来的 1/N。

细节描述: 1.当MongoDB的任务数量增多的时候,数组查询相当的慢,任务数达到5K就已经不能容忍了。 2.任务处理每个md5对应的N个子任务必须要全部完成才从MongoDB中删除 3.任务在超时后可以重置

改进方案如下: 由于原有代码的耦合,不能完全抛弃MongoDB,所以决定加一个Redis缓存。一个md5对应的N个子任务分发到N个Redis队列中(拆分子任务)。一个单独的进程从MongoDB中向Redis中将任务同步,客户端不再从MongoDB取任务。这样做的好处是抛弃了原有的MongoDB的数组查询,同步进程从MongoDB中取任务是按照任务的优先级偏移(已做索引)来取,所以速度比数组查询要快。这样客户端向Redis的N个队列中取子任务,把任务结果返回原来的MongoDB任务记录中(根据md5返回子任务)。

改进过程遇到的问题: 由于客户端向MongoDB返回时候会有一个update操作,如果N个子任务都完成,就将任务从MongoDB中删除。这样的一个问题就是,经过测试后发现MongoDB在高并发写的情况下性能很低下,整个任务系统任务处理速度最大为200/s(16核, 16G, CentOS, 内核2.6.32-358.6.3.el6.x86_64),原因大致为在频繁写情况下,MongoDB的性能会由于锁表操作急剧下降。

具体问题: (Think out of the Box)能否提出一个好的解决方案,能够保存任务状态(子任务状态),速度至少超过MongoDB的?

迷茫迷茫2799 Il y a quelques jours784

répondre à tous(3)je répondrai

  • 迷茫

    迷茫2017-04-22 08:58:16

    Après quelques réflexions préliminaires, à titre indicatif :

    1. Tout d’abord, mentionnons l’index. Je pense que vous devriez y ajouter un index.
    2. J'ai une question à confirmer. La granularité du verrouillage dans la dernière version de mongodb est toujours au niveau de la base de données. Je ne sais pas quelle version vous utilisez. Elle n'a pas encore atteint la granularité de la table de verrouillage (Collection). ), donc c'est pire lorsque la concurrence d'écriture est importante. Mais les performances ne devraient pas être aussi mauvaises que vous l'avez décrit ? Je ne comprends pas. Je vous suggère d'envisager la possibilité d'une sous-bibliothèque de tâches ?
    3. Pouvez-vous envisager de sauvegarder séparément le statut des sous-tâches et le statut des tâches principales ? Le statut des sous-tâches peut être placé dans Redis, et la tâche principale n'est responsable que de son propre statut, de cette manière, la fréquence de mise à jour de chaque tâche principale est réduite à 1/N, ce qui peut réduire considérablement la pression sur la tâche principale. table en mongodb.
    4. Une fois la sous-tâche terminée ou expirée, la synchronisation séquentielle asynchrone monothread en arrière-plan de l'état de la tâche principale de mongodb peut-elle être prise en compte ?

    répondre
    0
  • 阿神

    阿神2017-04-22 08:58:16

    Personnellement, je pense que les problèmes de performances de la requête et de la mise à jour du tableau MongoDB mentionnés par l'interrogateur sont susceptibles d'être des problèmes liés à la conception du schéma. Mais l'interlocuteur n'a pas donné de design précis, je vais donc avancer quelques points dignes d'attention à titre de référence uniquement :

    1. Index, comme mentionné ci-dessus, vous auriez dû indexer le tableau. Cependant, il convient de noter que l'index d'un champ de tableau est beaucoup plus grand que l'index d'un champ ordinaire (selon la taille du tableau, plus le tableau est grand, plus l'espace occupé par l'index est grand). Cela peut poser un problème : l'index n'est pas (complètement) en mémoire ! La conséquence est que chaque requête nécessite des opérations d'E/S supplémentaires et les performances chuteront fortement.
    2. La requête renvoie la taille du document. Si la quantité de données de document renvoyée pour chaque requête est importante et que le client et mongodb ne sont pas sur la même machine, cela augmentera le temps requis pour la transmission réseau (ne sous-estimez pas ce temps), alors essayez de renvoyer uniquement toutes les données requises. champs.
    3. mise à jour sur place. En raison de la fonctionnalité sans schéma, mongodb réservera un espace pour chaque enregistrement de document à utiliser lors de l'ajout de champs ou de données supplémentaires afin d'améliorer les performances de mise à jour. Mais si la taille de votre document augmente fréquemment (ajout de champs, augmentation de la longueur du tableau, etc.), cela entraînera des problèmes de performances d'écriture : MongoDB doit déplacer le document en croissance vers un autre endroit. (Équivaut à passer d'un emplacement du disque dur à un autre emplacement plus libre) Les performances à ce moment seront considérablement réduites.

    Mongodb est une base de données en mémoire si toutes vos données de hotspot sont en mémoire, ses performances seront très excellentes, et cela dépend en grande partie de la conception de votre schéma.

    PS : Les avantages de Schemaless que mongodb a toujours vantés ont induit de nombreuses personnes en erreur. En fait, il s'agit davantage de montrer que mongodb est un schéma dynamique, plutôt que de concevoir un schéma.

    répondre
    0
  • 大家讲道理

    大家讲道理2017-04-22 08:58:16

    La file d'attente des tâches peut prendre en compte RabbitMQ. De plus, mongodb ne devrait pas être si lent, n'est-ce pas ? Ou essayez la collecte plafonnée.

    répondre
    0
  • Annulerrépondre