作者:小傅哥,博客:https://bugstack.cn
本文的宗旨在于通過簡單干凈實踐的方式,向讀者介紹一款基于內(nèi)存的分布式SQL數(shù)據(jù)庫Apache Ignite的部署、使用和性能測試。
那有了Redis這樣優(yōu)秀的NoSql數(shù)據(jù)庫,為啥還會用到Apache Ignite呢?
不知道你是否有想過一個事情,就是Redis這樣的內(nèi)存數(shù)據(jù)庫,如果能支持SQL語句,是不是就更牛了。這樣一來本身存在MySQL數(shù)據(jù)庫里的數(shù)據(jù),就可以原封不動的封到內(nèi)存中使用。既保留了原有的業(yè)務邏輯,又使用上了內(nèi)存讀取高性能。
所以,它來了。Apache Ignite是一個兼容ANSI-99、水平可擴展以及容錯的分布式SQL數(shù)據(jù)庫,作為一個SQL數(shù)據(jù)庫,Ignite支持所有的DML指令,包括SELECT、UPDATE、INSERT和DELETE,它還實現(xiàn)了一個與分布式系統(tǒng)有關的DDL指令的子集。Ignite的一個突出特性是完全支持分布式的SQL關聯(lián),Ignite支持并置和非并置的數(shù)據(jù)關聯(lián)。并置時,關聯(lián)是在每個節(jié)點的可用數(shù)據(jù)集上執(zhí)行的,而不需要在網(wǎng)絡中移動大量的數(shù)據(jù),這種方式在分布式數(shù)據(jù)庫中提供了最好的擴展性和性能。
本文涉及的工程:
-
- xfg-dev-tech-ignite:https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-ignite-
docs/dev-ops 提供了 mysql、ignite 安裝腳本,和數(shù)據(jù)初始化操作。
-
- 官網(wǎng)站點:https://ignite.apache.org/ -
官網(wǎng) docs 可以閱讀安裝和使用
-
- 中文文檔:https://ignite-service.cn/doc/2.7.0/sql/ -
這是一個 Ignite 的中文站點
-
- 管理工具:DBeaver -
安裝最新版,直接可以連接 Ignite 數(shù)據(jù)庫
一、案例說明
本案例中為了對比MySQL和Ignite的性能差異,以及如何同時使用兩套數(shù)據(jù)庫,這里小傅哥會在一個工程中分別配置出不同的數(shù)據(jù)庫對應數(shù)據(jù)源的創(chuàng)建和MyBatis的配置用。如果說你做過小傅哥的 DB-Router 組件開發(fā),那么也可以在組件中添加對Ignite內(nèi)存數(shù)據(jù)庫的路由配置。這樣的使用會更加方便,也可以自動的通過注解來切換數(shù)據(jù)源的使用。
-
- SpringBoot應用的yml配置,本身默認是配置一個數(shù)據(jù)源的。但我們這里需要把Ignite也配置出數(shù)據(jù)源并讓它可以結合MyBatis進行使用。所以需要做一點編碼的擴展使用。
具體可以參考源碼
- 與此同時還需要考慮對 Dao、Mapper 分不同的路徑進行加載使用。因為本身來說,他們就是一套東西的不同數(shù)據(jù)源使用方式。
二、環(huán)境安裝
在安裝執(zhí)行 docker-compose.yml 腳本之前,你需要先在本地安裝 docker之后 IntelliJ IDEA 打開 docker-compose.yml 文件,如圖操作即可安裝。
- 在 docker-compose.yml 中會先安裝 MySQL 并執(zhí)行 sql 文件夾里的 SQL 語句初始化數(shù)據(jù)庫表。之后會安裝 Ignite 環(huán)境,安裝后需要用到 DBeaver 連接使用。同時 compose 中還安裝了一個 ApacheBench 壓測工具。
三、連接配置
首先確保你已經(jīng)安裝過 ?DBeaver ,之后就可以連接和創(chuàng)建表了。
1. 選擇 Ignite
2. 驗證鏈接
3. 創(chuàng)建庫表
4. 創(chuàng)建完成
- 之后你所有做的修改,包括你自己手動創(chuàng)建表、字段、索引,都需要點保存。否則它是紅色的,不生效。
四、功能配置
1. 工程結構
- app層;application-dev.yml 配置多套數(shù)據(jù)源,并在 DataSourceConfig 中實現(xiàn)多套數(shù)據(jù)源的加載。infrastructure層;用于提供數(shù)據(jù)的 dao 層,這里分開2套分別提供。trigger;觸發(fā)器層,提供了調(diào)用 Ignite、MySQL 的測試驗證接口。
2. 數(shù)據(jù)源創(chuàng)建
<!--?https://mvnrepository.com/artifact/org.apache.ignite/ignite-core?-->
<dependency>
????<groupId>org.apache.ignite</groupId>
????<artifactId>ignite-core</artifactId>
????<version>2.15.0</version>
</dependency>
<!--?https://mvnrepository.com/artifact/org.apache.ignite/ignite-spring?-->
<dependency>
????<groupId>org.apache.ignite</groupId>
????<artifactId>ignite-spring</artifactId>
????<version>2.15.0</version>
</dependency>
- 注意引入 ignite 的 pom 配置
2.1 Ignite
源碼:cn.bugstack.xfg.dev.tech.config.DataSourceConfig#IgniteMyBatisConfig
@Configuration
@MapperScan(basePackages?=?"cn.bugstack.xfg.dev.tech.infrastructure.ignite.dao",?sqlSessionFactoryRef?=?"igniteSqlSessionFactory")
static?class?IgniteMyBatisConfig?{
????@Bean("igniteDataSource")
????@ConfigurationProperties(prefix?=?"spring.ignite.datasource")
????public?DataSource?igniteDataSource(Environment?environment)?{
????????IgniteConfiguration?igniteConfig?=?new?IgniteConfiguration();
????????DataStorageConfiguration?dataStorageConfig?=?new?DataStorageConfiguration();
????????DataRegionConfiguration?defaultDataRegionConfig?=?new?DataRegionConfiguration();
????????defaultDataRegionConfig.setPersistenceEnabled(false);
????????dataStorageConfig.setDefaultDataRegionConfiguration(defaultDataRegionConfig);
????????igniteConfig.setDataStorageConfiguration(dataStorageConfig);
????????ConnectorConfiguration?configuration?=?new?ConnectorConfiguration();
????????configuration.setIdleTimeout(6000);
????????configuration.setThreadPoolSize(100);
????????configuration.setIdleTimeout(60000);
????????igniteConfig.setConnectorConfiguration(configuration);
????????return?DataSourceBuilder.create()
????????????????.url(environment.getProperty("spring.ignite.datasource.url"))
????????????????.driverClassName(environment.getProperty("spring.ignite.datasource.driver-class-name"))
????????????????.build();
????}
????@Bean("igniteSqlSessionFactory")
????public?SqlSessionFactory?igniteSqlSessionFactory(DataSource?igniteDataSource)?throws?Exception?{
????????SqlSessionFactoryBean?factoryBean?=?new?SqlSessionFactoryBean();
????????factoryBean.setDataSource(igniteDataSource);
????????factoryBean.setMapperLocations(new?PathMatchingResourcePatternResolver().getResources("classpath:/mybatis/mapper/ignite/*.xml"));
????????return?factoryBean.getObject();
????}
}
- 創(chuàng)建 Ignite 的數(shù)據(jù)源,以及對應的 igniteSqlSessionFactory 工廠。這樣就把 MyBatis 給關聯(lián)起來了。
2.2 MySQL
源碼:cn.bugstack.xfg.dev.tech.config.DataSourceConfig#MysqlMyBatisConfig
@Configuration
@MapperScan(basePackages?=?"cn.bugstack.xfg.dev.tech.infrastructure.mysql.dao",?sqlSessionFactoryRef?=?"mysqlSqlSessionFactory")
static?class?MysqlMyBatisConfig?{
????@Bean("mysqlDataSource")
????@ConfigurationProperties(prefix?=?"spring.mysql.datasource")
????public?DataSource?mysqlDataSource(Environment?environment)?{
????????return?DataSourceBuilder.create()
????????????????.url(environment.getProperty("spring.mysql.datasource.url"))
????????????????.driverClassName(environment.getProperty("spring.mysql.datasource.driver-class-name"))
????????????????.build();
????}
????@Bean("mysqlSqlSessionFactory")
????public?SqlSessionFactory?mysqlSqlSessionFactory(DataSource?mysqlDataSource)?throws?Exception?{
????????SqlSessionFactoryBean?factoryBean?=?new?SqlSessionFactoryBean();
????????factoryBean.setDataSource(mysqlDataSource);
????????factoryBean.setMapperLocations(new?PathMatchingResourcePatternResolver().getResources("classpath:/mybatis/mapper/mysql/*.xml"));
????????return?factoryBean.getObject();
????}
}
- 同樣,創(chuàng)建 MySQL 的數(shù)據(jù)源以及 MyBatis 的關聯(lián)操作。
五、性能測試
小傅哥提供了 IgniteController、MySQLController 兩個 HTTP 訪問類,分別提供了兩個數(shù)據(jù)庫的壓測操作。
- 這里提供了 Ignite、MySQL 的 HTTP 訪問接口,分別進行壓測。
1. Ignite 壓測
-
- 初始化ID值:
ab -c 1 -n 1 http://127.0.0.1:8091/api/ignite/start
-
- 寫入數(shù)據(jù):
ab -c 20 -n 50000 http://127.0.0.1:8091/api/ignite/insert
-
- 隨機加載內(nèi)存1000條數(shù)據(jù):
ab -c 20 -n 1000 http://127.0.0.1:8091/api/ignite/cacheData
-
- 根據(jù)加載到內(nèi)存的數(shù)據(jù)查詢Ignite:
ab -c 20 -n 1000 http://127.0.0.1:8091/api/ignite/selectByOrderId
- - 記得給 OrderId 加索引
2. MySQL 壓測
-
- 初始化ID值:
ab -c 1 -n 1 http://127.0.0.1:8091/api/ignite/start
-
- 寫入數(shù)據(jù):
ab -c 20 -n 50000 http://127.0.0.1:8091/api/ignite/insert
-
- 隨機加載內(nèi)存1000條數(shù)據(jù):
ab -c 20 -n 1000 http://127.0.0.1:8091/api/ignite/cacheData
-
- 根據(jù)加載到內(nèi)存的數(shù)據(jù)查詢MySQL:
ab -c 20 -n 1000 http://127.0.0.1:8091/api/ignite/selectByOrderId
- - 記得給 OrderId 加索引
綜上,Ignite 略勝一籌,確實純內(nèi)存的數(shù)據(jù)庫會更快一些。也適合在一些需要內(nèi)存計算的場景中,并且不改變MySQL表結構的情況下,做一些優(yōu)化的是使用。
- 180天小卡拉米專屬學習路線又完結一個新項目,小而美、小而精!從MVC到DDD,架構的本質(zhì)API網(wǎng)關架構設計,從單體服務到微服務的架構演進Java 面經(jīng)手冊