首页 存档 技术 查看内容

分享一下我和MongoDB与Redis那些事 [原] 分享一下我和 MongoDB 与 Redis 那些事

2018-3-30 13:00 |来自: 互联网 332 0

摘要: 分享一下我和 MongoDB 与 Redis 那些事 缘起:来自于我在近期一个项目上遇到的问题,在 Segmentfault 上发表了提问 知识背景: 对不是很熟悉 MongoDB 和 Redis 的同学做一下介绍。 MongoDB 数组查询:Mongo ...

[原] 分享一下我和 MongoDB 与 Redis 那些事




缘起:来自于我在近期一个项目上遇到的问题,在 Segmentfault 上发表了提问




知识背景:


对不是很熟悉 MongoDB 和 Redis 的同学做一下介绍。

  1. MongoDB 数组查询:MongoDB 自带 List, 可以存放类似这样的结构 List = [1, 2, 3, 4, 5, 6, 7, 8, 9].

    如果我们有一个 l = [2, 3, 8], 则可以进行这样的查询:spce ={'List' : {'$in' : l}, 这里 spce 就是一个查询条件,代表 l 是 List 的一个子集。

  2. Redis 队列: Redis 提供基本的 List(普通链表),set(集合),Zset(有序集合) 类型的结构,将 List 的 lpush, rpop 操作运用起来,可以做一个普通的队列,运用 Zset 可以做一个带权值的最小堆排序的队列 (可以看做优先级)。


整体架构如下图所示:


生产者产生任务,通过 LVS 与 RPC 服务器将任务记录到 MongoDB,消费者同样通过 RPC 服务获取任务,这是个很简单的架构,一般服务可能去掉集群都是这样的。


整个业务架构需要一个前提,任务不能丢失,也就是说任务即使失败也需要重新加入到队列,至少若干次后任然失败也要知道为什么失败 (非记录日志形式)。


很多人问为什么不直接用 RabbitMQ 或者 Redis,因为这类消息队列无法做到管理任务超时等情况,因为业务需要,也需要做一些简单的查询,这类队列是不支持某些稍复杂的查询的,而且一开始我们的任务量估计在 5KW/Day 这样,担心 Redis 扛不住,后来我发现这是个错误的假设。





问题内容如下:


问题背景: 近期在重构公司内部一个重要的任务系统,由于原来的任务系统使用了 MongoDB 来保存任务,客户端从 MongoDB 来取,至于为什么用 MongoDB,是一个历史问题,也是因为如果使用到MongoDB 的数组查询可以减少任务数量很多次,假设这样的情况,一个 md5(看做一条记录的唯一标识) 需要针对 N 种情况做任务处理,如果用到 MongoDB 的数组,只需要将一个 md5 作为一条任务,其中包含一个长度为 N 的待处理任务列表,可以使用到 MongoDB 的数组 (只有 N 个子任务都处理完后整个任务才算处理完毕),这样整个任务系统的数量级就变为原来的 1/N(如果需要用到普通的关系型数据库,可能需要创建 m*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 的性能会由于锁表操作急剧下降 (锁表时间可以达到 60%-70%,熟悉 MongoDB 的人都知道这是多么恐怖的数字)。


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




提出这个问题后,很感谢官方将问题发到微博首页,有一个回答我觉得可以采纳:

1

本文转载自:微信公众账号 - SOHU-DBA,版权归原作者所有!

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。
转载请注明:文章转载自 [http://www.php230.com]
本文标题:分享一下我和MongoDB与Redis那些事
IT技术书籍推荐:
算法导论(原书第3版)
Thomas H.Cormen (作者), Charles E.Leiserson (作者), Ronald L.Rivest (作者), Clifford Stein (作者), 殷建平 (译者), 徐云 (译者), 王刚 (译者), 等 (译者)
《算法导论(原书第3版)》内容简介:在有关算法的书中,有一些叙述非常严谨,但不够全面;另一些涉及了大量的题材,但又缺乏严谨性。《算法导论(原书第3版)》将严谨性和全面性融为一体,深入讨论各类算法,并着力使这些算法的设计和分析能为各个层次的读者接受。全书各章自成体系,可以作为独立的学习单元;算法以英语和伪代码的形式描述,具备初步程序设计经验的人就能看懂;说明和解释力求浅显易懂,不失深度和数学严谨性。全书选材经典、内容丰富、结构合理、逻辑清晰,对本科生的数据结构课程和研究生的算法课程都是非常实用的教材,在IT专业人员的职业生涯中,《算法导论(原书第3版)》也是一本案头必备的参考书或工程实践手册。

路过

雷人

握手

鲜花

鸡蛋

相关分类