Related Posts Plugin for WordPress, Blogger...

[2014JDD]從 SQL 與 Java 為出發點的 NewSQL Database:VoltDB

2014 Java Developer Day 講師 - 陳貽文 EvenChen 2014/08/01(五) 2014 Java Developer Day Taiwan,這是我第一次在 JDD 擔任講師,講題 "從 SQL 與 Java 為出發點的 NewSQL Database:VoltDB",當天精神不是很好,加上吃藥副作用會非常口渴,多喝水又怕跑廁所,所以整個議程可能會有些詞句不順暢,好在還算準時把該講的講完,畢竟當學員時就認為準時、禮物發完是講師的基本道義,希望來參與的人還能接受,也有得到想要的資訊,當然一次議程是不可能把 VoltDB 介紹得很清楚,更何況表訂只有四十五分鐘的時間,其實已經簡化相當多的內容了,要說簡介可能都嫌不足,趁著記憶還新把當天講稿整理做補充。

其實沒想到來的人有這麼多,因為同時段都是權威講師,就如同開場時的玩笑:該不會是因為這間會議室座位是最舒服的所以選這個議程吧!相信是對傳統關聯式資料庫效能有所需求,但是又對 NoSQL 徹頭徹尾毀滅式的砍掉重練有跨越的門檻,沒有錯!NewSQL 這一派就是認為傳統關聯式資料庫太慢了,但也認為 NoSQL 顛覆得太過偏頗,事實上 NoSQL 陣營也普遍的加入 SQL 功能的支援了,定義也修改為 "Not Only SQL"。

