BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

Nextdoor分布式任务队列系统的演进

| 作者 马德奎 关注 0 他的粉丝 发布于 2014年8月22日. 估计阅读时间: 6 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

近日,私密社交网络Nextdoor在其官方博客发表了一篇文章,介绍其分布式任务队列系统的演进过程。该系统每天要处理数以百万计的异步任务,包括向数以百万计的邻居发送内容通知、创建搜索索引、以及其它应该从交互式Web和移动应用程序解耦的耗时的处理过程。它由两部分组成:消息代理(队列)和一组任务工作进程。像其它许多系统一样,他们使用RabbitMQ作为消息代理,使用Celery作为任务工作进程。在公司规模较小的时候,这些开源项目提供了很大的帮助。但随着用户数的增多,不久前,他们在Celery的稳定性方面遇到了问题。即使得到了Celery创建者Ask Solem本人的支持,但他们仍然会遇到一些问题。最终,他们决定用他们自己开发的项目Taskworker替换Celery。同时,为了减少运维开销,他们用Amazon SQS替换了RabbitMQ。他们的理由是,Amazon SQS容易理解,具有高可扩展性,而且完全由Amazon管理。

文章首先列出了他们在使用Celery时面临的三个主要问题:

  1. Celery工作进程在他们系统的现有规模下不稳定。工作进程经常莫名其妙地宕掉,而且由于其代码库很复杂,很难进行故障排除。
  2. Celery工作进程无法有效利用系统的计算资源。由于Celery不支持优先级队列,所以许多工作进程节点要么未充分利用,要么出现了过载。
  3. Celery工作进程处理任务的延时经常非常高。

由于上述问题的存在,他们为Taskworker设定了三个目标:

  1. 简单:故障排除要简单。
  2. 高效:计算资源的利用要尽可能的高效。
  3. 可扩展:系统应该是完全分布式的,并可横向扩展。

文章接下来详细介绍了Taskworker设计及应用到生产环境过程中的一些关键点。

设计决策

基于上述三个目标,他们提出了一种很简单的设计,用Python伪代码表示(不包括错误处理和重试逻辑)如下:

def run_taskworker():
    while True:
        queue = select_queue()
        tasks = queue.get_tasks()
        for task in tasks:                
            task.run()

在底层,他们会在每个工作进程节点上运行一组Taskworker进程,每个进程都运行上面所示的循环。所有进程都是完全独立的。select_queue()函数根据队列的优先级决定从哪个队列获取任务。它既要能优先处理高优先级队列的任务,又要能避免低优先级队列挨饿。

在通过模拟生产负载进行了十多次基准测试后,他们最终选用了一个彩票算法的变体,如下所示:

def select_queue():
    candidate_queues = get_all_queues()
    while not candidate_queues.empty():
        queue = run_lottery(candidate_queues)
        if queue.empty():
             candidate_queues.remove(queue)
        else:
             return queue
return run_lottery(get_all_queues())

文中还提到,他们要管理十几个或更多不同种类的队列,每个队列包含的任务具有相同的优先级和相似的运行时间。他们在队列层面进行配置设定,包括优先级、SQS可见性超时以及一次任务处理循环获取的任务数。另外,SQS在向工作进程发送任务时遵循“至少一次”的语义,这就需要任务必须是幂等的。

应用到生产环境

在这一部分,文章介绍了以下三个方面:

  1. 发布过程:为了保持兼容,SQS队列和Taskworker的版本总是相同。
  2. 能力计划:他们使用Taskworker模拟生产负载,以决定在一天中的不同时段如何设置工作进程的能力。
  3. 任务迁移:他们基于每个任务增加了自己开发的开关功能,用于决定是将任务发布到RabbitMQ还是SQS。当开始迁移的时候,他们只需要简单地、一个任务接一个任务地开启开关功能。

结论

截止博文发表时,Taskworker已经在生产环境中运行了三个多月。他们没有再遇到稳定性问题。在运行相同数量的工作进程节点的情况下, Celery系统队列中的任务忙时平均延时是Taskworker系统的40倍。

文章最后指出,Taskworker还有许多可以改进的地方,而且正在准备开源。


感谢郭蕾对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT