8.1.2 TiDB存儲引擎的原理

TiDB 簡介

TiDB 是 PingCAP 公司自主設計、研發的開源分布式關系型數據 庫,是一款同時支持在線事務處理與在線分析處理 (Hybrid Transactional and Analytical Processing, HTAP) 的融合型分布 式數據庫產品,具備水平擴容或者縮容、金融級高可用、實時 HTAP、云原生的分布式數據庫、兼容 MySQL 5.7 協議和 MySQL 生態等重要特性。目標是為用戶提供一站式 OLTP (Online Transactional Processing)、OLAP (Online Analytical Processing)、HTAP 解決方案。TiDB 適合高可用、強一致要求 較高、數據規模較大等各種應用場景。

TiDB用來解決mysql單節點容量問題,有了TiDB之后,以往的技術如用redis緩存MySQL的數據的這種方案就沒有必要存在了,MySQL的分布分表,各種復雜的不同的水平分表分庫、垂直分表分庫也沒有必要去學了。TiDB都可以解決這些問題,因為它是一種分布式的。

分布式系統

分布式系統是一種其組件位于不同的聯網計算機上的系統,然 后通過互相傳遞消息來進行通訊和協調,為了達到共同的目 標,這些組件會相互作用;換句話說,分布式系統把需要進行 大量計算的工程數據分割成若干個小塊,由多臺計算機分別進 行計算和存儲,然后將結果統一合并到數據結論的科學;本質 上就是進行數據存儲與計算的分治

帶來的問題:CAP理論:一致性、可用性(主數據庫宕機,從數據庫進行替換使用)、分區容錯性(分布式系統在遇到某節點或網絡分區故障的時候仍然能夠對外 提供滿足一致性或可用性的服務;)

應用場景

1、對數據一致性及高可靠、系統高可用、可擴展性、容災要求較高的金融行業屬性的場景。

TiDB 采用多副本 + Multi-Raft 協議的方式將數據調度到不同的機房、機架、機器,當部分機器出現故障時系統可自動進行切換,確保系統的 RTO <= 30s 及 RPO = 0。

RTO(Recovery Time Objective):恢復時間目標,即在發生系統故障或災難事件時,恢復系統功能所需的時間。它代表了組織能夠接受的最長系統停機時間。

RPO(Recovery Point Objective):恢復點目標,即在發生系統故障或災難事件時,允許數據丟失的時間范圍。它表示組織庫接受的數據丟失程度。

RTO關注的是從故障中恢復正常操作所需的時間,而RPO關注的是在故障發生前可接受丟失的數據量。

2、對存儲容量、可擴展性、并發要求較高的海量數據及高并發的 OLTP 場景。

TiDB 采用計算、存儲分離的架構,可對計算、存儲分別進行 擴容和縮容,計算最大支持 512 節點,每個節點最大支持 1000 并發,集群容量最大支持 PB 級別。

3、Real-time HTAP 場景

TiDB 在 4.0 版本中引入列存儲引擎 TiFlash 結合行存儲引擎 TiKV 構建真正的 HTAP 數據庫,在增加少量存儲成本的情況 下,可以在同一個系統中做聯機交易處理、實時數據分析, 極大地節省企業的成本。

4、數據匯聚、二次加工處理的場景

業務通過 ETL 工具或者 TiDB 的同步工具將數據同步到 TiDB,在 TiDB 中可通過 SQL 直接生成報表。(ETL 是將業務系統的數據經過抽取、清洗轉換之后加載到數據倉庫的過程,目的是將企業中的分散、零亂、標準不統一的數據整合到一起,為企業的決策提供分析依據)

關系型模型

在傳統的在線交易場景里,關系型模型仍然是標準;關系型數 據庫的關鍵在于一定要具備事務

事務

事務的本質是:并發控制的單元,是用戶定義的一個操作序列;這些操作要么都做,要么都不做,是一個不可分割的工作單位;

為了保證系統始終處于一個完整且正確的狀態;

ACID 特性

原子性:事務包含的全部操作時一個不可分割的整體;要么全部執 行,要么全部不執行;

一致性:事務的前后,所有的數據都保持一個一致的狀態;不能違反 數據的一致性檢測;

