使用VoltDB的最新版本(v8.3.1)在集群配置中安装,并执行简单的存储过程

首先

VoltDB在2018年10月的最新版本是v8.3.1。
※截至2018年11月,v8.3.3已经发布。
※截至2019年4月,v9.0已经发布。

因为我第一次使用VoltDB时是在v4.9版本,所以现在版本已经有了很大提升。
因此,这次我想尝试一下最新版本,我首先安装了它,并尝试执行了客户端程序。

VoltDB的最新版本发布说明

尽管v9.0版本也已发布,但安装步骤与v8.3.x相同。

雖然有些陳舊,VoltDB 8.2的發布內容可參考以下資訊。
試著使用VoltDB 8.2版本的發布,體驗自動刪除舊資料的TTL功能。

下面是关于集群架构构建步骤的文章,而单一架构的构建步骤则可以参考以下文章。

安装最新版本(v8.3.1)的内存数据库VoltDB(单节点配置)。

VoltDB 是什么?

VoltDB是一种内存中的关系型数据库,由曾参与PostgreSQL项目的迈克尔·斯通布雷克所创建。
它比NoSQL更快速,并且支持使用SQL和事务。

最近不太受人关注(?),但在2011年的国民偶像团体选拔总选举时引起了话题。
我也购买了此书,其中详细记载了幕后情况(虽然没有涉及太深的技术内容)。

如何构建一个能够承受超负荷的网络系统 〜国民偶像团体选拔总选举的幕后故事 (《软件设计加》)

如果您有兴趣的话,以下内容也可能会对您有所帮助。

