PipelineDB Version:0.9.7

PostgreSQL Version:9.5.3

PipelineDB的数据处理组件:

从上图来看主要就是pipeline_streams,stream_fdw,Continuous View,Transform。

其实就是运用了Postgres的FDW功能来实现的stream功能。

从数据库也能看到这个FDW

pipeline=# \des
List of foreign servers
Name | Owner | Foreign-data wrapper
------------------+-----------------+----------------------
pipeline_streams | unknown (OID=0) | stream_fdw
(1 row)

数据流转入下图

可以看到数据流转都是通过ZeroMQ来实现的(前面的版本0.8.2之前是通过TupleBuff来实现)

数据插入到Stream后然后调用ForiegnInsert,插入到初始化的IPC里面去,在数据库目录下面有个pipeline/zmq

TransForm其实就是把数据的dest指向了Stream,数据库默认有个pipeline_stream_insert其实这个是个Trigger,把tuple再扔到目标stream里面。

或者你可以自己写UDF,就是写个trigger,数据可以写到表或者别的FDW里面,或者是自己封装的消息队列IPC都没问题,这块自由发挥的空间就比较大。

首先我们来创建个STREAM跟CV

pipeline=# create stream my_stream(x bigint,y bigint,z bigint);
CREATE STREAM
pipeline=# create continuous view v_1 as select x,y,z from my_stream;
CREATE CONTINUOUS VIEW
pipeline=#

插入一条数据:

pipeline=# insert into my_stream(x,y,z) values(1,2,3);
INSERT 0 1
pipeline=# select * from v_1;
x | y | z
---+---+---
1 | 2 | 3
(1 row) pipeline=#

数据插入到CV中了,我们现在来看看PipelineDB是如何插入的。

上面有介绍了Stream就是个FDW。我们来看看他的handler(source:src/backend/pipeline/stream_fdw.c)

/*
* stream_fdw_handler
*/
Datum
stream_fdw_handler(PG_FUNCTION_ARGS)
{
FdwRoutine *routine = makeNode(FdwRoutine); /* Stream SELECTS (only used by continuous query procs) */
routine->GetForeignRelSize = GetStreamSize;
routine->GetForeignPaths = GetStreamPaths;
routine->GetForeignPlan = GetStreamScanPlan;
routine->BeginForeignScan = BeginStreamScan;
routine->IterateForeignScan = IterateStreamScan;
routine->ReScanForeignScan = ReScanStreamScan;
routine->EndForeignScan = EndStreamScan; /* Streams INSERTs */
routine->PlanForeignModify = PlanStreamModify;
routine->BeginForeignModify = BeginStreamModify;
routine->ExecForeignInsert = ExecStreamInsert;
routine->EndForeignModify = EndStreamModify; routine->ExplainForeignScan = NULL;
routine->ExplainForeignModify = NULL; PG_RETURN_POINTER(routine);
}

主要是关注Streams Inserts这几个函数.

每个worker process启动的时候都会初始化一个recv_id,其实这个就是ZeroMQ的ID

数据会发送到对应的队列里面去,worker process就去这个IPC里面去获取数据

source:src/backend/pipeline/ipc/microbath.c

void
microbatch_send_to_worker(microbatch_t *mb, int worker_id)
{
...... worker_id = rand() % continuous_query_num_workers;
}
} recv_id = db_meta->db_procs[worker_id].pzmq_id; microbatch_send(mb, recv_id, async, db_meta);
microbatch_reset(mb);
}

首先是获取worker_id 这个是随机获取的一个worker进程。stream数据随机发到一worker process里面去了

recv_id这个就是从初始化的IPC队列获取ID,数据就发送到该队列里面

最后就调用

pzmq_send(recv_id, buf, len, true)

数据就推送到了IPC中了。

(gdb) p	recv_id
$12 = 1404688165
(gdb)

这部分就是数据生产者部分。

下面就是数据消费者CV

数据接受还是通过ZMQ的API来接受的

这个主要是worker process来干活的

srouce:src/backend/pipeline/ipc/pzmq.c&reader.c

(gdb) p *zmq_state->me
$8 = {id = 1404688165, type = 7 '\a', sock = 0x1139ba0, addr = "ipc:///home/pipeline/db_0.9.7/pipeline/zmq/1404688165.sock", '\000' <repeats 965 times>}
(gdb)

可以看到这个数据是从1404688165里面获取的 ,并且把IPC的addr也给出来了,这个就是我数据库目录

获取到是个buf,然后unpack,从消息里面获取到对应的Tuple.

获取到了tuple后,然后就找所有的CV跟这个stream相关的target。遍历他们,然后执行CV中对应的SQL。

执行流程跟标准SQL差不多也是初始化执行计划然后ExecutePlan然后endplan 。

数据会到Combiner里面,如果是AGG还会有一系列操作的。