隔離性:各個并發事務之間互相影響的程度;主要規定多個并發事務 訪問同一個數據資源,各個并發事務對該數據資源訪問的行 為;不同的隔離性是應對不同的現象(臟讀、可重復讀、幻 讀等);

持久性:事務一旦完成要將數據所做的變更記錄下來;包括數據存儲 和多副本的網絡備份;

TiDB可以視為分布式的mysql

TiDB 部署本地測試集群

# 下載并安裝 
TiUP curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
# 聲明全局環境變量 
source .bash_profile 
# 運行最新版本的 TiDB 集群, 其中 TiDB、TiKV、PD 和 TiFlash 實例各 1 個
tiup playground 
# 如果想指定版本并運行多個
tiup playground v4.0.16 --db 3 --pd 3 --kv 3 -- monitor 
# 注意: 按照上面的部署, 在結束部署測試后 TiUP 會清理掉原 集群數據,重新執行該命令后會得到一個全新的集群。 # 如果希望持久化數據, 并指定存儲目錄為 /tmp/tidb 
tiup playground -T /tmp/tidb --host 0.0.0.0

與傳統非分布式數據庫架構對比

  • 兩者都支持 ACID、事務強一致性;

  • 分布式架構,組件解耦,擁有良好的擴展性,支持彈性的擴縮容;

  • 默認支持高可用,在少數副本失效的情況下,數據庫能夠自動進 行故障轉移,對業務透明;

  • 采用水平擴展,在大數據量、高吞吐的業務場景中具有先天優勢;

  • 強項不在于輕量的簡單 SQL 的響應速度,而在于大量高并發 SQL 的吞吐;

TiDB 分布式數據庫整體架構

  • 由多模塊組成,各模塊互相通信,組成完整的 TiDB 系統;

  • 前端 stateless、后端 stateful (Raft);

  • 兼容 MySQL;

TiDB Server 的模塊

SQL 層,對外暴露 MySQL 協議的連接 endpoint,負責接受客 戶端的連接,執行 SQL 解析和優化,最終生成分布式執行計 劃。TiDB 層本身是無狀態的,實踐中可以啟動多個 TiDB 實例,通過負載均衡組件(如 LVS、HAProxy 或 F5)對外提供統 一的接入地址,客戶端的連接可以均勻地分攤在多個 TiDB 實例 上以達到負載均衡的效果。TiDB Server 本身并不存儲數據,只是解析SQL,將實際的數據讀取請求轉發給底層的存儲節點 TiKV(或 TiFlash)。

數據映射關系

數據與 KV 的映射關系中定義如下:

tablePrefix     = []byte{'t'} 
recordPrefixSep = []byte{'r'} 
indexPrefixSep  = []byte{'i'} 

假設表結構如下:

CREATE TABLE User (   ID int,    Name varchar(20),    Role varchar(20),    Age int,    UID int,     PRIMARY KEY (ID),     KEY idxAge (Age),     UNIQUE KEY idxUID (UID) 
); 

假設表數據如下:

1, "TiDB", "SQL Layer", 10, 10001 
2, "TiKV", "KV Engine", 20, 10002 
3, "PD", "Manager", 30, 10003 

表數據與 KV 的映射關系

Key 的形式:tablePrefix{TableID}_recordPrefixSep{RowID}

Value 的形式:[col1, col2, col3, col4]

映射示例:

# 假設系統為user表分配了表ID為10
t10_r1 --> ["TiDB", "SQL Layer", 10, 10001] 
t10_r2 --> ["TiKV", "KV Engine", 20, 10002] 
t10_r3 --> ["PD",   "Manager",   30, 10003] 

索引數據和 KV 的映射關系

對于唯一索引:

Key 的形式: tablePrefix{tableID}_indexPrefixSep{indexID}_indexe dColumnsValue

Value 的形式: RowID

映射示例:

# 假設系統為idxUID 分配的索引ID為3
t10_i3_10001 --> 1 
t10_i3_10002 --> 2 
t10_i3_10003 --> 3 

非唯一索引:

Key 的形式: tablePrefix{TableID}_indexPrefixSep{IndexID}_indexe dColumnsValue_{RowID}

Value 的形式:null

映射示例:

