timescaledb性能测试

link:https://github.com/timescale/timescaledb[timescaledb]是postgresql数据库的一个插件,通过hypertable实现对时间序列数据库进行分块,通过把大表分为多个小表的方式,新的数据总是插入到最新的块上,由于进行了分块,使得索引数据变小,保持索引一直处于内存当中,不用去磁盘交换数据,因此加快了数据的插入速度。timescaledb官方提供了数据库性能测试工具和数据,可参考link:https://github.com/timescale/benchmark-postgres[benchmark-postgres]。 官方也有link:https://blog.timescale.com/timescaledb-vs-6a696248104e[测试报告],随着数据量的增加,数据插入的性能一直处于稳定状态,而相比之下,postgresql则表现为指数级下降。 本测试采用官方提供的数据和程序,测试环境为阿里云ecs.g5.large云服务器,具体配置如下: * 2核cpu * 8GB内存 * 两块100GB ssd云盘,1800 IOPS * 系统为Debian 9.2 ## 测试步骤: 分别挂在两块ssd云盘到/data和/data1。 安装postgresql-9.6,安装timescaledb扩展。修改配置,修改配置: ```ini shared_preload_libraries = 'timescaledb' data_directory = ‘/data/pgdb’ shared_buffers = 2GB ``` 保存后重启postgresql。具体步骤参考相应的文档。 下载官方提供的link:https://timescaledata.blob.core.windows.net/datasets/benchmark_postgres.tar.bz2[数据]并解压到/data1目录下,cpu-data.csv中包含1亿条数据,每条数据格式如下: ```shell 2016-01-03 23:59:30+00,host_1999,80.6521114433705,60.9865370795396,38.7496729040943,11.5620089238801,47.2124408432341,82.4793308352443,41.6463534391737,85.2477509705689,53.843722695106,52.3795963946359 ``` 下载测试程序,安装go环境,并编译3个程序,并将测试程序拷贝到/data1目录下。 创建benchmark数据,并初始化cpu_ts和cpu_pg表: ```shell postgres@debian:/data1$ psql -c 'CREATE DATABASE benchmark;' postgres@debian:/data1$ psql -d benchmark benchmark-setup-timescaledb.sql postgres@debian:/data1$ psql -d benchmark benchmark-setup-postgresql.sql ``` 分别想cpu_pg和cpu_ts数据库插入数据: ``` postgres@debian:/data1$ ./copy --db-name=benchmark --table=cpu_pg --verbose --reporting-period=30s --file=cpu-data.csv --connection='host=localhost user=postgres password=postgres' postgres@debian:/data1$ ./copy…

tcpdump使用方法介绍

tcpdump是一个网络抓包工具,依赖于libpcap实现。libpcap是一个网络抓包库,支持ether,fddi,tr,wlan,ip,ip6,arp,rarp,decnet,tcp和udp协议。 tcpdump的基本是用方法为: [source,shell] ---- tcpdump options expression ---- options指定程序运行选项,expression是一个逻辑表达式,只抓取满足expressionn表达式的包。例如`tcpdump -i eth0 tcp and host 192.168.1.101`抓取eth0接口到192.168.1.101主机的所有tcp包。`-i eth0`是运行选项,`tcp and host 192.168.1.101`是表达式,表示抓取所有到192.168.1.101主机的tcp包。tcpdump支持的详细参数可参考`man tcpdump`,表达式的详细信息可参考`man pcap-filter`。 == 常用的选项 -A:: 采用ASCII码打印出包内容,抓取网页时很方便。 -F file:: 使用file文件中的内容作为表达式,命令行中的表达式将被忽略。 -i interface:: 要抓取的网络接口,如果未指定,则使用序号最小的接口,如eth0。也可以使用any来使用任意接口。 -l:: 设置stdout的输出模式为行缓冲,当想一边抓包一遍查看数据的时候有用。如`tcpdump -l | tee dat`和`tcpdump -l dat & tail -f dat`。 -e:: 打印数据链路层包头。 -Q direction:: 设置要抓取发送还是接收的数据,可能的值为in,out和inout。 -r file:: 从文件中读取数据包(有tcpdump -w生成,或其他pcap兼容格式)。 -v:: -vv:: -vvv:: 打印详细信息。 -w file:: 将原始包信息输出到文件中,之后可以通过-r来打印。 -x:: 除了打印包头,同样以十六进制方式打印包内容,不包括链路层的包头。 -xx:: 除了打印包头,同样以十六进制方式打印包内容。 -X:: 除了打印包头,同样以十六进制和ASCII码方式打印包内容,不包括链路层的包头。 -XX:: 除了打印包头,同样以十六进制和ASCII码方式打印包内容。 == 表达式语法…