尝试使用VoltDB
[https://qiita.com/ytake/items/4da625997079716404ad]
VoltDB(维基百科)
[https://ja.wikipedia.org/wiki/VoltDB]

VoltDB社在2017年进行了与Cassandra的性能比较,据记载,VoltDB在性能和成本方面优于Cassandra。

比较快速数据性能:VoltDB和Cassandra基准测试的比较。

截至2018年11月,DB-ENGINES 在全球排名第109位,在关系数据库管理系统排名中位居第56位。

环境和建设步骤的概要

在VirtualBox上启动3个CentOS 7.4实例,并使用VoltDB构建集群配置。
由于是在本地环境,firewalld和SELinux已被禁用。
[2018/10/8更新]添加了在firewalld启用的情况下进行端口解除和设置的步骤。

服务器是以下三台:
・192.168.10.121
・192.168.10.122
・192.168.10.123

在構築过程中,按照以下顺序进行实施。

    1. 安装OpenJDK

 

    1. 配置NTP

 

    1. 安装VoltDB

 

    1. 配置VoltDB

 

    1. 创建模式

 

    1. 创建和编译过程

 

    启动VoltDB

建造步骤

安装OpenJDK

安装OpenJDK 8或OracleJDK 8。
本次安装了OpenJDK,但推荐使用OracleJDK。
[2018/10/4更新]
虽然推荐使用OracleJDK,但也支持OpenJDK。

# yum install java-1.8.0-openjdk-devel

# java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)

我正在設置JAVA_HOME並在PATH中添加Java的路徑。

# echo "export JAVA_HOME=$(readlink -e $(which java)|sed 's:/bin/java::')" > /etc/profile.d/java.sh
# echo "PATH=\$PATH:\$JAVA_HOME/bin" >> /etc/profile.d/java.sh
# source /etc/profile

NTP的配置

在集群配置中,由于VoltDB服务器之间的时间差需要保持在100毫秒以下,因此需要使用NTP进行时间同步。

在我的环境中,我将”volt1:192.168.10.122″设定为NTP服务器,并将其他两台设备设置为NTP客户端。

由于这是测试环境,所以设置很简略。

①第一台的VoltDB服务器(NTP服务器)

由于运行的是CentOS 7,因此已经安装了chrony。

vi /etc/chrony.conf

在下面进行补充。

# 以下をコメントアウトする
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst

# 以下のコメントを外す
allow 192.168.0.0/16
local stratum 10

重启chronyd。

systemctl restart chronyd

第二台以及之后的VoltDB服务器(NTP客户端)

NTP客户端将直接使用chrony。

vi /etc/chrony.conf

我会在下面添加补充内容。

#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
#server 192.168.10.121 iburst
server volt1 iburst minpoll 4 maxpoll 4

peer volt2 minpoll 4 maxpoll 4
peer volt3 minpoll 4 maxpoll 4

重启chronyd。

systemctl restart chronyd

确认第2台、第3台服务器(volt1、volt2)是否通过”chronyc sources”进行了时间同步。

# chronyc sources
210 Number of sources = 3
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^* volt1                        10   4    37     5    -42us[-1569us] +/-  387us
=? volt2                         0   4     0     -     +0ns[   +0ns] +/-    0ns
=? volt3                        11   4     1    10  -7673us[-9201us] +/-   12ms


防火墙的设置

[2018年10月8日更新]

VoltDB默认使用的端口列表如下。

客户端端口号:21212
管理员端口号:21211
Web界面端口号(httpd):8080
启用TSL/SSL的Web界面端口号:8443
内部服务器端口号:3021
复制端口号:5555
Zookeeper端口号:7181

在这些中,只有在使用时需要打开端口的是“Web Interface Port(启用TSL/SSL)”和“Replication Port”。

firewall-cmd --add-port=21212/tcp --permanent
firewall-cmd --add-port=21211/tcp --permanent
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --add-port=3021/tcp --permanent
firewall-cmd --add-port=5555/tcp --permanent
firewall-cmd --add-port=7181/tcp --permanent
firewall-cmd --add-port=123/udp --permanent
firewall-cmd --add-port=22/tcp --permanent
firewall-cmd --reload

※123 是用于NTP 的

使用下列指令来确认设置。

firewall-cmd --list-ports --zone=public
21212/tcp 21211/tcp 8080/tcp 3021/tcp 5555/tcp 7181/tcp 22/tcp

SSH的配置。

需要在没有密码的情况下使用SSH登录彼此的服务器。之后将会写下步骤。

安装VoltDB

可以通过以下官方网站下载VoltDB模块的“COMMUNITY EDITION”。尽管某些功能可能不可用,但我认为它已经覆盖了足够的功能,可以在生产环境中使用。

如果要使用旧版本,请通过文件指定进行下载,因为上述URL将始终下载最新版本。

image.png

首先,将voltdb-community-8.3.1.tar.gz文件解压到/opt目录下,并创建符号链接。

# tar xvzf voltdb-community-8.3.1.tar.gz -C /opt/
# ln -s /opt/voltdb-community-8.3.1/ /opt/voltdb

在VoltDB中,需要禁用透明大页(Transparent HugePages)。如果不执行此操作,VoltDB将无法启动。这意味着每次操作系统启动后都必须执行此操作。

# echo never > /sys/kernel/mm/transparent_hugepage/enabled
# echo never > /sys/kernel/mm/transparent_hugepage/defrag

要在操作系统启动时自动执行,需要编辑rc.local文件。[2018/10/7更新]
在/etc/rc.local文件中追加以下内容。(适用于CentOS 7.4)

if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
   echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
   echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi

另外,请为rc.local文件赋予执行权限。

# chmod u+x /etc/rc.d/rc.local

最后重启操作系统,执行以下命令以确保两者都设为”never”。

# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]
# cat /sys/kernel/mm/transparent_hugepage/defrag
always madvise [never]

将本次使用的三台服务器放入hosts中。

vi /etc/hosts

将要添加到「/etc/hosts」的内容如下:

192.168.10.121  volt1
192.168.10.122  volt2
192.168.10.123  volt3

接下来,将”/opt/voltdb/bin”添加到路径中。

vi /etc/profile.d/voltdb.sh

追加的内容如下所示。

export PATH="$PATH:/opt/voltdb/bin"

为了立即生效,请输入以下命令。

source /etc/profile

内存管理相关设置

    2.3. Configure Memory Management
# vi /etc/sysctl.conf

vm.swappiness=0
vm.overcommit_memory=1
vm.max_map_count=1048576

# sysctl -p
vm.swappiness = 0
vm.overcommit_memory = 1
vm.max_map_count = 1048576

TCP分段功能关闭

$ vi /etc/rc.d/rc.local

ethtool -K enp0s8 tso off
ethtool -K enp0s8 gro off

確認
$ ethtool --show-features eth0

※enp0s8在不同的环境下会有所不同。

禁用JVM的统计数据收集

禁用JVM的统计收集。

# vi /etc/profile.d/voltdb.sh
export VOLTDB_OPTS='-XX:+PerfDisableSharedMem'

VoltDB的配置

新建一个配置文件,其中包含了VoltDB的集群配置等设置。创建名为”/opt/voltdb/deployment.xml”的文件,内容如下。

“kfactor=”1″” 是备份数量。设置为”1″时,每个数据都会创建一个备份,即使有一台服务器宕机也能保持集群运行。如果有两台服务器宕机,集群将会停止运行。
当集群停止运行时,需要从预先创建的快照文件中恢复。
此次我们将快照设置为””,即关闭快照功能。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<deployment>
    <cluster sitesperhost="8" kfactor="1" schema="ddl"/>
    <paths>
        <!-- <voltdbroot path="/opt/voltdb/voltdbroot"/> -->
        <snapshots path="snapshots"/>
        <exportoverflow path="export_overflow"/>
        <droverflow path="dr_overflow"/>
        <commandlog path="command_log"/>
        <commandlogsnapshot path="command_log_snapshot"/>
        <largequeryswap path="large_query_swap"/>
    </paths>
    <partition-detection/>
    <heartbeat/>
    <ssl/>
    <httpd enabled="true">
        <jsonapi enabled="true"/>
    </httpd>
    <snapshot enabled="false"/>
    <commandlog enabled="false">
        <frequency/>
    </commandlog>
    <systemsettings>
        <temptables/>
        <snapshot/>
        <elastic/>
        <query/>
        <procedure/>
        <resourcemonitor>
            <memorylimit/>
        </resourcemonitor>
    </systemsettings>
    <security/>
</deployment>

创建模式

在「/opt/voltdb」下创建schema.sql文件。
VoltDB4.9的DDL语法有些变化。
表格和存储过程也可以在安装后创建,所以不一定需要在安装前进行准备。

我们正在创建一个名为TEST_DATA的表,并且创建了两个名为GetData和InsertData的存储过程。

CREATE TABLE TEST_DATA (
   NAME varchar(50) NOT NULL,
   DATA smallint,
   UNIQUE (NAME),
   PRIMARY KEY (NAME)
);
PARTITION TABLE TEST_DATA ON COLUMN NAME;

CREATE PROCEDURE
   PARTITION ON TABLE TEST_DATA COLUMN NAME
   FROM CLASS test.GetData;

CREATE PROCEDURE
   PARTITION ON TABLE TEST_DATA COLUMN NAME
   FROM CLASS test.InsertData;

创建和编译程序

以下是一个用于搜索TEST_DATA并插入GetData和InsertData的示例程序(过程)。

这次我们正在创建存储过程,但实际上,在VoltDB中已经有默认的存储过程,可以进行插入/更新/删除/选择操作。只有在需要实现默认无法实现的存储过程时,才需要创建自定义存储过程。

package test;

import org.voltdb.SQLStmt;
import org.voltdb.VoltProcedure;
import org.voltdb.VoltTable;

public class GetData extends VoltProcedure {

    public final SQLStmt selectData = new SQLStmt("select data from test_data where name = ?");

    public VoltTable[] run(String name) {

        voltQueueSQL(selectData, name);
        VoltTable[] results = voltExecuteSQL();

        return results;
    }
}
package test;

import org.voltdb.SQLStmt;
import org.voltdb.VoltProcedure;
import org.voltdb.VoltTable;

public class InsertData extends VoltProcedure {

    public final SQLStmt insertData = new SQLStmt("insert into test_data values(?, ?)");

    public VoltTable[] run(String name, int data) {

        voltQueueSQL(insertData, name, data);
        VoltTable[] results = voltExecuteSQL();

        return results;
    }
}



为了编译, 将位于/opt/voltdb/voltdb目录下的voltdb-8.3.1.jar添加到构建路径中。
然后,将其打包成一个Jar文件(catalog.jar),并存储在每个服务器的/opt/voltdb目录下。

VoltDB的初始化和启动

使用Procedure(catalog.jar)、DDL(schema.sql)、配置文件(deployment.xml)对VoltDB进行初始化。在所有三台上执行。
※如果附加-f选项,则会强制执行初始化。由于这是第一次操作,所以不需要加上-f选项。如果已经初始化完毕,则需要添加-f选项。

# cd /opt/voltdb
# voltdb init -D /opt/voltdb -C /opt/voltdb/deployment.xml -j /opt/voltdb/catalog.jar -s /opt/voltdb/schema.sql -f

启动 VoltDB。

# cd /opt/voltdb
# voltdb start -D /opt/voltdb -H volt1 -c 3 -B

-D:指定VoltDB的根目录(与init时相同的目录)
-H:连接到集群的服务器
这次连接到的是volt1,但通常只需要设置为volt1、volt2、volt3。
-c:集群中的服务器数量
-B:在后台运行

打开VoltDB的Web界面

在VoltDB中,通过启动Web应用程序可以执行SQL并查看性能。该应用程序在每个服务器上运行,并可以通过8080端口访问。

画面如下所示。

image.png

运行客户端程序

我們將創建一個客戶端程式,以訪問先前創建的GetData和InsertData程序。

import java.io.IOException;

import org.voltdb.VoltTable;
import org.voltdb.VoltType;
import org.voltdb.client.Client;
import org.voltdb.client.ClientFactory;
import org.voltdb.client.ClientResponse;
import org.voltdb.client.NoConnectionsException;
import org.voltdb.client.ProcCallException;

public class SimpleMain {

    public static void main(String[] args) throws NoConnectionsException, IOException, ProcCallException {
        Client client = ClientFactory.createClient();
        client.createConnection("192.168.10.121");
        client.createConnection("192.168.10.122");
        client.createConnection("192.168.10.123");

        String msgId = "test1";
        VoltTable[] results;
        ClientResponse res;

        res = client.callProcedure("InsertData", msgId, 1);

        if (res.getStatus() == ClientResponse.SUCCESS) {
            System.out.println("Insertに成功");
        }

        res = client.callProcedure("GetData", msgId);
        results = res.getResults();

        while (results[0].advanceRow()) {
            Short value = (Short) results[0].get(0, VoltType.SMALLINT);
            System.out.println("value = " + value);
        }
    }
}

我正在连接以下所有构成集群的服务器。

        Client client = ClientFactory.createClient();
        client.createConnection("192.168.10.121");
        client.createConnection("192.168.10.122");
        client.createConnection("192.168.10.123");

测试性能

我创建了一个测试程序,用500个线程将50万条记录插入,并测量了性能。
在VoltDB中,最好将大约8个核心分配给一个服务器,但由于我在本地PC的虚拟环境中运行,所以配置成了一个核心三个服务器的结构。
您可以在VoltDB的Web界面上查看测量结果。

image.png

首先,每秒最多能处理约18,000条记录的交易,在这种不太理想的环境中,算是相当不错了吧?

image.png

特别是平均延迟(毫秒)为0.02毫秒,非常快。我认为这展现了内存型关系型数据库的真正价值。

广告
将在 10 秒后关闭
bannerAds