何时使用非阻塞>!/线程和阻止> !!/goroutines with clojure core.async

 手机用户2602927383 发布于 2023-01-30 14:41

我正在编写一个ETL过程来从产品数据库中读取事件级数据,转换/聚合它并写入分析数据仓库.我正在使用clojure的core.async库将这些进程分成并发执行的组件.这是我的代码的主要部分现在看起来像

    (ns data-staging.main
        (:require [clojure.core.async :as async])
        (:use [clojure.core.match :only (match)]
              [data-staging.map-vecs]
              [data-staging.tables])
        (:gen-class))

    (def submissions (make-table "Submission" "Valid"))
    (def photos (make-table "Photo"))
    (def videos (make-table "Video"))
    (def votes (make-table "Votes"))

    ;; define channels used for sequential data processing
    (def chan-in (async/chan 100))
    (def chan-out (async/chan 100))

    (defn write-thread [table]
        "infinitely loops between reading subsequent 10000 rows from 
         table and ouputting a vector of the rows(maps) 
         into 'chan-in'"
        (while true
            (let [next-rows (get-rows table)]
                (async/>!! chan-in next-rows)
                (set-max table (:max-id (last next-rows))))))

    (defn aggregator []
        "takes output from 'chan-in' and aggregates it by coupon_id, date.
         then adds / drops any fields that are needed / not needed and inputs
         into 'chan-out'"
        (while true
            (->>
                (async/!! chan-out))))

    (defn read-thread []
        "reads data from chan out and interts into Analytics DB" 
        (while true 
            (upsert (async/

正如你所看到的,我将每个os组件放到它自己的线程上并使用阻塞> !! 打电话给频道.感觉就像使用非阻塞>!对于此用例,调用以及go例程可能更好,特别是对于数据库读取,这些读取花费大部分时间执行i/o并等待产品db中的新行.是这种情况,如果是这样,实施它的最佳方法是什么?我对这两种方法之间的所有权衡以及如何有效地使用go例程有点不清楚.此外,任何其他关于如何改善整体架构的建议将非常感谢!

1 个回答
  • 就个人而言,我认为你在这里使用线程可能是正确的.go-blocks的神奇非阻塞性质来自"停放",这是core.async的状态机使用的一种特殊的伪阻塞 - 但是因为你的数据库调用真正阻塞而不是将状态机置于停放状态,你只是阻止来自core.async线程池的一些线程.它确实取决于你的同步调用需要多长时间,所以这就是基准可以提供信息的东西,但我强烈怀疑线程是正确的方法.

    一个例外是您的聚合器功能.在我看来它可以只是折叠成一个chan-out的定义,如(def chan-out (map< aggregate chan-in)).

    对于go-blocks与线程的一般概述,Martin Trojer对这两种方法进行了很好的检验,哪种方法在哪种情况下更快.Cliff的Notes版本是go-blocks适合于调整已经异步的库以与core.async一起使用,而线程适合于使异步进程脱离同步部分.例如,如果您的数据库有一个基于回调的API,则go-blocks将是一个明确的胜利.但由于它是同步的,它们不适合.

    2023-01-30 14:43 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有