libvirt虚拟化开发简介

libvirt是一个虚拟化开发的工具库,提供了底层的kvm,xen,vmware esx等虚拟化的统一封装。可以通过libvirt提供的api对不同的底层实现进行同一的管理。除了原生的c api,还有c#, go, java, ocaml. perl, python, php, ruby的api,用户可自主选择自己熟悉的语言。 要使用libvirt首先要安装libvirtd,这是一个后台守护进程,负责管理虚拟机系统以及和客户端交互。libvirt还包含了virsh命令行工具,供用户通过shell手动管理。另外,还可以通过图形界面方式进行管理,该工具是virt-manager,如果您想要通过python的api进行开发,需要安装python3-libvirt或python-libvirt。在debian下,可通过下列指令安装这些包: apt-get install libvirt-daemon libvirt-daemon-system libvirt-clients python3-libvirt virt-manager 启动libvirtd: systemctl start libvirtd 接下来我们就可以通过virt-manager创建一个虚拟机。熟悉vmware或者virtualbox的同学,可以看到virt-manager和这些软件很类似,安装系统就不再介绍了。 系统安装完成之后,我们就可以通过virsh工具进行基本的操作了。运行virsh,回车,进入virsh的命令行,可通过help查看virsh支持的操作。 virsh # help Grouped commands: Domain Management (help keyword 'domain'): attach-device attach device from an XML file attach-disk attach disk device attach-interface attach network interface autostart autostart a domain blkdeviotune Set or query a block device I/O tuning parameters. blkiotune Get or set blkio parameters blockcommit…

reStructuredText标记语言参考规范

译自http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html reStructuredText是纯文本格式,采用简单直观的结构表示结构化的文档。这些结构很容易阅读和处理。本篇文档本身就是reStructuredText例子。reStructureText解析器是Docutils的一个组件。 用简单,隐式的标记来表示特殊的结构,如节标题,无序列表和强调。使用的标记尽可能的简单和恰当。不经常使用的标记可能会比较复杂或有明确的标记。 reStructuredText既可以应用于篇幅较小的文档(如内联程序文档,如python文档),也可一个用于篇幅很长的文档(如本文)。 第一部分通过例子来展示一些reStructuredText基本语法,然后会给出详细的语法规范。 本篇文章通过文本块来展示示例。 内容 语法概览 语法详细 空白字符 空行 缩进 转义机制 引用名称 文档结构 文档 节 转换 主体元素 段落 无序列表 有序列表 定义列表 字段列表 书目字段 RCS关键字 选项列表 文本块 缩进文本块 引用文本块 行块 块引用 Doctest块 表格 网格表格 简单表格 显示标记块 脚注 自动编号脚注 自动符号脚注 手动和自动编号混合脚注 引文 链接目标 匿名链接 指令 替代定义 注释 隐士链接目标 内联标记 内联标记识别规则 识别顺序 字符级内联标记 强调 着重强调 解释文本 内联文本 超链接引用 嵌入式URI和别名 内联内部目标 脚注引用 引文引用 替代引用 标准超链接 单位 长度单位 百分比单位 错误处理 语法概述 reStructuredText文档由主体或块级元素构成,还可以结构化为节。节是根据标题样式(下划线和可选的上划线)决定的。节包含主体元素和/或子节。主体元素包含更多的元素,如列表项,段落和其他主体元素。其他的,例如段落包含文本和内联标记元素。 下面是一些主体元素示例:…

