如何在Ubuntu14.04上安装MemSQL
与 MemSQL 合作编写
介绍
MemSQL 是一种内存数据库,可以提供比传统数据库更快的读取和写入。 尽管它是一项新技术,但它使用 MySQL 协议,因此使用起来感觉非常熟悉。
MemSQL 采用了具有现代特性的 MySQL 的最新功能,例如 JSON 支持和 upsert 数据的能力。 MemSQL 相对于 MySQL 的最大优势之一是它能够将单个查询拆分到多个节点,称为 大规模并行处理 ,这会导致读取查询速度更快。
在本教程中,我们将在单个 Ubuntu 14.04 服务器上安装 MemSQL,运行性能基准测试,并通过命令行 MySQL 客户端插入 JSON 数据。
先决条件
要遵循本教程,您将需要:
- 一个 Ubuntu 14.04 x64 Droplet,至少 8 GB RAM
- 具有 sudo 权限的非 root 用户,您可以按照 Initial Server Setup with Ubuntu 14.04 教程进行设置
第 1 步 — 安装 MemSQL
在本节中,我们将为 MemSQL 安装准备工作环境。
最新版本的 MemSQL 列在 他们的下载页面 。 我们将下载和安装 MemSQL Ops,这是一个管理下载和准备服务器以正确运行 MemSQL 的程序。 在撰写本文时,最新版本的 MemSQL Ops 是 4.0.35。
首先,从他们的网站下载 MemSQL 的安装包文件。
wget http://download.memsql.com/memsql-ops-4.0.35/memsql-ops-4.0.35.tar.gz
接下来,解压缩包。
tar -xzf memsql-ops-4.0.35.tar.gz
解压包创建了一个名为 memsql-ops-4.0.35
的文件夹。 请注意,文件夹名称包含版本号,因此如果您下载的版本比本教程指定的版本更新,您将拥有一个包含您下载版本的文件夹。
将目录更改到此文件夹。
cd memsql-ops-4.0.35
然后,运行安装脚本,它是我们刚刚解压的安装包的一部分。
sudo ./install.sh
您将看到脚本的一些输出。 片刻之后,它会询问您是否只想在此主机上安装 MemSQL。 我们将在以后的教程中介绍如何在多台机器上安装 MemSQL。 因此,出于本教程的目的,让我们通过输入 y 来表示同意。
安装脚本提示和输出
. . . Do you want to install MemSQL on this host only? [y/N] y 2015-09-04 14:30:38: Jd0af3b [INFO] Deploying MemSQL to 45.55.146.81:3306 2015-09-04 14:30:38: J4e047f [INFO] Deploying MemSQL to 45.55.146.81:3307 2015-09-04 14:30:48: J4e047f [INFO] Downloading MemSQL: 100.00% 2015-09-04 14:30:48: J4e047f [INFO] Installing MemSQL 2015-09-04 14:30:49: Jd0af3b [INFO] Downloading MemSQL: 100.00% 2015-09-04 14:30:49: Jd0af3b [INFO] Installing MemSQL 2015-09-04 14:31:01: J4e047f [INFO] Finishing MemSQL Install 2015-09-04 14:31:03: Jd0af3b [INFO] Finishing MemSQL Install Waiting for MemSQL to start...
现在,您已将 MemSQL 集群部署到您的 Ubuntu 服务器! 但是,从上面的日志中,您会注意到 MemSQL 安装了两次。
MemSQL 可以作为两种不同的角色运行:聚合器节点和叶节点。 之所以安装两次 MemSQL,是因为它需要至少一个聚合器节点和至少一个叶节点才能运行集群。
聚合器节点 是 MemSQL 的接口。 在外界看来,它很像 MySQL:它侦听同一个端口,您可以将期望与 MySQL 对话的工具和标准 MySQL 库连接到它。 聚合器的工作是了解所有 MemSQL 叶节点,处理 MySQL 客户端,并将它们的查询转换为 MemSQL。
叶节点 实际上存储数据。 当叶节点从聚合器节点接收到读取或写入数据的请求时,它会执行该查询并将结果返回给聚合器节点。 MemSQL 允许您在多个主机之间共享您的数据,并且每个叶节点都有该数据的一部分。 (即使使用单个叶节点,您的数据也会在该叶节点中拆分。)
当您有多个叶节点时,聚合器负责将 MySQL 查询转换为应该参与该查询的所有叶节点。 然后它从所有叶节点获取响应并将结果聚合到一个查询中,该查询返回给您的 MySQL 客户端。 这就是管理并行查询的方式。
我们的单主机设置在同一台机器上运行聚合器和叶节点,但您可以在许多其他机器上添加更多叶节点。
第 2 步 — 运行基准测试
让我们看看使用 MemSQL Ops 工具可以多快运行 MemSQL,该工具是作为 MemSQL 安装脚本的一部分安装的。
在您的网络浏览器中,转到 http://your_server_ip:9000
MemSQL Ops 工具为您提供集群的概览。 我们有 2 个 MemSQL 节点:主聚合器和叶节点。
让我们在我们的单机 MemSQL 节点上进行速度测试。 点击左侧菜单中的Speed Test,然后点击START TEST。 以下是您可能会看到的结果示例:
我们不会在本教程中介绍如何在多台服务器上安装 MemSQL,但为了进行比较,这里有一个来自具有三个 8GB Ubuntu 14.04 节点(一个聚合器节点和两个叶节点)的 MemSQL 集群的基准测试:
通过将叶节点的数量增加一倍,我们几乎可以将插入率提高一倍。 通过查看 Rows Read 部分,我们可以看到我们的三节点集群能够在相同的时间内同时读取比单节点集群多 12M 的行。
第 3 步 — 通过 mysql-client 与 MemSQL 交互
对于客户来说,MemSQL 看起来像 MySQL; 他们都说相同的协议。 要开始与我们的 MemSQL 集群通信,让我们安装一个 mysql-client。
首先,更新 apt 以便我们在下一步安装最新的客户端。
sudo apt-get update
现在,安装 MySQL 客户端。 这会给我们一个 mysql
命令来执行。
sudo apt-get install mysql-client-core-5.6
我们现在准备好使用 MySQL 客户端连接到 MemSQL。 我们将以 root 用户身份连接到端口 3306 上的主机 127.0.0.1
(这是我们的本地主机 IP 地址)。 我们还将自定义提示信息为memsql>
。
mysql -u root -h 127.0.0.1 -P 3306 --prompt="memsql> "
您将看到几行输出,然后是 memsql>
提示符。
让我们列出数据库。
show databases;
你会看到这个输出。
数据库输出
+--------------------+ | Database | +--------------------+ | information_schema | | memsql | | sharding | +--------------------+ 3 rows in set (0.01 sec)
创建一个名为 tutorial 的新数据库。
create database tutorial;
然后通过 use
命令切换到使用新数据库。
use tutorial;
接下来,我们将创建一个 users
表,其中包含 id
和 email
字段。 我们必须为这两个字段指定一个类型。 让我们将 id 设为 bigint 并通过电子邮件发送一个长度为 255 的 varchar。 我们还将告诉数据库 id
字段是主键,并且 email
字段不能为空。
create table users (id bigint auto_increment primary key, email varchar(255) not null);
您可能会注意到最后一个命令的执行时间很短(15 - 20 秒)。 MemSQL 创建这个新表很慢的一个主要原因是:代码生成。
在底层,MemSQL 使用 代码生成 来执行查询。 这意味着每当遇到一种新类型的查询时,MemSQL 都需要生成和编译代表该查询的代码。 然后将此代码发送到集群以执行。 这加快了处理实际数据的速度,但准备工作需要成本。 MemSQL 尽其所能重用预先生成的查询,但结构从未见过的新查询将减慢速度。
回到我们的 users 表,看看表定义。
describe users;
表定义输出
+-------+--------------+------+------+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+------+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | email | varchar(255) | NO | | NULL | | +-------+--------------+------+------+---------+----------------+ 2 rows in set (0.00 sec)
现在,让我们在 users 表中插入一些示例电子邮件。 此语法与我们可能用于 MySQL 数据库的语法相同。
insert into users (email) values ('one@example.com'), ('two@example.com'), ('three@example.com');
插入电子邮件输出
Query OK, 3 rows affected (1.57 sec) Records: 3 Duplicates: 0 Warnings: 0
现在查询用户表。
select * from users;
可以看到我们刚刚输入的数据:
用户表输出
+----+-------------------+ | id | email | +----+-------------------+ | 2 | two@example.com | | 1 | one@example.com | | 3 | three@example.com | +----+-------------------+ 3 rows in set (0.07 sec)
第 4 步 - 插入和查询 JSON
MemSQL 提供 JSON 类型,因此在这一步中,我们将创建一个事件表来使用传入事件。 该表将有一个 id
字段(就像我们为用户所做的那样)和一个 event
字段,它将是一个 JSON 类型。
create table events (id bigint auto_increment primary key, event json not null);
让我们插入几个事件。 在 JSON 中,我们将引用一个 email
字段,该字段反过来又引用我们在步骤 3 中插入的用户的 ID。
insert into events (event) values ('{"name": "sent email", "email": "one@example.com"}'), ('{"name": "received email", "email": "two@example.com"}');
现在我们可以看看我们刚刚插入的事件。
select * from events;
事件表输出
+----+-----------------------------------------------------+ | id | event | +----+-----------------------------------------------------+ | 2 | {"email":"two@example.com","name":"received email"} | | 1 | {"email":"one@example.com","name":"sent email"} | +----+-----------------------------------------------------+ 2 rows in set (3.46 sec)
接下来,我们可以查询 JSON name
属性为文本“received email”的所有事件。
select * from events where event::$name = 'received email';
“收到的电子邮件”查询输出
+----+-----------------------------------------------------+ | id | event | +----+-----------------------------------------------------+ | 2 | {"email":"two@example.com","name":"received email"} | +----+-----------------------------------------------------+ 1 row in set (5.84 sec)
尝试更改该查询以查找 name
属性为文本“已发送电子邮件”的那些。
select * from events where event::$name = 'sent email';
“已发送电子邮件”查询输出
+----+-------------------------------------------------+ | id | event | +----+-------------------------------------------------+ | 1 | {"email":"one@example.com","name":"sent email"} | +----+-------------------------------------------------+ 1 row in set (0.00 sec)
这个最新查询的运行速度比前一个查询快得多。 这是因为我们只更改了查询中的一个参数,所以 MemSQL 能够跳过代码生成。
让我们为分布式 SQL 数据库做一些高级的事情:让我们在非主键上连接两个表,其中一个连接值嵌套在 JSON 值中,但过滤不同的 JSON 值。
首先,我们将要求用户表的所有字段与事件表通过匹配的电子邮件连接,其中事件名称为“received email”。
select * from users left join events on users.email = events.event::$email where events.event::$name = 'received email';
“收到的电子邮件”字段输出
+----+-----------------+------+-----------------------------------------------------+ | id | email | id | event | +----+-----------------+------+-----------------------------------------------------+ | 2 | two@example.com | 2 | {"email":"two@example.com","name":"received email"} | +----+-----------------+------+-----------------------------------------------------+ 1 row in set (14.19 sec)
接下来,尝试相同的查询,但过滤为仅“已发送电子邮件”事件。
select * from users left join events on users.email = events.event::$email where events.event::$name = 'sent email';
“已发送电子邮件”字段输出
+----+-----------------+------+-------------------------------------------------+ | id | email | id | event | +----+-----------------+------+-------------------------------------------------+ | 1 | one@example.com | 1 | {"email":"one@example.com","name":"sent email"} | +----+-----------------+------+-------------------------------------------------+ 1 row in set (0.01 sec)
和以前一样,第二个查询比第一个快得多。 正如我们在基准测试中看到的那样,代码生成的好处在执行数百万行时会得到回报。 使用理解 JSON 以及如何任意跨表连接的横向扩展 SQL 数据库的灵活性是一项强大的用户功能。
结论
您已经安装了 MemSQL,运行了节点性能基准测试,通过标准 MySQL 客户端与节点交互,并使用了 MySQL 中没有的一些高级功能。 这应该是对内存中 SQL 数据库可以为您做什么的一个很好的体验。
关于 MemSQL 如何实际分发数据、如何构建表以获得最大性能、如何跨多个节点扩展 MemSQL、如何复制数据以实现高可用性以及如何保护 MemSQL,还有很多东西需要学习。