# 假設系統為idxAge 分配的索引ID為2 
t10_i2_10_1 --> null 
t10_i2_20_2 --> null 
t10_i2_30_3 --> null 

PD(Placement Driver)Server

整個 TiDB 集群的元信息管理模塊,負責存儲每個 TiKV 節點實 時的數據分布情況和集群的整體拓撲結構,提供 TiDB Dashboard 管控界面,并為分布式事務分配事務 ID。PD 不僅 存儲元信息,同時還會根據 TiKV 節點實時上報的數據分布狀 態,下發數據調度命令給具體的 TiKV 節點,可以說是整個集群 的“大腦”。此外,PD 本身也是由至少 3 個節點構成,擁有高可 用的能力。建議部署奇數個 PD 節點。

調度需求

  1. 作為一個分布式高可用存儲系統,必須滿足的需求,包括幾種:

  • 副本數量不能多也不能少

  • 副本需要根據拓撲結構分布在不同屬性的機器上

  • 節點宕機或異常能夠自動合理快速地進行容災

  1. 作為一個良好的分布式系統,需要考慮的地方包括:

  • 維持整個集群的 Leader 分布均勻

  • 維持每個節點的儲存容量均勻

  • 維持訪問熱點分布均勻

  • 控制負載均衡的速度,避免影響在線服務

  • 管理節點狀態,包括手動上線/下線節點

滿足第一類需求后,整個系統將具備強大的容災功能。滿足第 二類需求后,可以使得系統整體的資源利用率更高且合理,具 備良好的擴展性。

調度操作

  • 增加一個副本

  • 刪除一個副本

  • 將 Leader 角色在一個 Raft Group 的不同副本之間 transfer (遷移)。

信息收集

  • 每個 TiKV 節點會定期向 PD 匯報節點的狀態信息

  • 每個 Raft Group 的 Leader 會定期向 PD 匯報 Region 的狀態信 息

存儲節點

TiKV Server

負責存儲數據,從外部看 TiKV 是一個分布式的提供事務的 KeyValue 存儲引擎。存儲數據的基本單位是 Region,每個 Region 負責存儲一個 Key Range(從 StartKey 到 EndKey 的左閉右開 區間)的數據,每個 TiKV 節點會負責多個 Region。TiKV 的 API 在 KV 鍵值對層面提供對分布式事務的原生支持,默認提供了 SI (Snapshot Isolation) 的隔離級別,這也是 TiDB 在 SQL 層 面支持分布式事務的核心。TiDB 的 SQL 層做完 SQL 解析后, 會將 SQL 的執行計劃轉換為對 TiKV API 的實際調用。所以,數 據都存儲在 TiKV 中。另外,TiKV 中的數據都會自動維護多副本 (默認為三副本),天然支持高可用和自動故障轉移。

TiFlash

TiFlash 是一類特殊的存儲節點。和普通 TiKV 節點不一樣的 是,在 TiFlash 內部,數據是以列式的形式進行存儲,主要的功 能是為分析型的場景加速。

  • 列式存儲可以滿足快速讀取特定列的需求,在線分析處理往往需 要在上百列的寬表中讀取指定列分析;

  • 列式存儲就近存儲同一列的數據,使用壓縮算法可以得到更高的壓縮率,減少存儲占用的磁盤空間;

RocksDB

RocksDB 作為 TiKV 的核心存儲引擎,用于存儲 Raft 日志以及 用戶數據。每個 TiKV 實例中有兩個 RocksDB 實例,一個用于 存儲 Raft 日志(通常被稱為 raftdb),另一個用于存儲用戶數 據以及 MVCC 信息(通常被稱為 kvdb)。kvdb 中有四個 ColumnFamily:raft、lock、default 和 write:

  • raft 列:用于存儲各個 Region 的元信息。僅占極少量空間,用 戶可以不必關注。

  • lock 列:用于存儲悲觀事務的悲觀鎖以及分布式事務的一階段 Prewrite 鎖。當用戶的事務提交之后,lock cf 中對應的數據會 很快刪除掉,因此大部分情況下 lock cf 中的數據也很少(少于 1GB)。如果 lock cf 中的數據大量增加,說明有大量事務等待提交,系統出現了 bug 或者故障。

  • write 列:用于存儲用戶真實的寫入數據以及 MVCC 信息(該數 據所屬事務的開始時間以及提交時間)。當用戶寫入了一行數據 時,如果該行數據長度小于 255 字節,那么會被存儲 write 列 中,否則的話該行數據會被存入到 default 列中。由于 TiDB 的 非 unique 索引存儲的 value 為空,unique 索引存儲的 value 為主鍵索引,因此二級索引只會占用 writecf 的空間。

  • default 列:用于存儲超過 255 字節長度的數據。