阿里云发送短信 python3实现

import uuid import datetime import hmac import base64 import requests from urllib.parse import urlencode, quote class AliyunSMS(object): def __init__(self, app): self.app = app self.format = app.config.get("ALIYUN_API_FORMAT") or "JSON" self.version = "2016-09-27" self.key = app.config["ALIYUN_API_KEY"] self.secret = app.config["ALIYUN_API_SECRET"] self.signature = "" self.signature_method = "HMAC-SHA1" self.signature_version = "1.0" self.signature_nonce = str(uuid.uuid4()) self.timestamp = datetime.datetime.utcnow().isoformat("T") self.region_id = app.config["ALIYUN_API_REGION_ID"] self.gateway = app.config["ALISMS_GATEWAY"] self.action = "" self.sign = "" self.template = "" self.params = {}…

jabberd2认证配置之mysql配置

jabberd2自带了的authreg支持mysql、sqlite、ldap、pipe等方式。通常情况下,你有一个网站为用户提供服务,用户在你的网站注册了,用户名和密码信息存储在网站服务器的数据库中。而现在你用jabberd2为用户搭建了一个xmpp聊天服务器,并且希望你的用户能够通过在你的网站上注册的用户名和密码登录聊天服务器,而不是在聊天服务器上创建新用户,那么你可以使用jabberd2自带的authreg_mysql模块。要使用authreg_mysql模块,你需要在c2s.xml的mysql节修改或添加如下配置: <mysql> <!-- 数据库服务器的地址和端口 --> <host>localhost</host> <port>3306</port> <!-- 数据库名 --> <dbname>jabberd2</dbname> <!-- 数据库用户和密码 --> <user>jabber</user> <pass>jabber</pass> <!-- table_name为数据库中存储用户表的表名 --> <table>table_name</table> <field> <!-- username_field为表中用户名字段 --> <username>username_field</username> <!-- password_field为表中密码字段 --> <username>password_field</username> <!-- realm_filed,c2s.xml中配置的realm --> <username>realm_filed</username> </field> </mysql> 如果你的用户表中,没有关于real的字段,所有的用户属于同一区域下,你可以使用下面这种配置: <mysql> <!-- 数据库服务器的地址和端口 --> <host>localhost</host> <port>3306</port> <!-- 数据库名 --> <dbname>jabberd2</dbname> <!-- 数据库用户和密码 --> <user>jabber</user> <pass>jabber</pass> <sql> <!-- 替换_password,_usertable,_username,_realm为真实的名称,_realm与c2s.xml中配置的相同 --> <select>select `_password` from `_usertable` where `_username` = '%s' and '%s' = '_realm'</select> </sql> </mysql> 更多信息请参考https://github.com/jabberd2/jabberd2/blob/master/storage/authreg_mysql.c。…

《C++注解》第9章 类和内存分配

