1. 程式人生 > >MySQL Cluster 初用初測小結

MySQL Cluster 初用初測小結

基於上篇搭建的環境,驗證一些基本功能和效能需求。這裡先說一下功能使用的問題。OneCoder也是第一次用。摸索著來,僅做一個記錄。

從部署圖就可知道,對資料庫的請求操作發生在SQL節點上。為了達到試驗效果,這裡又追加了一個sql節點。現在叢集環境如下:

在追加的過程中,發現MySQL Cluster對啟動順序要求嚴格,在沒考慮熱部署方案的情況下,必須停止了所有節點,重新按照management->data->sql的順序啟動節點。

現在測試對錶的建立和修改的自動同步:

在任意SQL節點執行:(這裡選擇44.200節點)

create table bigdata_cluster(id int primary key, name varchar(20)) engine=ndbcluster default charset utf8;

建立表,注意表的引擎一定要指定ndbcluster,在201節點檢視

show tables;

發現已經可以同步查詢了。其實本來底層data節點對上層就是透明的,自然可以查到。多sql節點,就可以起到負載均衡的效果。

調整表和資料插入,都跟傳統的MySQL方式相同,不再贅述,同樣也是可以做到實時同步的,這裡也測過了。下面通過JDBC程式碼測試下API操作的效果,同時也想灌入100w的資料,進行一下效率測試和對比。

在測試前,OneCoder先用SQLyog工具,測試了一下資料庫遠端訪問許可權,發現果然沒有。在一個節點grant all了一下以後,卻發現另一個節點仍然無法訪問,搜尋才知,原來MySQL Cluster的使用者許可權預設不是共享的,進行如下設定,在mysql終端執行:

mysql> SOURCE /usr/local/mysql/share/ndb_dist_priv.sql;
mysql> CALL mysql.mysql_cluster_move_privileges();

即可完成許可權共享,現在在一個終端設定的許可權就是叢集共享的了。在用SQLYog測試,果然均可以連結了。下面開始開發JDBC連結MySQL的程式碼:</p>

/**
  * 向資料庫中插入資料
  *
  * @param conn
  * @param totalRowCount
  * @param perRowCount
  * @param tableName
  * @author lihzh(OneCoder)
  * @throws SQLException
  * @date 2013-1-17 下午1:57:10
  */
private void insertDataToTable(Connection conn, String tableName, long totalRowCount, long perRowCount) throws SQLException { conn.setAutoCommit(false); long start = System.currentTimeMillis(); String sql = "insert into " + tableName + " VALUES(?,?,?)"; System.out.println("Begin to prepare statement."); PreparedStatement statement = conn.prepareStatement(sql); for (int j = 0; j < TOTAL_ROW_COUNT / BATCH_ROW_COUNT; j++) { long batchStart = System.currentTimeMillis(); for (int i = 0; i < BATCH_ROW_COUNT; i++) { long id = j * BATCH_ROW_COUNT + i; String name_pre = String.valueOf(id); statement.setLong(1, id); statement.setString(2, name_pre); statement.setString(3, name_pre); statement.addBatch(); } System.out.println("It's up to batch count: " + BATCH_ROW_COUNT); statement.executeBatch(); conn.commit(); long batchEnd = System.currentTimeMillis(); System.out.println("Batch data commit finished. Time cost: " + (batchEnd - batchStart)); } long end = System.currentTimeMillis(); System.out.println("All data insert finished. Total time cost: " + (end - start)); }

開始設定BATCH_ROW_COUNT為5w,結果報錯:

java.sql.BatchUpdateException: Got temporary error 233 'Out of operation records in transaction coordinator (increase MaxNoOfConcurrentOperations)' from NDBCLUSTER

意思比較明顯,超過了MaxNoOfConcurrentOperations設定的值。該值預設為:32768。你可以通過修改config.ini裡的配置改變預設值。不過有人提到,修改該值的同事,你也需要修改

MaxNoOfLocalOperations的值,並且建議後者的值超過前者值10%左右(1.1倍)。

這裡為了避免麻煩,我們直接將程式碼的裡預設值調小到2w,再執行程式碼。

Begin to prepare statement.
It's up to batch count: 20000
Batch data commit finished. Time cost: 20483
It's up to batch count: 20000
Batch data commit finished. Time cost: 19768
It's up to batch count: 20000
Batch data commit finished. Time cost: 20136
It's up to batch count: 20000
Batch data commit finished. Time cost: 19958
…….
java.sql.BatchUpdateException: The table 'bigdata_cluster' is full

無語……表滿了。共寫入了88w條資料。每次batch寫入時間穩定。再測試條件查詢耗時:

/**
  * 查詢特定的一個或者一組資料,列印查詢耗時
  *
  * @param conn
  * @param tableName
  * @author lihzh
  * @throws SQLException
  * @date 2013-1-17 下午4:46:20
  */
private void searchData(Connection conn, String tableName) throws SQLException {
long start = System.currentTimeMillis();
String sql = "select * from " + tableName + " where name = ?";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setString(1, "300");
ResultSet resultSet = statement.executeQuery();
resultSet.first();
System.out.println("Name is: " + resultSet.getObject("name"));
long end = System.currentTimeMillis();
System.out.println("Query one row from 88w record cost time: " + (end - start));
}

通過另一個sql節點,根據沒有索引的name欄位查詢耗時約1.4s,有索引的id查詢耗時20ms左右。

再新建一個表,發現什麼資料再也無法寫入,看來是資料節點全域性容量限制導致的。修改config.ini檔案中的

DataMemory=80M    # How much memory to allocate for data storage
IndexMemory=18M   # How much memory to allocate for index storage
                  # For DataMemory and IndexMemory, we have used the
                  # default values. Since the "world" database takes up
                  # only about 500KB, this should be more than enough for
                  # this example Cluster setup.

分別改為1400和384M。重啟叢集。再通過

ndb_mgm> all report memoryusage

命令檢視使用情況,

似乎恢復了正常。再向新表寫入資料,成功。

測試刪除資料,又遇到提示:

ERROR 1297 (HY000): Got temporary error 233 'Out of operation records in transaction coordinator (increase MaxNoOfConcurrentOperations)' from NDBCLUSTER

看來真的得調整MaxNoOfConcurrentOperations引數的大小了。根據虛擬機器記憶體情況(據說1約需要1kb記憶體。因此10w,大約100m記憶體),調整如下:

MaxNoOfConcurrentOperations=300000
MaxNoOfLocalOperations=330000

重啟,測試刪除11w資料,通過。同時,再次測試向新表寫入100w條資料,以20w為一組,也順利通過了。

It's up to batch count: 200000
Batch data commit finished. Time cost: 268642
It's up to batch count: 200000
Batch data commit finished. Time cost: 241301
It's up to batch count: 200000
Batch data commit finished. Time cost: 209329
It's up to batch count: 200000
Batch data commit finished. Time cost: 207634
It's up to batch count: 200000
Batch data commit finished. Time cost: 241746
All data insert finished. Total time cost: 1168703

目前的使用情況大致如此,接下來OneCoder打算測試一下叢集節點新增和資料自動分割槽讀寫情況。等有了結論在與大家分享。