內存占用

為了提高讀取性能以及減少對磁盤的讀取,RocksDB 將存儲在 磁盤上的文件都按照一定大小切分成 block(默認是 64KB), 讀取 block 時先去內存中的 BlockCache 中查看該塊數據是否存 在,存在的話則可以直接從內存中讀取而不必訪問磁盤。

BlockCache 按照 LRU 算法淘汰低頻訪問的數據,TiKV 默認將 系統總內存大小的 45% 用于 BlockCache,用戶也可以自行修 改 storage.block-cache.capacity 配置設置為合適的值,但 是不建議超過系統總內存的 60%。

寫入 RocksDB 中的數據會寫入 MemTable,當一個 MemTable 的大小超過 128MB 時,會切換到一個新的 MemTable 來提供寫入。TiKV 中一共有 2 個 RocksDB 實例, 合計 4 個 ColumnFamily,每個 ColumnFamily 的單個 MemTable 大小限制是 128MB,最多允許 5 個 MemTable 存 在,否則會阻塞前臺寫入,因此這部分占用的內存最多為 4 x 5 x 128MB = 2.5GB。這部分占用內存較少,不建議用戶自行更 改。

空間占用

  • 多版本:RocksDB 作為一個 LSM-tree 結構的鍵值存儲引擎, MemTable 中的數據會首先被刷到 L0。L0 層的 SST 之間的范圍 可能存在重疊(因為文件順序是按照生成的順序排列),因此同 一個 key 在 L0 中可能存在多個版本。當文件從 L0 合并到 L1 的 時候,會按照一定大小(默認是 8MB)切割為多個文件,同一 層的文件的范圍互不重疊,所以 L1 及其以后的層每一層的 key 都只有一個版本。

  • 空間放大:RocksDB 的每一層文件總大小都是上一層的 x 倍, 在 TiKV 中這個配置默認是 10,因此 90% 的數據存儲在最后一層,這也意味著 RocksDB 的空間放大不超過 1.11(L0 層的數 據較少,可以忽略不計)。

  • TiKV 的空間放大:TiKV 在 RocksDB 之上還有一層自己的 MVCC,當用戶寫入一個 key 的時候,實際上寫入到 RocksDB 的是 key + commit_ts,也就是說,用戶的更新和刪除都是會寫 入新的 key 到 RocksDB。TiKV 每隔一段時間會刪除舊版本的數 據(通過 RocksDB 的 Delete 接口),因此可以認為用戶存儲在 TiKV 上的數據的實際空間放大為,1.11 加最近 10 分鐘內寫入 的數據(假設 TiKV 回收舊版本數據足夠及時)。

compact

RocksDB 中,將內存中的 MemTable 轉化為磁盤上的 SST 文 件,以及合并各個層級的 SST 文件等操作都是在后臺線程池中 執行的。后臺線程池的默認大小是 8,當機器 CPU 數量小于等 于 8 時,則后臺線程池默認大小為 CPU 數量減一。通常來說, 用戶不需要更改這個配置。如果用戶在一個機器上部署了多個 TiKV 實例,或者機器的讀負載比較高而寫負載比較低,那么可 以適當調低 rocksdb/max-background-jobs 至 3 或者 4。

WriteStall(寫停頓)

RocksDB 的 L0 與其他層不同,L0 的各個 SST 是按照生成順序 排列,各個 SST 之間的 key 范圍存在重疊,因此查詢的時候必 須依次查詢 L0 中的每一個 SST。為了不影響查詢性能,當 L0 中的文件數量過多時,會觸發 WriteStall 阻塞寫入。

如果用戶遇到了寫延遲突然大幅度上漲,可以先查看 Grafana RocksDB KV 面板 WriteStall Reason 指標,如果是 L0 文件數 量過多引起的 WriteStall,可以調整下面幾個配置到 64。

