问题背景: 近期在重构公司内部一个重要的任务系统,由于原来的任务系统使用了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的?
Après quelques réflexions préliminaires, à titre indicatif :
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 :
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.
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.