NewSQL 最早是由 The 451 Group 所提出的,原文:NewSQL databases designed to meet scalability requirements of distributed architectures or to improve performance such that horizontal scalability is no longer a necessity, including new MySQL storage engines, transparent sharding technologies, software and hardware appliances, and completely new databases;目前 NewSQL 參考文獻在台灣並不多,投影片有節錄某本書整理的要點,但並不是很好,定義也被擴大解釋、解讀好幾回了,很難再去追究或者釐清什麼是 NewSQL,總結來說 NewSQL 普遍特性就是:性能好、可橫向擴充、傳統的一些包袱可以斟酌改良或拋棄,在 SQL 與 NoSQL 間取捨的新型態資料庫。(維基百科:NewSQL

The 451 Group 的 DB 分類表(著名的 MySQL Cluster、本文介紹的 VoltDB):
資料庫分類表(Relational、Non-Relational、NoSQL、NewSQL)

In-Memory Database 其實就是把記憶體當作儲存媒體的資料庫,資料放在記憶體中,讀、寫、搜尋以及反應速度都很快(相較於傳統硬碟保守估算高出數十倍以上),但斷電資料就會遺失,而這也不是什麼新技術,MySQL 有 memoey storage engine、SQLite 有 In-memory mode、微軟 SQL Server Compact 也有相關應用…等。

VoltDB 主要的創辦人 Michael Stonebraker 同時也是 PostgreSQL 之父,這意謂者 VoltDB 也會有不錯的 SQL 支援能力及程度,畢竟 PostgreSQL 已經有公司以此為基底,改寫成 Hadoop 版本推出解決方案,此外,VoltDB 還有很多很好的設計,像是針對多核心處理器優化、In-memory database 資料都在記憶體中無須緩衝管理、只保留 command logging、所有程序在記憶體中循序執行免除 Lock、Latch 的必要。

系統需求
作業系統 64-bit Linux
CPU 雙核心、x86_64、1.6GHz
RAM 4GB
Java Java 7 or 8(OracleJDK、OpenJDK)
必要軟體 NTP
Python 2.5 or later release of 2.x
建議軟體 Eclipse 3.x (or other Java IDE)
這是指最低需求,CentOS 6.3, RHEL 6.3, and Ubuntu 10.4 and 12.4 是主要官方支援的,其他 Linux 甚至 Macintosh OS X 10.7 也有安裝包以及通過 VoltDB 測試,OS、CPU、RAM 三項應該一起看,限制乃自於 In-memory DB 的關係,六十四位元才足以定址夠大的記憶體,JDK 部份才說 VoltDB 追隨得不錯,從年初 Java 6 進階到 Java 7,沒想到現在查看又增加 Java 8;必要軟體 NTP 網路校時協定,是為了確保 Cluster 中多台機器時間一致(單機器執行非必須),Python 是很多指令都是由 Python 以 Script 方式寫的,比較令人匪夷所思的是 Java IDE,身為 Java Developer 看到 eclipse 總是有股莫名的安心感,但 database 為什麼需要 Java IDE 呢?

因為 JDBC、ODBC 這類通訊協定也被認為是拖慢 Database 的兇手之一,早期的 VoltDB 版本是只支援 Java Stored Procedure 存取的,也就是要用 Java 寫 Code 去 Access VoltDB,之後支援 JDBC Ad hoc queries,但在 2.0~3.0 版本那段時間,曾經特別諮詢原廠,基本上還是非常不建議使用 Ad hoc 的方式訪問,但 VoltDB 也從善如流,在 4.0 Release note 已經看到這部份已經被最佳化了。

安裝方面應該沒有什麼問題,官方提供 deb 與 rpm 安裝包,大部分常見的 Linux 環境都有支援,參考官方安裝文件應該可以輕鬆過關
$ sudo apt-get install openjdk-7-jdk
$ sudo dpkg -i voltdb_4.0.2-1_amd64.deb
但是以上方式為 Enterprise 版本限定,Open Source 的 community 版本就只能到 GitHub 下載 Source code 自行 Build,使用 Ant 1.7 以上版本就可 Build 好在 Ant 也是 Java 好朋友,實際 Build 過一次沒有什麼大問題。
$ ant dist

下載的部份須先填寫註冊表,然後 VoltDB.com 會把下載位置 email 寄出,這沒什麼奇怪的,不會寫程式也輕易能使用這個功能,但是有趣的是…怎麼會自動修正英文名字呢?(Even 是我個人特別選用的名字,Evan 才是常見常用的英文名)顯然是真人,不是掛機
image image

Start DB 也是關卡之一,跟一般 DB 不同的是,VoltDB 需先準備好 Table Schema 用 DDL 存成文字檔案,透果 voltdb 指令 compile 成 jar 檔
$ voltdb compile towns.sql
或
$ voltdb compile -o towns.jar towns.sql
之後才可用 voltdb 的 create 指令啟 DB
$ voltdb create towns.jar
這也意味著 VoltDB 啟動後,不能更改 Table 也就是不支援 ALERT 指令,需要更改 Table 就必須先把 DB 關閉,是一個很大的限制。

SQLCmd 支援標準的 SQL Statements & Functions
$ sqlcmd
SQL Command :: localhost:21212

1> insert into towns values ('Billerica','Middlesex','MA');
2> insert into towns values ('Buffalo','Erie','NY');
3> insert into towns values ('Bay View','Erie','OH');

4> select count(*) as total from towns;
TOTAL 
------
     3

(1 row(s) affected)
5> select town, state from towns ORDER BY town;
TOWN         STATE 
------------ ------
Bay Village  OH    
Billerica    MA    
Buffalo      NY    

(3 row(s) affected)

Stored Procedure 之前有提到是官方推薦的 data access 方法,以下用簡單例子說明:
import org.voltdb.*; //1

public class LeastPopulated extends VoltProcedure {  //2

  public final SQLStmt getLeast = new SQLStmt(
      " SELECT TOP 1 county, abbreviation, population "
    + " FROM people, states WHERE people.state_num=?"
    + " AND people.state_num=states.state_num"
    + " ORDER BY population ASC;" ); //3

  public VoltTable[] run(integer state_num)  //4
      throws VoltAbortException {

          voltQueueSQL( getLeast, state_num );  //5
          return voltExecuteSQL();  //6

      }
}
1: Import VoltDB 的 Library
2: Extend VoltProcedure 類別
3: 要執行的 SQL
4: Implements run 這個 method
5: 呼叫 voltQueueSQL 這個 method
6: 執行所有命令並且回傳結果

使用 JDBC 就沒有太特殊,重點就是
Class Name
org.voltdb.jdbc.Driver
URL
jdbc:voltdb://{server}:{port}
跟其他 DB 提供的範例不會差異太大:
import java.sql.*;
import java.io.*;

public class JdbcDemo {

    public static void main(String[] args) {
 
        String driver = "org.voltdb.jdbc.Driver";
        String url = "jdbc:voltdb://localhost:21212";
        String sql = "SELECT dialect FROM helloworld";
        
        try {
            // Load driver. Create connection.
            Class.forName(driver);
            Connection conn = DriverManager.getConnection(url);
            
            // create a statement
            Statement query = conn.createStatement();
            ResultSet results = query.executeQuery(sql);
            while (results.next()) {
                System.out.println("Language is " + results.getString(1));
            }
            
            // call a stored procedure
            CallableStatement proc = conn.prepareCall("{call Select(?)}");
            proc.setString(1, "French");
            results = proc.executeQuery();
            while (results.next()) {
                System.out.printf("%s, %s!\n", results.getString(1), 
                                               results.getString(2));
            }
            
            //Close statements, connections, etc.
            query.close(); 
            proc.close();
            results.close();
            conn.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Scaling 擴充的部份也是 VoltDB 的亮點之一,相較於 MySQL Cluster 來說算相當容易,在 Start DB command:voltdb create 帶入 deployment 設定檔
voltdb create \
host voltsvr1 \
catalog mycatalog.jar \
deployment deployment.xml
deployment.xml 內容也相當容易理解,主要設定 Scale、HA、安全係數…等,詳細設定可參考官方附件
<?xml version="1.0"?>
<deployment>
   <cluster hostcount="6" sitesperhost="4" kfactor="2" />
</deployment>
其中 kfactor 也就是 VoltDB 的安全機制 K-Safety,K值表示 "額外" 有幾組資料備份,公式:
Unique partitions = (nodes * partitions/node) / (K + 1)
以上面 deployment.xml 為範例:
6 個節點、每個節點有 4 個 partitions、k-safety等級2
(6 * 4) / (2 + 1) = 8 個 Unique partitions,另外 16 個 partitions 作為備份,以圖例來看:
※ k=2:
  • Unique partitions:A、B、C、D、E、F、G、H 共 8 個 Unique partitions
    Unique partitions
  • 任 2 個節點同時損毀可保證資料安全
  • 3 個節點同時損毀則不一定,ex: SVR1、SVR2、SVR3,A、B、C、D 同時損毀已無法復原
  • image
※ k=1:
  • Unique partitions:A、B、C、D、E、F、G、H、I、J、K、L 共 12 個 Unique partitions
    Unique partitions
  • 任 1 個節點同時損毀可保證資料安全
  • 2 個節點同時損毀則不一定,ex: SVR1、SVR4,A、B、C、D 同時損毀已無法復原
    image
Scaling 效能可參考官方報告 Scaling with VoltDB: The Clustered Database
Scaling chart chart_6 (1)
無 HA(no high availability specified) High Availability(k-safety factor of 2)

其他可參考資料:
MySQL vs. Oracle vs. VoltDB Comparison - db-engines.com
Popularity ranking of database management systems - db-engines.com
Popularity ranking of relational DBMS - db-engines.com

在議程中有提到,很遺憾的 VoltDB 排名並不好,當時現場玩了一個小遊戲:猜猜八月正好是第一天,排名是下降還是升高,結果連線查詢資料還是停留在七月份的資料,現在統計排名已經出來了,很不幸的…排名下降,沒記錯的話,小禮物正好是送給猜下降的那位學員…囧!

後來有學員來問我,為什麼選擇 VoltDB?
其實 VoltDB 剛推出的時候非常轟動,沒有記錯的話 SAP 也打算導入 VoltDB,並且設定為往後 Roadmap 的重點項目,後來不知道什麼原因,隨後卻採用自家 In-memory DB:SAP HANA,也有可能是誤傳或者眼殘看錯,誤把 SAP In-memory DB 跟 VoltDB 關聯起來了,不論如何 VoltDB 起初是相當被看好這點是毋庸置疑的,加上與各位分享在客戶端的成功案例:把 VoltDB 當作 Cache DB 使用,門檻相當低、效果卻是非常的好,當然若認真考慮把 VoltDB 當作唯一、主要 DB 用於系統,縱使目前 DRAM 價格還算低,考量其他因素還是不切實際的夢想,不難看出 VoltDB 設計概念有超跑的味道,光就 K-Safety 機制而言,保留速度犧牲了至少一半的儲存空間,資料完整性還不見得非常安全,就如同早期許多超跑不願意遷就空調犧牲了動力,所以千萬超跑搞笑的只配了電風扇。

為什麼不考慮別家的 NewSQL 或者 In-memory 解決方案?
這邊我要修正一下,費用雖然是很大個考量,但不是唯一的考量,若是費用合理不是不能考慮的選項,畢竟在業界免費的東西還不見得有人敢用,而是有人負責、背書相對代價對等、合理的東西才容易被採用,另類的 CP 值:效能 / 花費 = 代價,那免費、開放原始碼對於用戶而言,除了性價比高外,代價也可能是無限大的;回歸正題,目前除了 MySQL Cluster 外,還真找不到有 In-memory 又有 SQL 且可橫向擴充的解決方案,雖然不乏口號喊得震天響的產品(如:SAP HANA),但又有哪個有比較完整的資訊、實例甚至能拿到手實際測試的呢?或許是敝人資訊貧乏、眼界不夠廣,這也是參加開發者大會的原因之一,歡迎更多人來測試、挑戰外,有更好的建議、構想也提出來跟大家分享(應該可以發現我這次跳出來是沒有拿任何廠商贊助,甚至公司名稱我都沒說,純粹是出來拋磚引玉的)。
張貼留言