rocksdb.defaultcf.level0-slowdown-writes-trigger 
rocksdb.writecf.level0-slowdown-writes-trigger 
rocksdb.lockcf.level0-slowdown-writes-trigger 
rocksdb.defaultcf.level0-stop-writes-trigger 
rocksdb.writecf.level0-stop-writes-trigger 
rocksdb.lockcf.level0-stop-writes-trigger 

參考連接:https://github.com/0voice

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/91651.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/91651.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/91651.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PTE之路--01

空格繞過:/**/ URL編碼偽協議:pagezip://xxx/xx/x/x/xxx.jpg%23解壓后的名字pagephar://xxx/xx/x/x/xxx.jpg/解壓后的名字pageddata://ata://text/plain,<?php eval($_POST[x]) ;?>pagedata://text/plain,<?php eval($_POST[x]) ;?>127.0.0.1 | grep . ../key…

企業級日志分析系統ELK

1.什么是 Elastic Stack 如果系統和應用出現異常和問題,相關的開發和運維人員想要排查原因,就要先登錄到應用運行所相應的主機,找到上面的相關日志文件再進行查找和分析,所以非常不方便,此外還會涉及到權限和安全問題,而ELK 的出現就很好的解決這一問題。 ELK 是由一家 …

ai項目多智能體

手把手教你構建一個 本地化的&#xff0c;免費的&#xff0c;企業級的&#xff0c;AI大模型知識庫問答系統 - 網旭哈瑞.AI 體驗 AutoGen Studio - 微軟推出的友好多智能體協作框架_autogenstudio-CSDN博客 AutoGen Studio: Interactively Explore Multi-Agent Workflows | Au…

【HTML】淺談 script 標簽的 defer 和 async

The async and defer attributes are boolean attributes that indicate how the script should be evaluated. There are several possible modes that can be selected using these attributes, depending on the script’s type. async 和 defer 屬性是布爾屬性&#xff0c;…

Kafka Streams 并行處理機制深度解析:任務(Task)與流線程(Stream Threads)的協同設計

在構建實時流處理應用時&#xff0c;如何充分利用計算資源同時保證處理效率是一個關鍵問題。Kafka Streams 通過其獨特的任務(Task)和流線程(Stream Threads)并行模型&#xff0c;為開發者提供了既簡單又強大的并行處理能力。本文將深入解析 Kafka Streams 中任務與線程的協同工…

使用 Docker 部署 Label Studio 時本地文件無法顯示的排查與解決

目錄 使用 Docker 部署 Label Studio 時本地文件無法顯示的排查與解決 1. 背景 2. 問題現象 3. 排查步驟 3.1 確認文件是否存在 3.2 檢查環境變量配置 4. 解決方案 方法一&#xff1a;修改 Sync Storage 路徑&#xff08;相對路徑&#xff09; 方法二&#xff1a;修改…

ElasticJob怎么使用?

我們使用ElasticJob需要以下步驟&#xff1a; 1. 添加依賴 2. 配置任務&#xff08;可以使用Spring命名空間配置或Java配置&#xff09; 3. 實現任務邏輯&#xff08;實現SimpleJob、DataflowJob等接口&#xff09; 4. 啟動任務 下面是一個詳細的示例&#xff0c;包括Spring Bo…

TCP協議的特點和首部格式

文章目錄TCP協議是什么&#xff1f;TCP協議的主要特點1. 面向連接2. 可靠傳輸3. 流量控制4. 擁塞控制TCP首部格式源端口和目標端口&#xff08;各16位&#xff09;序列號&#xff08;32位&#xff09;確認號&#xff08;32位&#xff09;數據偏移&#xff08;4位&#xff09;保…

IO流-文件的常用方法

1.關于java.io.File類- File類只能表示計算機中的文件或目錄而不能獲取或操作文件- 通過File類獲得到文件的基本信息&#xff0c;如文件名、大小等&#xff0c;但不能獲取文件內容- java中表示文件路徑分隔符使用"/"或"\\"- File類中的構造方法- File(&quo…

AUTOSAR進階圖解==>AUTOSAR_SRS_E2E