如果数据符合CV的SQL逻辑,那么数据就插入到对应的物理表。

这就是Stream的一个简单的工作原理。

谢谢

浅谈PipelineDB系列一: Stream数据是如何写到Continuous View中的的更多相关文章

  1. 浅谈POSIX线程的私有数据

    当线程中的一个函数需要创建私有数据时,该私有数据在对函数的调用之间保持一致,数据能静态地分配在存储器中,当我们采用命名范围也许可以实现它使用在函数或是文件(静态),或是全局(EXTERN).但是当涉及 ...

  2. 浅谈c#的三个高级参数ref out 和Params C#中is与as的区别分析 “登陆”与“登录”有何区别 经典SQL语句大全(绝对的经典)

    浅谈c#的三个高级参数ref out 和Params   c#的三个高级参数ref out 和Params 前言:在我们学习c#基础的时候,我们会学习到c#的三个高级的参数,分别是out .ref 和 ...

  3. 浅谈ASP.net处理XML数据

    XML是一种可扩展的标记语言,比之之前谈到的html有着很大的灵活性,虽然它只是与HTML仅有一个字母只差,但两者有很大的区别. XML也是标记语言,所以它每个标签必须要闭合,而HTML偶尔忘了闭合也 ...

  4. sqlite升级--浅谈Android数据库版本升级及数据的迁移

    Android开发涉及到的数据库采用的是轻量级的SQLite3,而在实际开发中,在存储一些简单的数据,使用SharedPreferences就足够了,只有在存储数据结构稍微复杂的时候,才会使用数据库来 ...

  5. 浅谈c语言代码段 数据段 bss段

    代码段.数据段.bss段 (1)编译器在编译程序的时候,将程序中的所有的元素分成了一些组成部分,各部分构成一个段,所以说段是可执行程序的组成部分. (2)代码段:代码段就是程序中的可执行部分,直观理解 ...

  6. 浅谈Xcode5和Xcode7在系统创建的文件夹和文件中的区别

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  7. 【WebApi系列】浅谈HTTP

    [01]浅谈HTTP在WebApi开发中的运用 [02]聊聊WebApi体系结构 [03]详解WebApi如何传递参数 [04]详解WebApi测试和PostMan [05]浅谈WebApi Core ...

  8. 【WebApi系列】浅谈HTTP在WebApi开发中的运用

    WebApi系列文章 [01]浅谈HTTP在WebApi开发中的运用 [02]聊聊WebApi体系结构 [03]详解WebApi参数的传递 [04]详解WebApi测试和PostMan [05]浅谈W ...

  9. 浅谈如何使用python抓取网页中的动态数据

    我们经常会发现网页中的许多数据并不是写死在HTML中的,而是通过js动态载入的.所以也就引出了什么是动态数据的概念, 动态数据在这里指的是网页中由Javascript动态生成的页面内容,是在页面加载到 ...

随机推荐

  1. Mybatis报错:Parameter 'list' not found. Available parameters are [groupList, param1]

    GroupDao.java 里面定义的方法: void batchInsertLog(@Param("groupList") List<MktPromotionIntegra ...

  2. Django web框架篇:基础

    对于web开发者来说,socket是基础.因为Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. 对于真实开发中的python web程序来说,一般会分为两 ...

  3. 最长上升子序列(logN算法)

    例如:1 7 3 5 9 4 8 一个序列,比如说a[]={1,7,3,5,9,4,8},找出它的最长上升子序列的个数,很明显是4个,可以是{1,3,5,9},{1,3,5,8}或者{1,3,4,8} ...

  4. Android 开发笔记___FrameLayout

    xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:la ...

  5. Flex中宽度计算

    flex 有三个属性值,分别是 flex-grow, flex-shrink, flex-basis,默认值是 0 1 auto. 发现网上详细介绍他们的文章比较少, 今天就详细说说他们,先一个一个看 ...

  6. Apple 公司开发者账号添加团队成员

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  7. jQuery_DOM学习之------遍历节点

    一.children()方法 例子: <!DOCTYPE html> <html> <head> <meta http-equiv="Content ...

  8. Linux学习(二十)软件安装与卸载(三)源码包安装

    一.概述 源码包安装的优点在于它自由程度比较高,可以指定目录与组件.再有,你要是能改源码也可以. 二.安装方法 步骤 1.从官网或者信任站点下载源码包 [root@localhost ~]# wget ...

  9. 一个简单的MVC框架的实现

    1.Action接口 package com.togogo.webtoservice; import javax.servlet.http.HttpServletRequest; import jav ...

  10. elastic-search单机部署以及中文分词IKAnalyzer安装

    前提条件 elasticsearch使用版本5.6.3,需要jdk版本1.8,低于该版本不能使用 下载 https://artifacts.elastic.co/downloads/elasticse ...