Apache Ignite 介紹
Ignite是什么呢?先引用一段官網關於Ignite的描述:
Ignite is memory-centric distributed database, caching, and processing platform for transactional, analytical, and streaming workloads delivering in-memory speeds at petabyte scale
直接翻譯就是,Ignite是以內存為中心的分布式的數據庫,緩存和處理平台。它可以在數據量達到PB級別,依然為事務性處理,數據分析和流式任務提供了內存級的操作速度。 再從官網借用一張架構圖,從下面這張圖也可以看出來Ignite提供了哪些能力:
圖中紅色部分屬於Ignite提供的組件,我們依次從下往上看:
- 持久化層:Ignite同時支持原生持久化和用第三方存儲做持久化,比如RMDBMS,HDFS等。雖然Ignite有以內存為中心的存儲,但是畢竟內存中數據在節點出現故障的時候都有丟失的可能性。 因此持久化層為Ignite提供了故障恢復的能力。另外有了持久化能力,可以讓冷熱數據更合理使用內存。比如在內存足夠情況下,數據可以全部加載到內存中。 而當內存緊張時,可以只加載熱數據至內存中,冷數據就留在硬盤上。
- Ignite內存存儲層:這一層可以算是Ignite的核心層了。數據可以通過不同分區,復制模式分布在Ignite集群所有節點,部分節點或者本地節點。通過數據分區和復制,比如1主多備的方式,可以提高數據的可用性,即便主數據節點故障后,集群中的備數據節點可以切換為主節點繼續提供讀寫服務。 同時備節點也可以作為只讀節點使用,提高數據讀操作的吞吐量。Ignite還利用Java堆外內存存儲數據和索引,減少了JVM的垃圾回收次數和時間,提供了更高效的操作。
- API接口層: 豐富多樣的接口支撐Ignite向上提供了諸如分布式數據庫,數據網格和計算網格的能力。Key/Value+transaction,可以把Ignite當做和Redis,Memcached一樣的緩存使用。 而對SQL ANSI-99的兼容,有可以把Ignite當做一個分布式數據庫來用。 除了數據能力,Ignite還允許你通過Compute Grid的接口提交計算任務,充分利用集群的計算資源。Ignite還支持把計算任務部署在和計算數據所在的相同節點上,減少網絡傳輸和數據的序列化開銷,提高計算效率。 流處理,機器學習網格,服務網格,消息隊列等,Ignite也同時提供支持。
以上只是簡單羅列了目前我所了解的Ignite的特性,如果還想了解更多關於Ignite基本概念和資料,可以參閱官方文檔, 英文不好的同學可以看看李玉珏翻譯的中文官方文檔。 光從文檔量上看,Ignite的特性相當繁雜,而且有些例子還是需要實際跑跑代碼才能弄清楚如何使用,后面我會根據自己的學習進度,更新Ignite的學習筆記,把自己對Ignite的理解和小伙伴分享。
Ignite 集群安裝部署和啟動
Ignite有多種安裝方式,比如源碼安裝,docker,RPM包等,個人認為二進制包的安裝方式最簡單,開箱即用。下面我們看看如何通過二級制包來安裝部署Ignite。
1.首先我們需要從官網下載二進制壓縮包。在我寫這篇博客時候,最新版本為2.6.0。
2.下載后我們需要解壓縮二進制包,然后設置好環境變量IGNITE_HOME,指向剛剛解壓好的目錄。
3.然后我們可以通過IGNITE_HOME/bin/ignite.sh腳本啟動我們的第一個Ignite節點:
$cd IGNITE_HOME
$bin/ignite.sh
4.節點啟動過程,會在終端上打印日志信息,當看到下面類似日志時就代表節點啟動成功了:
[23:41:41] Ignite node started OK (id=e935ab3a)
[23:41:41] Topology snapshot [ver=1, servers=1, clients=0, CPUs=2, offheap=1.6GB, heap=1.0GB]
我們先來簡單看看最后那一行日志都提供了哪些信息:
- “ver=1”代表Ignite集群topology版本是1。關於什么是topology,我會在介紹Ignite原生持久化能力的時候討論到。
- “servers=1”代表現在集群里面就一個server節點,“clients=0”代表集群里沒有client節點。 client/server節點在作為數據節點和計算節點時時有區別的,我會在后面介紹。現在可以簡單的理解為server節點總是存放數據,client節點不存放數據,數據的訪問總是通過server節點。
- “CPUs=2”代表當前節點的CPU數量。
- “offheap=1.6GB”代表當前節點可以使用的Java堆外內存是1.6GB。堆外內存是個很重要的概念,我會在介紹Ignite內存架構的時候再詳細解釋Ignite是如何使用堆外內存。現在只要記住Ignite用堆外用來存儲數據和索引來減少GC。默認配置下Ignite能使用的堆外內存為節點內存大小的20%。我啟動Ignite的虛擬機只有8G內存,因此堆外內存為8GB*20%=1.6GB。
- “heap=1.0GB”這個就是Ignite能使用的Java堆內存了。這個值的大小也是可以調整的,如果你沒有配置JAVA_OPTS,在ignite.sh腳本中啟動JVM時用的最小/最大堆都是1GB。
就是這么簡單,開箱即用。 到目前為止我們已經成功在一個節點上啟動了一個Ignite實例。我們還可以在同一個節點上或者多個節點上用相同的辦法啟動多個Ignite實例。在新的Ignite實例啟動后,新老節點會互相發現自動的形成一個集群。比如我在相同的虛擬機上在啟動一個實例,在第一個和第二個實例的日志中有這么一行:
[00:24:27] Topology snapshot [ver=2, servers=2, clients=0, CPUs=2, offheap=3.1GB, heap=2.0GB]
細心的小伙伴應該會發現ver, servers, offheap, heap值都改變了,這說明Ignite集群加入了新的節點,所以topology的版本號變了,集群內server數量也變成2。
Ignite REST和SQL客戶端
server節點啟動后,我們就可以用客戶端連接上進行操作了。 目前Ignite支持的客戶端有REST, SQL, Java/.NET客戶端。 其中Java/.NET客戶端都需要自己寫代碼連接到服務器上,所以這里我們先介紹使用REST和SQL客戶端,下一篇文章再分享如何寫一個簡單的Java程序連接Ignite server節點。
REST 客戶端使用
注意: 為了啟用REST連接,必須保證ignite-rest-http模塊在啟動JVM的classpath中。 如果你下載了二進制包,可以在$IGNITE_HOME/libs/optional中找到ignite-rest-http模塊,只要將它拷貝到$IGNITE_HOME/libs目錄中就可以了。
Ignite啟動后,默認會自動監聽8080端口,我們就可以通過以下curl命令查看server節點版本(192.168.0.110是我的Ignite server節點啟動的ip地址):
$curl 'http://192.168.0.110:8080/ignite?cmd=version'
{"successStatus":0,"sessionToken":null,"error":null,"response":"2.6.0"}
目前我們的Ignite集群里沒有任何的cache,讓我們試着用REST命令創建一個新的cache:
$curl 'http://192.168.0.110:8080/ignite?cmd=getorcreate&cacheName=myfirstcache'
{"successStatus":0,"sessionToken":null,"error":null,"response":null}
然后我們就可以往這個cache里添加數據了:
$curl 'http://192.168.0.110:8080/ignite?cmd=put&key=Toronto&val=Ontario&cacheName=myfirstcache'
{"successStatus":0,"affinityNodeId":"370c1554-03f4-4fa2-9c45-880e40288467","sessionToken":null,"error":null,"response":true}
$curl 'http://192.168.0.110:8080/ignite?cmd=put&key=Edmonton&val=Alberta&cacheName=myfirstcache'
{"successStatus":0,"affinityNodeId":"370c1554-03f4-4fa2-9c45-880e40288467","sessionToken":null,"error":null,"response":true}
我們往cache里寫了兩條關於加拿大城市和所在省份的數據,第一條key是Toronto市,value值是Ontario省。 第二條key是Edmonton市,value值是Alberta省。 然后再讓我們試着讀取cache里的數據:
$curl 'http://192.168.0.110:8080/ignite?cmd=get&key=Toronto&cacheName=myfirstcache'
{"successStatus":0,"affinityNodeId":"370c1554-03f4-4fa2-9c45-880e40288467","sessionToken":null,"error":null,"response":"Ontario"}
$curl 'http://192.168.0.110:8080/ignite?cmd=get&key=Edmonton&cacheName=myfirstcache'
{"successStatus":0,"affinityNodeId":"370c1554-03f4-4fa2-9c45-880e40288467","sessionToken":null,"error":null,"response":"Alberta"}
$curl 'http://192.168.0.110:8080/ignite?cmd=get&key=Ottawa&cacheName=myfirstcache'
{"successStatus":0,"affinityNodeId":"370c1554-03f4-4fa2-9c45-880e40288467","sessionToken":null,"error":null,"response":null}
當我們查詢Toronto和Edmonton時,返回的省份名稱和我們之前寫入的一樣。 當我們查詢Ottawa時,因為我們的cache沒有這組數據,所以返回值是null。
或許有小伙伴已經注意到默認情況下REST API會把key/value當做String來處理,包括存儲在集群里的格式也是String。 當然在用put/get命令的時候也你可以用keyType/valueType將key/value其他Ignite支持的類型,比如整型,布爾型,浮點型,日期等類型,但這些類型也僅限於Java內置類型。 如果你想通過REST API來存儲一個復雜對象,可能就需要你自己先把對象序列化為一個string,然后讀取的時候再反序列化回一個對象。 所以個人覺得REST API還不能發揮出Ignite全部的實力,只能支持一些簡單的緩存使用場景,對復雜的操作可能還是SQL或者用代碼更方便。
更多的REST API和具體的使用參數可以查看官方的REST API文檔。
SQL 客戶端使用
還記得在官方介紹Ignite的描述中,把Ignite描述為一個以內存為中心的分布式數據,同時Ignite兼容SQL ANSI-99標准,所以可以像使用一個數據庫一樣使用Ignite,這個特性倒是目前其他內存緩存所不具備的。
我們可以使用DBeaver工具像連接其他數據庫一樣連接Ignite。按照官方文檔配置完JDBC驅動用到的類,URL連接模板,端口號以及需要使用到的Ignite的jar包,就可以連接到Ignite上了。這個時候Ignite集群里還沒有任何數據,所以在DBeaver里是看不到任何表的:
現在讓我們用SQL語句創建兩張表,在執行完SQL語句后,在左邊的Tables選項下就可以看見剛剛創建的兩張表了,點開任意一張表,我們就可以在Dbeaver里看到表的schema定義了。:
然后我們在對這兩張表用省的名字和市的名字分別建立索引:
同樣,在執行完SQL語句后,我們就在indexes選項下看到新建的表索引了。接着,我們可以往表格里插入一些數據,並做簡單的查詢:
對就是這么簡單,和使用其他的數據庫沒什么區別。而且如果你的Ignite集群包含多個節點,Ignite已經根據你建表時的配置(注意我們在建表的時候with之后有諸如template=replicated, backup=1,affinityKey=province_id關鍵字,這些配置會在后面進行介紹),自動幫你把表數據復制到不同的節點上去了,你不用關心你的數據是如何分布的,一切就交給Ignite做管理吧,即便是有些節點發生故障,也不用擔心數據會丟失。
除了Dbeaver外,Ignite也自帶了一個SQL命令行工具,叫做SQLLine,也可以用來連接Ignite執行SQL語句。在$IGNITE_HOME/bin下可以找到這個工具,使用下面的命令啟動SQLLine並連接到Ignite集群中:
$cd $IGNITE_HOME/bin
$./sqlline.sh --verbose=true -u jdbc:ignite:thin://192.168.0.110/
連接成功后,我們可以查看Ignite中所有的表(!tables),表結構(!columns),還可以用SQL語句修改/查詢數據(!sql SQL Statement):
0: jdbc:ignite:thin://192.168.0.110/> !tables
+--------------------------------+--------------------------------+--------------------------------+--------------------------------+--+
| TABLE_CAT | TABLE_SCHEM | TABLE_NAME | TABLE_TYPE | |
+--------------------------------+--------------------------------+--------------------------------+--------------------------------+--+
| | PUBLIC | CITY | TABLE | |
| | PUBLIC | PROVINCE | TABLE | |
+--------------------------------+--------------------------------+--------------------------------+--------------------------------+--+
0: jdbc:ignite:thin://192.168.0.110/> !columns
+--------------------------------+--------------------------------+--------------------------------+--------------------------------+--+
| TABLE_CAT | TABLE_SCHEM | TABLE_NAME | COLUMN_NAME | |
+--------------------------------+--------------------------------+--------------------------------+--------------------------------+--+
| | PUBLIC | CITY | ID | |
| | PUBLIC | CITY | NAME | |
| | PUBLIC | CITY | PROVINCE_ID | |
| | PUBLIC | PROVINCE | ID | |
| | PUBLIC | PROVINCE | NAME | |
+--------------------------------+--------------------------------+--------------------------------+--------------------------------+--+
0: jdbc:ignite:thin://192.168.0.110/> !sql SELECT p.name, c.name FROM PROVINCE p, CITY c WHERE p.id=c.province_id;
+--------------------------------+--------------------------------+
| NAME | NAME |
+--------------------------------+--------------------------------+
| Alberta | Edmonton |
| Alberta | Calgary |
| Ontario | Toronto |
| Quebec | Montreal |
+--------------------------------+--------------------------------+
更多SQLLine使用的方法和命令,可以看這里。
Ignite Visor 命令行工具
在啟動了Ignite集群后,Ignite也提供了一個簡單的命令行工具,Visor Command Line Interface,通過這個工具可以查詢集群的狀態,檢測緩存的使用情況,控制節點等。同樣,在$IGNITE_HOME/bin下可以找到Visor命令行工具並啟動:
$cd $IGNITE_HOME/bin
$ ./ignitevisorcmd.sh
...
ADMIN CONSOLE
2018 Copyright(C) Apache Software Foundation
+-------------------------------------+
| Status | Disconnected |
| Ignite instance name | <n/a> |
| Config path | <n/a> |
| Uptime | <n/a> |
+-------------------------------------+
Type 'help' for more information.
Type 'open' to join the grid.
Type 'quit' to quit form Visor console.
visor> open
啟動成功后, 再通過open命令連接到當前使用的Ignite集群上,我們就可以查詢集群的topology信息:
visor> top
Hosts: 1
+=========================================================================================================================+
| Int./Ext. IPs | Node ID8(@) | Node Type | OS | CPUs | MACs | CPU Load |
+=========================================================================================================================+
| 0:0:0:0:0:0:0:1%lo | 1: 134F0292(@n0) | Server | Linux amd64 3.13.0-32-generic | 2 | 08:00:27:8F:07:76 | 10.17 % |
| 127.0.0.1 | 2: B677DAF2(@n1) | Server | | | | |
| 192.168.0.110 | | | | | | |
+-------------------------------------------------------------------------------------------------------------------------+
Summary:
+--------------------------------------+
| Active | true |
| Total hosts | 1 |
| Total nodes | 2 |
| Total CPUs | 2 |
| Avg. CPU load | 10.17 % |
| Avg. free heap | 81.00 % |
| Avg. Up time | 00:28:14 |
| Snapshot time | 2018-10-11 00:52:24 |
+--------------------------------------+
從上面的輸出可以看到,目前我的集群里有1台主機,2個Ignite server節點,這兩個節點都跑在同一台機器上的。我們還可以查看下目前集群里的緩存數據:
visor> cache
Time of the snapshot: 2018-10-11 01:04:59
+============================================================================================================================+
| Name(@) | Mode | Nodes | Entries (Heap / Off-heap) | Hits | Misses | Reads | Writes |
+============================================================================================================================+
| myfirstcache(@c0) | PARTITIONED | 2 | min: 1 (0 / 1) | min: 0 | min: 0 | min: 0 | min: 0 |
| | | | avg: 1.00 (0.00 / 1.00) | avg: 0.00 | avg: 0.00 | avg: 0.00 | avg: 0.00 |
| | | | max: 1 (0 / 1) | max: 0 | max: 0 | max: 0 | max: 0 |
+--------------------------+-------------+-------+---------------------------+-----------+-----------+-----------+-----------+
| SQL_PUBLIC_CITY(@c1) | PARTITIONED | 2 | min: 2 (0 / 2) | min: 0 | min: 0 | min: 0 | min: 0 |
| | | | avg: 2.00 (0.00 / 2.00) | avg: 0.00 | avg: 0.00 | avg: 0.00 | avg: 0.00 |
| | | | max: 2 (0 / 2) | max: 0 | max: 0 | max: 0 | max: 0 |
+--------------------------+-------------+-------+---------------------------+-----------+-----------+-----------+-----------+
| SQL_PUBLIC_PROVINCE(@c2) | REPLICATED | 2 | min: 1 (0 / 1) | min: 0 | min: 0 | min: 0 | min: 0 |
| | | | avg: 1.50 (0.00 / 1.50) | avg: 0.00 | avg: 0.00 | avg: 0.00 | avg: 0.00 |
| | | | max: 2 (0 / 2) | max: 0 | max: 0 | max: 0 | max: 0 |
+----------------------------------------------------------------------------------------------------------------------------+
可以看到目前我們集群里面有3個緩存,一個是我們通過REST API建立的myfirstcache緩存,剩下兩個是我們在DBeaver里面創建的兩張數據庫表。同時我們還可以看到每個緩存的統計信息,比如緩存是REPLICATED還是PARTITIONED模式,緩存中有多少條目,讀寫次數,命中率等。
Visor的命令行工具就簡單介紹到這, 更多命令的使用說明通過"help CMD" 或者 “? CMD”命令輸出命令的幫助文檔供查閱。
總結
- 簡單的介紹了Apache Ignite的特性,Ignite可以當做緩存使用,也可以當做分布式數據庫使用,還可以用來做計算節點和服務網格等。詳細的特性介紹會在隨后的文章詳細展開。
- Ignite的二進制包安裝十分簡單,一個命令就可以用默認的配置啟動一個Ignite實例,屬於開箱即用。
- Ignite支持REST, SQL, Java/.NET客戶端連接。使用REST, SQL客戶端(Dbeaver和SQLLine),可以不用寫一行代碼快速體驗Ignite的緩存和分布式數據庫能力。
- Ignite自帶的Visor Command Line Interface提供了基本的集群查詢/管理能力。
下一篇,讓我們看看如何寫Java代碼來連接Ignite集群,並解鎖更多Ignite的特性。