Apache IoTDB 觸發(fā)器實操步驟
Apache IoTDB(Internet of Things Database)是專為物聯(lián)網(wǎng)場景設(shè)計的時序數(shù)據(jù)庫,提供高效的時序數(shù)據(jù)存儲、查詢與分析能力。觸發(fā)器(Trigger) 作為 IoTDB 的核心功能之一,支持在數(shù)據(jù)插入、更新、刪除等事件發(fā)生時自動執(zhí)行預(yù)設(shè)邏輯,適用于實時數(shù)據(jù)校驗、告警觸發(fā)、數(shù)據(jù)轉(zhuǎn)換、跨系統(tǒng)同步等場景,是實現(xiàn) IoT 數(shù)據(jù)實時處理的關(guān)鍵組件。本指南將從基礎(chǔ)概念、核心特性、實操步驟、進階用法到最佳實踐,全面覆蓋 IoTDB 觸發(fā)器的使用細節(jié)。
一、觸發(fā)器核心概念與設(shè)計理念
1. 基本定義
觸發(fā)器是一種事件驅(qū)動的自動執(zhí)行機制,當滿足預(yù)設(shè)的 “觸發(fā)條件” 時,自動執(zhí)行關(guān)聯(lián)的 “動作邏輯”。在 IoTDB 中,觸發(fā)器與時序數(shù)據(jù)的生命周期深度綁定,僅針對時間序列數(shù)據(jù)操作生效。
2. 核心設(shè)計理念
- 輕量級無侵入:觸發(fā)器邏輯運行在 IoTDB 內(nèi)部,無需依賴外部中間件,避免跨系統(tǒng)通信開銷;
- 時序場景優(yōu)化:針對 IoT 數(shù)據(jù)高寫入、高并發(fā)特性,支持異步執(zhí)行、批量處理,最小化對主流程性能影響;
- 靈活擴展:支持 SQL 原生語法創(chuàng)建簡單觸發(fā)器,也支持 Java 自定義復(fù)雜邏輯(如調(diào)用外部系統(tǒng)、復(fù)雜計算);
- 兼容性強:適配單機與集群環(huán)境,支持與 IoTDB 的 UDF(用戶自定義函數(shù))、連續(xù)查詢(Continuous Query)等功能聯(lián)動。
3. 核心要素
一個完整的 IoTDB 觸發(fā)器包含 5 個關(guān)鍵要素:
| 要素 | 說明 |
|---|---|
| 觸發(fā)器名稱 | 全局唯一標識,用于管理(查詢 / 修改 / 刪除)觸發(fā)器 |
| 觸發(fā)事件(Event) | 觸發(fā)觸發(fā)器的核心操作,支持 3 類:INSERT(數(shù)據(jù)插入)、UPDATE(數(shù)據(jù)更新)、DELETE(數(shù)據(jù)刪除) |
| 觸發(fā)時機(Timing) | 事件發(fā)生的階段,支持 2 類:BEFORE(事件執(zhí)行前)、AFTER(事件執(zhí)行后) |
| 觸發(fā)條件(Condition) | 可選,滿足該條件才執(zhí)行動作(如 “溫度> 80℃”),支持 SQL 表達式語法 |
| 執(zhí)行動作(Action) | 觸發(fā)后執(zhí)行的邏輯,支持 2 類:SQL 動作(執(zhí)行 SQL 語句)、自定義動作(Java 實現(xiàn)的邏輯) |
二、觸發(fā)器核心特性
1. 支持的觸發(fā)場景
- 事件類型:覆蓋數(shù)據(jù)全生命周期操作(INSERT/UPDATE/DELETE),其中
INSERT是最常用場景(如設(shè)備數(shù)據(jù)上報時觸發(fā)); - 觸發(fā)時機:
BEFORE:用于數(shù)據(jù)寫入前的校驗、過濾(如攔截非法數(shù)據(jù));AFTER:用于數(shù)據(jù)寫入后的后續(xù)處理(如告警、同步、統(tǒng)計);
- 數(shù)據(jù)粒度:支持針對單個時間序列、設(shè)備(多個序列)、存儲組級別的觸發(fā)。
2. 執(zhí)行模式
- 同步執(zhí)行:觸發(fā)器動作與主操作(如 INSERT)在同一線程執(zhí)行,主操作需等待觸發(fā)器完成(適用于數(shù)據(jù)校驗、過濾等必須阻塞的場景);
- 異步執(zhí)行:觸發(fā)器動作在獨立線程執(zhí)行,主操作無需等待(適用于告警、數(shù)據(jù)同步等非阻塞場景,避免影響寫入性能);
- 注:默認同步執(zhí)行,創(chuàng)建觸發(fā)器時可通過參數(shù)指定
ASYNC模式。
3. 動作類型
| 動作類型 | 適用場景 | 優(yōu)勢 | 局限性 |
|---|---|---|---|
| SQL 動作 | 簡單邏輯(如插入告警記錄、更新統(tǒng)計值) | 無需開發(fā),直接通過 SQL 定義,上手快 | 不支持復(fù)雜邏輯(如循環(huán)、外部調(diào)用) |
| 自定義動作(UDF 擴展) | 復(fù)雜邏輯(如調(diào)用 HTTP 接口、跨系統(tǒng)同步、復(fù)雜計算) | 靈活度高,支持任意 Java 邏輯 | 需要開發(fā)、編譯、部署自定義類 |
4. 集群兼容性
- 單機環(huán)境:觸發(fā)器僅在本地生效,觸發(fā)邏輯運行在當前節(jié)點;
- 集群環(huán)境:支持分布式觸發(fā),可配置觸發(fā)器在 “所有節(jié)點” 或 “指定節(jié)點” 執(zhí)行,確保高可用(某節(jié)點故障時,其他節(jié)點仍能觸發(fā))。
三、觸發(fā)器實操指南(基于 IoTDB 1.2.x 版本)
1. 前置條件
- 已安裝 IoTDB(推薦 1.0 及以上版本,1.0 以下版本觸發(fā)器功能不完善);
- 熟悉 IoTDB 基本操作(如創(chuàng)建存儲組、時間序列、插入數(shù)據(jù));
- 若使用自定義觸發(fā)器,需具備 Java 開發(fā)環(huán)境(JDK 8+),并引入 IoTDB 核心依賴。
2. 基礎(chǔ)操作:SQL 原生觸發(fā)器(無需開發(fā))
2.1 創(chuàng)建觸發(fā)器語法
CREATE TRIGGER [IF NOT EXISTS] <trigger_name> ON ( <storage_group_path> | <device_path> | <time_series_path> ) [ WHEN ( <condition_expression> ) ] AFTER | BEFORE ( INSERT | UPDATE | DELETE ) [ ASYNC ] -- 可選,默認同步執(zhí)行 DO <sql_action>;
- 語法說明:
<trigger_name>:觸發(fā)器名稱(如temp_alarm_trigger);ON:指定觸發(fā)范圍(存儲組 / 設(shè)備 / 時間序列,如/root/sg1/dev1或/root/sg1/dev1/temperature);WHEN:可選觸發(fā)條件,支持 SQL 表達式(如temperature > 80 AND humidity < 30);AFTER/BEFORE:觸發(fā)時機;ASYNC:異步執(zhí)行標識;<sql_action>:觸發(fā)后執(zhí)行的 SQL 語句(支持 INSERT、UPDATE、DELETE、SELECT 等,多個 SQL 用;分隔)。
2.2 示例 1:數(shù)據(jù)插入后觸發(fā)告警(AFTER + INSERT + 條件)
場景:當設(shè)備 /root/sg1/dev1 的溫度(temperature)超過 80℃ 時,自動插入告警記錄到 alarm_series 序列。
步驟 1:創(chuàng)建基礎(chǔ)時間序列(存儲組、設(shè)備、告警序列)
-- 創(chuàng)建存儲組 CREATE STORAGE GROUP IF NOT EXISTS /root/sg1; -- 創(chuàng)建設(shè)備 dev1 的溫度、濕度序列 CREATE TIMESERIES IF NOT EXISTS /root/sg1/dev1/temperature WITH DATATYPE=FLOAT, ENCODING=PLAIN; CREATE TIMESERIES IF NOT EXISTS /root/sg1/dev1/humidity WITH DATATYPE=FLOAT, ENCODING=PLAIN; -- 創(chuàng)建告警序列(存儲告警信息) CREATE TIMESERIES IF NOT EXISTS /root/sg1/dev1/alarm WITH DATATYPE=TEXT, ENCODING=PLAIN;
步驟 2:創(chuàng)建觸發(fā)器
CREATE TRIGGER IF NOT EXISTS temp_alarm_trigger ON /root/sg1/dev1 -- 設(shè)備級觸發(fā),該設(shè)備下任意序列插入數(shù)據(jù)都會檢查條件 WHEN (temperature > 80.0) -- 僅溫度超過 80℃ 時觸發(fā) AFTER INSERT -- 數(shù)據(jù)插入后執(zhí)行 ASYNC -- 異步執(zhí)行,不影響溫度數(shù)據(jù)寫入 DO INSERT INTO /root/sg1/dev1 (alarm) VALUES (NOW(), '溫度超標告警:' || CAST(temperature AS TEXT) || '℃');
步驟 3:測試觸發(fā)器
-- 插入正常溫度數(shù)據(jù)(不會觸發(fā)告警) INSERT INTO /root/sg1/dev1 (temperature, humidity) VALUES (75.5, 40.0); -- 插入超標溫度數(shù)據(jù)(觸發(fā)告警) INSERT INTO /root/sg1/dev1 (temperature, humidity) VALUES (85.0, 35.0); -- 查詢告警序列,驗證結(jié)果 SELECT alarm FROM /root/sg1/dev1 WHERE time >= NOW() - 10s;
2.3 示例 2:數(shù)據(jù)插入前校驗(BEFORE + INSERT + 過濾非法數(shù)據(jù))
場景:攔截溫度低于 -40℃ 或高于 120℃ 的非法數(shù)據(jù)(IoT 傳感器正常工作范圍)。
CREATE TRIGGER IF NOT EXISTS temp_validate_trigger ON /root/sg1/dev1/temperature -- 僅針對溫度序列觸發(fā) WHEN (temperature < -40.0 OR temperature > 120.0) -- 非法數(shù)據(jù)條件 BEFORE INSERT -- 插入前執(zhí)行 DO REJECT; -- 內(nèi)置動作:拒絕插入該條數(shù)據(jù)
測試:插入非法數(shù)據(jù)會被攔截
-- 插入 -50℃(非法),不會寫入成功 INSERT INTO /root/sg1/dev1 (temperature) VALUES (-50.0); -- 查詢溫度序列,無該條數(shù)據(jù) SELECT temperature FROM /root/sg1/dev1;
2.4 觸發(fā)器管理操作
(1)查詢所有觸發(fā)器
SHOW TRIGGERS; -- 或查詢指定范圍的觸發(fā)器 SHOW TRIGGERS ON /root/sg1/dev1;
(2)查看觸發(fā)器詳情
DESCRIBE TRIGGER <trigger_name>;
(3)修改觸發(fā)器(僅支持修改條件、動作、執(zhí)行模式)
ALTER TRIGGER <trigger_name> [ WHEN ( <new_condition> ) ] [ DO <new_sql_action> ] [ ASYNC | SYNC ]; -- 修改執(zhí)行模式
(4)刪除觸發(fā)器
DROP TRIGGER IF EXISTS <trigger_name>;
3. 進階操作:自定義觸發(fā)器(Java 開發(fā))
當 SQL 動作無法滿足復(fù)雜需求(如調(diào)用外部 API、跨系統(tǒng)同步到 Kafka、復(fù)雜計算)時,可通過 Java 開發(fā)自定義觸發(fā)器。
3.1 開發(fā)步驟
(1)引入依賴(Maven)
<dependency>
<groupId>org.apache.iotdb</groupId>
<artifactId>iotdb-server</artifactId>
<version>1.2.2</version> <!-- 與 IoTDB 服務(wù)器版本一致 -->
<scope>provided</scope> <!-- 服務(wù)器已包含該依賴,無需打包 -->
</dependency>
<dependency>
<groupId>org.apache.iotdb</groupId>
<artifactId>iotdb-jdbc</artifactId>
<version>1.2.2</version>
</dependency>(2)實現(xiàn) Trigger 接口
自定義觸發(fā)器需實現(xiàn) org.apache.iotdb.db.engine.trigger.api.Trigger 接口,核心方法如下:
| 方法名 | 說明 |
|---|---|
| init() | 觸發(fā)器初始化(如創(chuàng)建 Kafka 連接、加載配置),僅執(zhí)行一次 |
| onInsert() | 插入數(shù)據(jù)時觸發(fā)(對應(yīng) INSERT 事件) |
| onUpdate() | 更新數(shù)據(jù)時觸發(fā)(對應(yīng) UPDATE 事件) |
| onDelete() | 刪除數(shù)據(jù)時觸發(fā)(對應(yīng) DELETE 事件) |
| close() | 觸發(fā)器銷毀時執(zhí)行(如關(guān)閉連接、釋放資源) |
示例:自定義觸發(fā)器(數(shù)據(jù)插入后同步到 Kafka)
import org.apache.iotdb.db.engine.trigger.api.Trigger;
import org.apache.iotdb.db.engine.trigger.api.TriggerContext;
import org.apache.iotdb.db.engine.trigger.api.TriggerEvent;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.write.record.Tablet;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import java.util.Properties;
public class KafkaSyncTrigger implements Trigger {
private KafkaProducer<String, String> kafkaProducer;
private String topic;
// 初始化:創(chuàng)建 Kafka 連接(配置從觸發(fā)器參數(shù)傳入)
@Override
public void init(TriggerContext context) throws Exception {
// 從觸發(fā)器創(chuàng)建時的參數(shù)中獲取 Kafka 配置
String bootstrapServers = context.getTriggerAttributes().get("bootstrap.servers");
this.topic = context.getTriggerAttributes().get("topic");
Properties props = new Properties();
props.put("bootstrap.servers", bootstrapServers);
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
this.kafkaProducer = new KafkaProducer<>(props);
}
// 插入數(shù)據(jù)時觸發(fā):將數(shù)據(jù)同步到 Kafka
@Override
public void onInsert(TriggerEvent event) throws Exception {
Tablet tablet = event.getTablet(); // 獲取插入的數(shù)據(jù)(Tablet 是 IoTDB 批量數(shù)據(jù)存儲結(jié)構(gòu))
String device = tablet.getDeviceId(); // 設(shè)備 ID
// 遍歷 Tablet 中的數(shù)據(jù)行,構(gòu)造 Kafka 消息
for (int i = 0; i < tablet.getRowSize(); i++) {
long timestamp = tablet.getTimestamps()[i]; // 時間戳
String temperature = tablet.getValues()[0][i].toString(); // 假設(shè)第一個序列是溫度
String message = String.format("device:%s,time:%d,temperature:%s", device, timestamp, temperature);
// 發(fā)送到 Kafka
kafkaProducer.send(new ProducerRecord<>(topic, device, message));
}
}
// 銷毀:關(guān)閉 Kafka 連接
@Override
public void close() throws Exception {
if (kafkaProducer != null) {
kafkaProducer.close();
}
}
// 無需處理更新和刪除事件,可空實現(xiàn)
@Override
public void onUpdate(TriggerEvent event) throws Exception {}
@Override
public void onDelete(TriggerEvent event) throws Exception {}
}(3)編譯打包
將自定義觸發(fā)器類編譯為 JAR 包(需包含所有依賴,除 IoTDB 自帶的 iotdb-server 和 iotdb-jdbc),命名格式如 kafka-sync-trigger-1.0.jar。
(4)部署 JAR 包
將 JAR 包上傳到 IoTDB 服務(wù)器的 ext/trigger 目錄(若目錄不存在,手動創(chuàng)建),然后重啟 IoTDB 服務(wù)(確保觸發(fā)器類被加載)。
(5)創(chuàng)建自定義觸發(fā)器
CREATE TRIGGER IF NOT EXISTS kafka_sync_trigger
ON /root/sg1/dev1 -- 設(shè)備級觸發(fā)
AFTER INSERT
ASYNC -- 異步執(zhí)行,避免影響寫入
WITH (
'trigger.class' = 'com.example.KafkaSyncTrigger', -- 自定義類的全限定名
'bootstrap.servers' = '192.168.1.100:9092', -- Kafka 地址(自定義參數(shù))
'topic' = 'iotdb_data_sync' -- Kafka 主題(自定義參數(shù))
);- 說明:
WITH子句用于傳入自定義觸發(fā)器的配置參數(shù),通過context.getTriggerAttributes()讀取。
3.2 測試自定義觸發(fā)器
-- 插入數(shù)據(jù) INSERT INTO /root/sg1/dev1 (temperature) VALUES (78.5); -- 查看 Kafka 主題 iotdb_data_sync,應(yīng)收到消息:device:/root/sg1/dev1,time:xxx,temperature:78.5
四、進階用法與性能優(yōu)化
1. 觸發(fā)器與其他功能聯(lián)動
(1)與 UDF 結(jié)合
自定義觸發(fā)器中可調(diào)用 IoTDB 的 UDF 函數(shù)(如復(fù)雜計算函數(shù)),示例:
// 在 onInsert 中調(diào)用 UDF 函數(shù)計算溫度平均值
UDFExecutor executor = new UDFExecutor("avg_temp_udf"); // avg_temp_udf 是已注冊的 UDF
Object result = executor.calculate(tablet.getValues()[0]); // 傳入溫度數(shù)據(jù)(2)與連續(xù)查詢(CQ)結(jié)合
連續(xù)查詢用于周期性統(tǒng)計數(shù)據(jù)(如每分鐘統(tǒng)計平均溫度),觸發(fā)器可在 CQ 執(zhí)行后觸發(fā)(如將統(tǒng)計結(jié)果同步到外部系統(tǒng)):
-- 先創(chuàng)建連續(xù)查詢
CREATE CONTINUOUS QUERY cq_avg_temp
BEGIN
INSERT INTO /root/sg1/dev1/avg_temp SELECT AVG(temperature) FROM /root/sg1/dev1 GROUP BY TIME(1m)
END;
-- 創(chuàng)建觸發(fā)器,監(jiān)聽 avg_temp 序列的插入(CQ 執(zhí)行結(jié)果)
CREATE TRIGGER cq_sync_trigger
ON /root/sg1/dev1/avg_temp
AFTER INSERT
ASYNC
DO INSERT INTO /root/sg1/dashboard/avg_temp_sync VALUES (NOW(), avg_temp);2. 性能優(yōu)化建議
(1)優(yōu)先使用異步執(zhí)行
對于非阻塞場景(如告警、同步),務(wù)必添加 ASYNC 關(guān)鍵字,避免觸發(fā)器執(zhí)行耗時影響主流程寫入性能。
(2)批量處理數(shù)據(jù)
IoTDB 寫入數(shù)據(jù)時默認批量插入(Tablet 格式),自定義觸發(fā)器中應(yīng)直接操作 Tablet 批量數(shù)據(jù),而非單條處理,減少循環(huán)開銷。
(3)控制觸發(fā)器粒度
- 避免在存儲組級別創(chuàng)建過于復(fù)雜的觸發(fā)器(存儲組下設(shè)備過多時,觸發(fā)頻率過高);
- 針對特定序列的觸發(fā)需求,直接指定序列路徑(如
/root/sg1/dev1/temperature),而非設(shè)備或存儲組。
(4)資源限制
- 異步觸發(fā)器使用線程池執(zhí)行,可通過
iotdb-trigger.properties配置線程池大?。J 10 線程):
trigger.async.thread.pool.size=20 # 調(diào)整為合適的線程數(shù)
- 避免自定義觸發(fā)器中出現(xiàn)長時間阻塞操作(如同步調(diào)用外部 API 無超時設(shè)置),可添加超時控制:
// Kafka 發(fā)送超時控制 kafkaProducer.send(record).get(5, TimeUnit.SECONDS); // 5 秒超時
(5)集群環(huán)境優(yōu)化
- 集群中創(chuàng)建觸發(fā)器時,可指定
NODE_LIST參數(shù),僅在部分節(jié)點執(zhí)行(避免所有節(jié)點重復(fù)觸發(fā)):
CREATE TRIGGER cluster_trigger
ON /root/sg1
AFTER INSERT
WITH (
'trigger.class' = 'com.example.ClusterTrigger',
'NODE_LIST' = 'node1,node2' -- 僅在 node1 和 node2 執(zhí)行
);五、常見問題與排查
1. 觸發(fā)器不執(zhí)行
- 檢查觸發(fā)器狀態(tài):
SHOW TRIGGERS查看觸發(fā)器是否存在,DESCRIBE TRIGGER確認配置正確; - 檢查觸發(fā)條件:是否滿足
WHEN子句的表達式(如數(shù)據(jù)類型不匹配,temperature > '80'會導(dǎo)致條件失效); - 檢查權(quán)限:IoTDB 觸發(fā)器需要
TRIGGER_ADMIN權(quán)限,確保當前用戶有權(quán)限操作; - 查看日志:IoTDB 日志目錄(
logs/iotdb-server.log)中搜索觸發(fā)器名稱,查看是否有報錯(如自定義觸發(fā)器類未找到、Kafka 連接失?。?。
2. 寫入性能下降
- 排查是否使用同步觸發(fā)器:
DESCRIBE TRIGGER查看是否有ASYNC標識,無則添加; - 查看觸發(fā)器執(zhí)行耗時:通過日志打印執(zhí)行時間,優(yōu)化自定義觸發(fā)器邏輯(如減少外部調(diào)用、批量處理);
- 檢查線程池是否滿了:日志中若出現(xiàn)
Trigger async thread pool is full,需增大線程池大?。?code>trigger.async.thread.pool.size)。
3. 自定義觸發(fā)器類加載失敗
- 確認 JAR 包已上傳到
ext/trigger目錄,且文件名無特殊字符; - 確認自定義類的全限定名與
trigger.class參數(shù)一致(如com.example.KafkaSyncTrigger); - 確認 JAR 包依賴完整(除 IoTDB 自帶依賴外,其他依賴如 Kafka 客戶端需包含在 JAR 中)。
六、總結(jié)與適用場景
1. 觸發(fā)器適用場景
- 實時數(shù)據(jù)校驗與過濾(如攔截非法數(shù)據(jù));
- 實時告警(如溫度超標、設(shè)備離線告警);
- 數(shù)據(jù)同步(如同步到 Kafka、Hadoop、關(guān)系型數(shù)據(jù)庫);
- 數(shù)據(jù)轉(zhuǎn)換與增強(如單位轉(zhuǎn)換、補全缺失值);
- 聯(lián)動外部系統(tǒng)(如調(diào)用 HTTP 接口、控制設(shè)備)。
2. 不適用場景
- 大批量數(shù)據(jù)離線處理(建議使用 IoTDB 的 Export 工具或 Flink 等流處理框架);
- 長時間阻塞的復(fù)雜計算(如機器學習模型推理,建議異步提交到任務(wù)隊列)。
3. 版本兼容性提示
- 1.0 以下版本:觸發(fā)器功能不完善,不支持異步執(zhí)行和自定義觸發(fā)器,建議升級;
- 1.0-1.2 版本:支持核心功能,但部分高級特性(如集群分布式觸發(fā))在 1.2 版本后穩(wěn)定;
- 2.0+ 版本:優(yōu)化了觸發(fā)器性能,支持更多觸發(fā)事件(如批量刪除觸發(fā)),建議優(yōu)先使用最新版本。
到此這篇關(guān)于Apache IoTDB 觸發(fā)器實操步驟的文章就介紹到這了,更多相關(guān)Apache IoTDB 觸發(fā)器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
從基礎(chǔ)查看到底層運維詳解Linux磁盤的相關(guān)命令
在Linux系統(tǒng)中,磁盤是存儲數(shù)據(jù)的核心硬件,本文介紹了Linux系統(tǒng)中常用的磁盤管理命令,文中的示例代碼講解詳細,感興趣的小伙伴可以了解下2026-02-02
使用Kubeadm在CentOS7.2上部署Kubernetes集群的方法
本篇文章主要介紹了使用Kubeadm在CentOS7.2上部署Kubernetes集群的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-03-03
利用win10自帶虛擬機hyper-v安裝centos7方法詳解
利用VMware安裝CentOS系統(tǒng)相信大家都比較熟悉了,今天為大家介紹一下利用Win10自帶的虛擬機hyper-v來安裝CentOS,hyper-v與VMware的區(qū)別還是挺大的2018-10-10