AUTOSAR E2E通信保護解析 AUTOSAR End-to-End通信保護機制詳解與應用目錄 概述 1.1. AUTOSAR E2E通信保護的作用 1.2. E2E通信保護的應用場景AUTOSAR E2E架構 2.1. E2E組件層次結構 2.2. E2E庫和E2E轉換器E2E監控狀態機 3.1. 狀態定義與轉換 3.2. 狀態機實現E2E保護數據交換流…

鏡像快速部署ollama+python+ai

算力租賃入口&#xff1a;https://www.jygpu.com為大家提供以上鏡像快速部署方式&#xff0c;節約大家環境部署時間一鍵部署的便捷性傳統自建GPU服務器需要經歷復雜的硬件采購、驅動安裝、環境配置等繁瑣步驟&#xff0c;而現代??GPU租賃價格對比??顯示&#xff0c;容器化平…

使用Gemini API開發領域智能聊天機器人的思路

以下是使用 Gemini API 開發軟件自動化測試專家領域專屬智能聊天機器人的詳細思路及具體實現過程&#xff1a; 階段一&#xff1a;基礎準備與規劃 (Foundation & Planning) 這個階段的目標是明確方向、準備好所有必要的工具和憑證。 步驟 1&#xff1a;明確聊天機器人的目…

第13屆藍橋杯Python青少組_省賽_中/高級組_2022年4月17日真題

更多內容請查看網站&#xff1a;【試卷中心 -----> 藍橋杯----> Python----> 省賽】 網站鏈接 青少年軟件編程歷年真題模擬題實時更新 第13屆藍橋杯Python青少組_省賽_中/高級組_2022年4月17日真題 一、選擇題 第 1 題 下列二進制數中最大的是&#xff08; &a…

sqli-labs:Less-17關卡詳細解析

1. 思路&#x1f680; 本關的SQL語句為&#xff1a; $sql"SELECT username, password FROM users WHERE username $uname LIMIT 0,1"; $update"UPDATE users SET password $passwd WHERE username$row1";注入類型&#xff1a;字符串型&#xff08;單引號…

文心一言:推動 AIGC 領域進步

文心一言:推動AIGC領域進步 關鍵詞:文心一言、AIGC、自然語言處理、多模態生成、大模型、技術架構、應用場景 摘要:本文深入剖析百度文心一言在AIGC(人工智能生成內容)領域的技術創新與實踐成果。通過解析其核心技術架構、多模態生成原理、工程化落地策略及行業應用案例,…

第15講——微分方程

文章目錄思維導圖基本概念微分方程及其階思維導圖 基本概念 微分方程及其階

RAGFlow Agent 知識檢索節點源碼解析:從粗排到精排的完整流程

RAGFlow Agent 知識檢索節點深度解析&#xff1a;從查詢到重排序的完整流程 1. 總體架構概覽 RAGFlow Agent 中的知識檢索&#xff08;Retrieval&#xff09;節點是整個RAG系統的核心組件&#xff0c;負責從知識庫中找到與用戶查詢最相關的文檔片段。檢索流程可以分為以下幾個…

Python算法實戰:從排序到B+樹全解析

Python中常見的算法示例 以下是Python中常見的算法示例,涵蓋基礎算法和經典問題解決方案,代碼可直接運行: 排序算法 冒泡排序 def bubble_sort(arr):n = len(arr)for i in range(n):for j in range(0, n-i-1):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr…

【C++算法】85.BFS解決最短路徑問題_最小基因變化

文章目錄題目鏈接&#xff1a;題目描述&#xff1a;解法C 算法代碼&#xff1a;題目鏈接&#xff1a; 433. 最小基因變化 題目描述&#xff1a; 解法 先看懂題目 先把這個問題轉化&#xff1a;圖論問題 邊權為1的最短路問題。 為什么可以這么想&#xff1f;&#xff01; 因為每…

基于單片機汽車少兒安全預警系統

文章目錄一、前言1.1 項目介紹【1】項目開發背景【2】設計實現的功能【3】項目硬件模塊組成【4】設計意義【5】市面上同類產品研究現狀【6】摘要1.2 設計思路1.3 系統功能總結1.4 開發工具的選擇【1】設備端開發【2】上位機開發1.5 模塊的技術詳情介紹1.6 框架圖框架圖說明&…