찾다

 >  Q&A  >  본문

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的?

迷茫迷茫2766일 전757

모든 응답(3)나는 대답할 것이다

  • 迷茫

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

    잠깐 생각한 후 참고용으로만 사용하세요.

    1. 우선 색인에 대해 언급하겠습니다. 이에 대한 색인을 추가해야 한다고 생각합니다.
    2. 최신 버전의 mongodb의 잠금 세분성은 아직 데이터베이스 수준에 있습니다. 아직 잠금 테이블(컬렉션)의 세분성에 도달하지 않았습니다. ), 그래서 쓰기 동시성이 크면 더 나빠지는데, 설명하신 것만큼 성능이 나빠서는 안 되겠죠? 이해가 안 돼요. 작업 하위 라이브러리의 가능성을 고려해 보시는 게 어떨까요?
    3. 하위 작업 상태와 주요 작업 상태를 별도로 저장하는 것을 고려할 수 있나요? 하위 작업의 상태는 Redis에 배치될 수 있으며 기본 작업은 자신의 상태만 담당합니다. 이러한 방식으로 각 기본 작업의 업데이트 빈도가 1/N으로 줄어들어 기본 작업에 대한 부담을 크게 줄일 수 있습니다. mongodb의 테이블.
    4. 하위 작업이 완료되거나 시간 초과된 후 mongodb의 기본 작업 상태에 대한 백그라운드 비동기 단일 스레드 순차 동기화를 고려할 수 있나요?

    회신하다
    0
  • 阿神

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

    개인적으로 질문자가 언급한 MongoDB 배열 쿼리 및 업데이트의 성능 문제는 스키마 설계 문제일 가능성이 높다고 생각합니다. 하지만 질문자는 구체적인 디자인을 제시하지 않았으므로 참고용으로 주목할 만한 몇 가지 사항을 제시하겠습니다.

    1. 인덱스는 위에서 언급했듯이 배열을 인덱싱했어야 합니다. 그러나 배열 필드의 인덱스가 일반 필드의 인덱스보다 훨씬 크다는 점은 주목할 가치가 있습니다(배열의 크기에 따라 배열이 클수록 인덱스가 차지하는 공간도 커집니다). 이로 인해 문제가 발생할 수 있습니다. 인덱스가 (완전히) 메모리에 없습니다! 결과적으로 각 쿼리에는 추가 IO 작업이 필요하고 성능이 급격히 저하됩니다.
    2. 쿼리는 문서의 크기를 반환합니다. 각 쿼리에 대해 반환되는 문서 데이터의 양이 크고 클라이언트와 mongodb가 동일한 시스템에 있지 않으면 네트워크 전송에 필요한 시간이 늘어나므로(이 시간을 과소평가하지 마십시오) 필요한 모든 데이터만 반환하도록 하십시오. 전지.
    3. update-in-place. 스키마 없는 기능으로 인해 mongodb는 업데이트 성능을 향상하기 위해 추가 필드나 데이터를 추가할 때 사용할 각 문서 레코드에 대해 일부 공간을 예약합니다. 그러나 문서 크기가 자주 확장되면(필드 추가, 배열 길이 증가 등) 쓰기 성능 문제가 발생합니다. MongoDB는 늘어나는 문서를 다른 위치로 옮겨야 합니다. (하드디스크의 한 위치에서 여유 공간이 더 많은 다른 위치로 이동하는 것과 같습니다.) 이때 성능은 크게 저하됩니다.

    Mongodb는 메모리 내 데이터베이스입니다. 모든 핫스팟 데이터가 메모리에 있으면 성능이 매우 뛰어나며 이는 주로 스키마 설계에 따라 달라집니다.

    PS: mongodb가 항상 선전했던 Schemaless의 장점은 많은 사람들을 오해했습니다. 사실 이는 mongodb가 스키마를 설계할 필요가 없다는 점을 보여주기 위한 것입니다.

    회신하다
    0
  • 大家讲道理

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

    작업 대기열에 Rabbitmq를 고려해 볼 수도 있습니다. 또한 mongodb는 너무 느려서는 안 됩니다. 그렇죠? 아니면 제한 컬렉션을 사용해 보세요.

    회신하다
    0
  • 취소회신하다