第9章 类和内存分配 和C语言中的内存分配函数(如malloc)对比,C++中的内存分配是由new运算符完成的。malloc和new的主要区别如下: malloc自身不清楚被分配的内存将作何用。例如,当为int类型分配内存时,编程者必须提供一个正确的表达式,用于表示分配多少个sizeof(int)大小的空间。相比之下,new只需指定一个类型就可,编译器会隐式调用sizeof运算符。使用new是类型安全的。 ~~malloc分配的内存会被calloc舒适化为指定的值~~(译者注:malloc不会调用calloc初始化,malloc分配的内存是未被初始化的,calloc分配的内存会被自动初始化为0)。如果分配的内存是为一个对象使用,这是不必要的。因为new运算符会根据该对象的构造函数对该内存进行特定的初始化。 采用C中的内存分配函数,我们必须要检查这些函数的返回值是否为NULL,采用new分配内存时则不需要这样的检查,我们可以通过配置new_handler来指定new失败时要执行的动作。 free和delete的比较:delete运算符能够保证在回收某个对象的内存时,这个对象的析构函数会被调用。 本章重点要讲的就是创建对象和销毁对象时,构造函数和析构函数的自动执行。在C程序的开发中,许多问题都是由不正常的内存分配和内存泄露造成的,如内存未被分配,内存未被释放,内存未被初始化,内存访问越界等。虽然C++不能自动的解决这些问题,但它给我们提供了有用的工具来防止这类问题的发生。 在C中,malloc经常用来处理字符串。在string.h其中有一些字符串处理函数是基于malloc的,如strdup。这些函数在C++中,我们应避免使用这些函数,取而代之,我们应该使用string类以及new和delete运算符。 Memory allocation procedures influence the way classes dynamically allocating their own memory should be designed. 因此,除了new和delete运算符,本章还会讨论这些内容。首先,先介绍new和delete运算符,然后会讨论: 析构函数:在对象被销毁时被调用的成员函数。 赋值运算符:允许我们将一个对象赋值给同类的另一个对象。 this指针:在一个对象的成员函数被调用时,明确的引用这个对象。 拷贝构造:创建一个对象副本的构造函数。 移动构造:从一个匿名的临时变量穿件对象的构造函数。 9.1 new和delete运算符 C++定义了两个用来分配和释放内存的运算符,分别为new和delete。 下面是一个简单的示例程序来演示如何使用他们。一个int类型的指针指向new申请的内存,之后该内存通过delete进行释放。 int *ip = new int; delete ip; 下面是new和delete运算符的一些特性: new和delete是运算符,因此使用时不需要加括号 new返回指向一个内存区域,该指针的类型为被分配内存的对象类型(上例中,返回一个int类型的指针) new后面跟着一个类型名称作为操作数,因此能为该类新的对象分配正确数量的内存 new是一个类型安全的操作符,它总是能够返回一个指向和操作数相同类型对象的指针,并且该指针的类型和这个对象的类型相同 new可能会失败,但是开发者不必担心这个问题,程序中不需要像使用malloc时那样必须检测内存是否分配成功,在9.2.2中会深入讨论new的这个特性 delete返回void new和delete必须成对使用,一个由new申请的内存,最终要有一个相对应的delete执行,以免内存泄露的情况发生 delete能够安全的处理0指针(什么也不做) delete只能释放由new申请的内存,不应该用来释放使用malloc申请的内存 C++中,malloc和相近的内存分配函数(如calloc)是被弃用的,因此我们应避免使用它们 new运算符既可以为基本类型分配内存,又可以给对象分配内存。当为基本类型或者没有构造函数的struct类型分配内存时,不能保证这些内存被初始化为0,但是我们可以为其提供一个初始化表达式。 int *v1 = new int; // not guaranteed to be initialized to 0 int *v1 = new…

openvpn systemd 配置

[Unit] Description=OpenVPN Service [Service] Type=forking ExecStartPre=/sbin/iptables-restore /etc/iptables-save ExecStart=/usr/sbin/openvpn --cd /etc/openvpn --config /etc/openvpn/server.conf --daemon [Install] WantedBy=multi-user.target…

堆排序算法

#include <stdio.h> void adjust_array(int array[], int length, int start) { int tmp; for (int i=start; i<=length/2-1; ) { if (array[2*i+1] > array[i] || 2*i+2 < length \ && array[2*i+2] > array[i]) { tmp = array[i]; if (2*i + 2 < length && array[2*i+2] > array[2*i+1]) { array[i] = array[2*i+2]; array[2*i+2] = tmp; i = 2*i + 2; } else { array[i] = array[2*i+1]; array[2*i+1] = tmp; i = 2*i +…