使用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
在構築过程中,按照以下顺序进行实施。
-
- 安装OpenJDK
-
- 配置NTP
-
- 安装VoltDB
-
- 配置VoltDB
-
- 创建模式
-
- 创建和编译过程
- 启动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将始终下载最新版本。

首先,将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端口访问。
画面如下所示。

运行客户端程序
我們將創建一個客戶端程式,以訪問先前創建的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界面上查看测量结果。

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

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