Redis——數據結構

目錄

1.動態字符串SDS

1.1SDS底層源碼

1.2 SDS動態擴容

1.3動態字符串SDS優點?

2.IntSet?

2.1底層結構

2.2有序性

2.3.IntSet結構擴容

2.4總結

3.Dict

3.1底層結構

3.2.Dict擴容?

3.3Dict收縮

?3.4.Dict的rehash

1.分配空間

2. 設置?rehashidx

3. 漸進式?rehash

Redis 采用漸進式?rehash?策略,避免一次性?rehash?大量鍵對服務器性能造成影響。具體步驟如下:

4. 遷移完成

4.ZipList

4.1底層結構

4.1.1 ZipList

?4.1.2 Entry

4.2.Encoding編碼

設計優勢

4.3.ZipList的連鎖更新問題

5.QuickList

5.1總結

6.SKipList

6.1底層結構源碼

?6.2總結

7.RedisObject

7.1.Redis的編碼方式


1.動態字符串SDS

我們都知道Redis保存的key是字符串value往往是字符串或者字符串的集合。可見字符串是redis中最常見的一種數據結構。

redis底層是c語言編寫的,不過redis并沒有直接使用c語言中的字符串,因為c語言字符串存在許多問題:

//c語言
char* s = "hello"
//本質是字符串數組:{'h','e','l','l','o','\0'}
  • 獲取字符串長度需要通過運算(獲取字符串長度還需要 - 結束標識符)
  • 非二進制安全(不能包含特殊字符)
  • 不可修改

所以Redis構建了一種新的字符串,動態字符串簡稱SDS

1.1SDS底層源碼

flags:redis為了解決數據結構體大小受限問題創建了不同的SDS數據結構類型(比如uint8_t只能存儲大小為255個字節數組字符串),flags主要作用就是用來存儲SDS的類型信息,在redis中,不同SDS在存儲容量和內存使用效率上各有不同。借助flags字段,redis能夠依據實際需求選用合適的SDS類型,從而實現內存的高效利用

flags默認值如下

例如,一個字符串包含name的sds結構如下:

flags:1表示使用type8來存儲數據

1.2 SDS動態擴容

SDS之所以叫動態字符串,因為它具備動態擴容的能力

步驟如下:

1.redis首先會去申請新的內存空間:申請規則如下

如果我們新的字符串大小小于1M,則新空間為擴張后字符串長度兩倍+1(減少內存分配的次數減少性能開銷

如果新字符串大小大于1M,則新空間為擴展后字符串長度+1M+1。稱為內存分配。(大于1M字符串如果再擴張為2倍非常浪費內存空間

2.再把原數組數據賦值過來

1.3動態字符串SDS優點?

  • 1.獲取字符串長度的時間復雜度為0(1)
  • 2.支持動態擴容
  • 3.減少內存分配次數
  • 4.二進制安全

2.IntSet?

IntSet是Redis中Set集合的一種實現方式,基于整數數組來實現的,并且具備長度可變有序等特征。

2.1底層結構

encoding其實和動態字符串SDS的flags作用一樣記錄使用哪種數據類型?,其中encoding包含三種模式,表示存儲的整數大小不同:

2.2有序性

為了方便查找,Redis會在intset中所有的整數按照升序依次保存在contens數組中,

現在每個數組中的每個數字都在int16_t范圍內,因此采用的編碼方式是INTSET_ENC_INT16

  • 1.IntSet底層采用的是連續的數組來存儲元素,并且每個元素的類型相同,那么每個元素內存中所占空間大小是固定的。
  • 2.intset會有尋址公式startPtr + (sizeof(int16)*index)通過這種尋址公式,intset可以高效的訪問數組中任意元素,通過將起始地址startPtr加上偏移量(sizeof(int16)*index),就能得到指定索引位置元素的內存地址。
  • 3.startPtr:這是整數集合底層數組的起始地址。根據上面那幅圖就是Header包含的部分
  • sizeof(int16)sizeof是一個用于獲取數據類型所占字節數的操作符,int16表示 16 位整數,
  • index:這是數組中元素的索引

2.3.IntSet結構擴容

IntSet支持動態升級能力,如果當前數據結構存儲不了要添加數據的大小就會升級編碼

舉個栗子:

現在假設有一個IntSet,元素為{5,10,20}采用的編碼是INTSET_ENC_INT16則每個整數占2個字節

我們向該其中添加一個數字:5000,這個數字超出了int16_t的范圍,intset會自動升級編碼方式到合適的大小。
以當前案例來說流程如下:

  • 1.升級編碼為INTSET_ENC_INT32每個整數占4字節,并按照新的編碼方式及元素個數擴容數組
  • 2.倒序依次將數組中的元素拷貝到擴容后的正確位置
  • 3.將待添加的元素放入數組末尾
  • 4.最后,將inset的encoding屬性改為INTSET_ENC_INT32,將length屬性改為4

這里你可能會有疑問為什么不正序添加元素而是采用倒序添加元素

主要是避免數據覆蓋問題:IntSet在內存中是連續存儲的,當進行編碼升級時,新元素類型的字節數會比原類型大。(要么添加到所有元素之后要么添加到所有元素之前,因為這個數要么就是負數很小,要么就是整數很大比如-5000or5000)如果正序添加元素,在將原Intset中的元素復制到新數組時,由于新元素占用空間更大,可能會覆蓋尚未處理的后續元素。

2.4總結

  • 1.Redis會確保Inset中的元素唯一,有序
  • 2.具備類型升級機制,可以節省內存空間
  • 3.底層采用二分查找方式來查詢

3.Dict

Dict是dictionary也就是字典的簡稱。redis是一個鍵值型(Key-Value pair)的數據庫,我們可以根據鍵實現快速的增刪改查。而鍵與值的映射關系Dict來實現的。
Dict由三部分組成,分別是:哈希表(DictHashTable),哈希節點(DictEntry),字典(Dict)

3.1底層結構

dict(字典)

  • 1.type表示字典類型(不同場景下使用不同字典類型,擴展性很強)
  • 2.ht[2]表是兩個hash表,一個用于存儲數據,一個用于重新構建hash表的時候使用
  • 3.rehashidx表示是否進行rehash

對于dictht(哈希表)

  • 1.第一個字段 table表示指針指向存儲hash節點數組的指針
  • 2.size代表hash表的大小也就是數組的大小
  • 3.掩碼sizemask,用于計算鍵值對存儲的位置
  • 4.used表示有多少個元素,因為會有hash沖突保存到數組同一個位置這樣就形成鏈表

DictEntry(hash節點):就表示一個鏈表數據結構


當我們向dict添加鍵值對時,redis首先根據key計算出hash值(h),然后利用h&sizemask(按位與)來計算元素應該存儲到數組中的哪個索引位置。我們存儲k1=v1,假設k1的哈希值h =1,則1&3=1,因此k1=v1要存儲到數組角標1位置。

3.2.Dict擴容?

Dict中的HashTable就是數組結合單向鏈表的實現,當集合中元素較多時,必然導致哈希沖突增多,鏈表過長,則查詢,效率會大大降低
Dict在每次新增鏈值對時都會檢查負載因子 (LoadFactor=used/size),滿足以下兩種情況時會觸發哈希表擴容:

  • 哈希表的LoadFactor>=1,并且服務器沒有執行bgsave 或者bgrewriteaof等后臺進程;(因為這些后臺進程對cpu使用非常高而且大量io讀寫,這時擴容影響性能)
  • 哈希表的LoadFactor>5;

底層源碼執行邏輯如下?

3.3Dict收縮

dict除了擴容以外,每次刪除元素時,也會對負載因子做檢查,當LoadFactor<0.1時,會做哈希表收縮;

實現邏輯如下

?3.4.Dict的rehash

不管是擴容還是收縮,必定會創建新的哈希表,導致哈希表的size和sizemask變化,而key的查詢與sizemask有關。因此必須對哈希表中的每一個key重新計算索引,插入新的哈希表,這個過程稱為rehash。

實現步驟如下:

1.分配空間
  • 擴展操作:為?ht[1]?分配空間,其大小是第一個大于等于?ht[0].used * 2?的 2 的冪。
  • 收縮操作:為?ht[1]?分配空間,其大小是第一個大于等于?ht[0].used?的 2 的冪。
2. 設置?rehashidx
把?dict?結構里的?rehashidx?設置為 0,這表明?rehash?操作正式開始。
3. 漸進式?rehash
Redis 采用漸進式?rehash?策略,避免一次性?rehash?大量鍵對服務器性能造成影響。具體步驟如下:
  • 在?rehash?期間,每次對字典執行增、刪、查、改操作時,程序除了完成指定操作之外,還會順帶將?ht[0]?哈希表在?rehashidx?索引上的所有鍵值對?rehash?到?ht[1],然后將?rehashidx?的值加 1。
  • 此外,Redis 還會在定時任務里對字典進行?rehash?操作,每次處理一定數量的鍵值對。
4. 遷移完成
當?ht[0]?中的所有鍵值對都被?rehash?到?ht[1]?之后,釋放?ht[0],將?ht[1]?設置為?ht[0],并創建一個新的空白哈希表作為?ht[1],同時將?rehashidx?設置為 -1,表明?rehash?操作結束。

4.ZipList

ziplist是一種特殊的"雙端鏈表",由一系列特殊編碼的連續內存塊組成。可以在任意一端進行壓入/彈出操作,并且"該操作的時間復雜度為0(1)。當列表或哈希元素數量較少且值較小時會采用這種結構。

4.1底層結構

4.1.1 ZipList

?4.1.2 Entry

ZipList中的Entiy井不像普通鏈表那樣記錄前后節點的指針,因為記錄兩個指針要占用16個字節,浪費內存。而是采用
了下面的結構:

previous_entry_length:前一節點的長度,占1個或5個字節。

  • 如果前一節點的長度小于254字節,則采用1個字節來保存這個長度值
  • 如果前一節點的長度大于254字書,則采用5個字節來保存這個長廢值,第一個字節為oxfe,后四個字節才是真實長度數據

encoding:編碼屬性,記錄contentent的數據類型(字符串還是整數)以及長度,占用1個,2個或5個字節


content:負責保存節點的數據,可以是字符串或整數


ZipList的Entry這樣設計不僅在節省內存空間的同時,保證數據的高效存儲和訪問,并且支持正向和反向遍歷等操作。

1.記錄前置節點長度(previous_entry_length)和當前節點長度(encoding)的字段,會根據實際長度動態調整。

2.反向遍歷:借助記錄前一個 Entry 的長度(previous_entry_length),能夠從后往前反向遍歷 ZipList。在某些場景下,反向遍歷是必要的,比如實現棧的操作時,就需要從后往前訪問元素。

4.2.Encoding編碼

ZipListEntry中的encoding編碼分為字符串和整數兩種

整數編碼:當?entry?存儲整數時,encoding?用 1 字節表示 。通過?encoding?可確定整數類型及實際大小

常見整數編碼如下:

  • ZIP_INT_8B?:對應二進制?11111110?,表示 8 位整數,content(數據部分)占 1 字節?
  • ZIP_INT_16B?:對應二進制?1100 0000?,表示 16 位整數,content?占 2 字節 。
  • ZIP_INT_24B?:對應二進制?1111 0000?,表示 24 位整數,content?占 3 字節 。
  • ZIP_INT_32B?:對應二進制?1110 0000?,表示 32 位整數,content?占 4 字節 。
  • ZIP_INT_64B?:對應二進制?1101 0000?,表示 64 位整數,content?占 8 字節 。
  • ZIP_INT_2C?:對應二進制?11111101?,表示 2 位有符號整數,實際取值范圍有限 。

字節數組(字符串)編碼:當?entry?存儲字符串時,根據字符串長度不同,encoding?有 3 種編碼方式,編碼的第一個字節前 2 位表示數據類型,后續位標識字符串實際長度:

總結:

1.判斷數據類型:encoding?第一個字節的前 2 位用于確定數據類型,二進制?11?開頭表示整數 ;非?11?開頭則是字節數組(字符串)。

2.解析字節數組長度:對于字節數組編碼,確定是字節數組類型后,根據前 2 位具體值判斷是哪種字符串編碼,再依據對應規則解析出字符串長度。

設計優勢

  • 節省內存:根據數據實際類型和長度選擇合適編碼,避免固定長度存儲造成的內存浪費。如存儲小整數或短字符串時,使用較少字節數編碼。
  • 快速解析:通過?encoding?編碼,可快速確定數據類型和長度,在讀取?entry?數據時提高解析效率 。

4.3.ZipList的連鎖更新問題

ZipList 的每個節點(Entry)包含一個記錄前一個節點長度的屬性?previous_entry_length?,該屬性占用 1 個或 5 個字節:
?
  • 若前一節點長度小于 254 字節,用 1 字節保存長度值。
  • 若前一節點長度大于等于 254 字節,用 5 字節保存長度值,第一個字節固定為?0xfe?,后 4 字節是真實長度數據。
?
假設存在 N 個連續的、長度在 250 - 253 字節之間的 Entry ,此時每個 Entry 的?previous_entry_length?都僅需 1 字節表示。若在隊首插入一個 254 字節的數據:
?
  1. 第二個 Entry 的?previous_entry_length?就得從 1 字節擴展為 5 字節 ,這使第二個 Entry 長度變為 254 字節。
  2. 第二個 Entry 長度變化后,第三個 Entry 的?previous_entry_length?也需從 1 字節變為 5 字節 ,依此類推,后續所有 Entry 都會因前一個長度的改變而改變 。
?
這種特殊情況下產生的連續多次空間擴展操作,就是連鎖更新(Cascade Update) 。不僅插入操作,刪除操作也可能引發連鎖更新。比如刪除一個節點后,相鄰節點記錄的前置節點長度發生變化,若涉及長度從小于 254 字節變為大于等于 254 字節(或反之),就可能引發連鎖更新。

5.QuickList

ZipList雖然節省內存,但申請內存必須是連續空間,如果內存占用過多,申請內存效率很低。所以當我們要存儲大量數據,超出ZipList最佳上限那么可以創建多個ZipList來分片存儲數據。

Redis3.2版本引入了新的數據結構QuickList,它是一個雙端鏈表,只不過鏈表中的每個節點都是ZipList

1.為了避免QuickList中的每個ZipList中entry過多,Redis提供了一個配置項:list-max-ziplist-size來限制。

  • 如果值為正,則代表ziplist的允許的entry個數的最大值
  • 如果值為負,則代表ziplist的最大內存大小,分5種情況:

1:每個ziplist的內存占用不能超過4kb

-2:每個ziplist的內存占用不能超過8kb

-3:每個ziplist的內存占用不能超過16kb

-4:每個ziplist的內存占用不能超過32kb

-5:每個ziplist的內存占用不能超過64kb

其默認值為-2:

2.除了控制ziplist的大小,quicklist-comprest還可以對節點的ZipList做壓縮。通過配置項ist-compress-depth來控制。因為鏈表一般都是從首尾訪問較多,所以首尾是不壓縮的。這個參數是控制首尾不壓縮的節點個數:

  • 0:特殊值,代表不壓縮
  • 1:標示quicklist的首尾各有1個節點不壓縮,中間節點壓縮
  • 2:標示quicklist的首尾各有2個節點不壓縮,中間節點壓縮

以此類推

默認值:

QuickList整體結構圖如下?

5.1總結

  1. quickList是一個節點為ZipList的雙端鏈表
  2. 節點采用ZipList,解決了傳統鏈表的內存占用問題
  3. 控制了ZipList大小,解決連續內存空間申請效率問題
  4. 中間節點可以壓縮,進一步節省了內存

6.SKipList

SkipList(跳表)是一種用于實現有序集合的數據結構。首先是鏈表,但與傳統鏈表相比有幾點差異:

  • 元素按照升序排列存儲
  • 節點可能包含多個指針,指針跨度不同。

6.1底層結構源碼

score:分值是用于排序的依據

ele:實際存儲的數據

backward:后退指針用于從尾向頭遍歷跳躍表

zskiplistLevel:層數組則用于實現多層索引結構,每個元素包含一個前進指針(forward)和跨度(span)。跨度表示從當前節點到下一個節點之間的元素數量

調表結構圖:

?6.2總結

  1. 調表是一個雙向鏈表,每個節點都包含score和ele值
  2. 節點按照score值排序,score值一樣按照ele字典排序
  3. 每個節點都可以包含多層指針,層數是1到32之間的隨機數
  4. 不同層指針到下一個節點的跨度不同,層級越高,跨度越大
  5. 增刪改查效率與紅黑樹基本一致,實現卻更簡單

7.RedisObject

Redis中的任意數據類型的鍵和值都會被封裝為一個RedisObject,也叫做Redis對象,源碼如下:

RedisObject是 Redis 實現多數據類型支持的關鍵結構。借助?type?和?encoding?字段,Redis 能夠靈活存儲和處理不同類型的數據,同時利用引用計數和 LRU/LFU 機制管理內存

7.1.Redis的編碼方式

Redis會根據存儲數據類型的不同,選擇不同的編碼方式,共包含11種不同類型:

String,List,Set,Zset,Hash每一種數據類型對應幾種不同編碼:

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

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

相關文章

C++ GPU并行計算開發實戰:利用CUDA/OpenCL加速粒子系統與流體模擬

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家、CSDN平臺優質創作者&#xff0c;高級開發工程師&#xff0c;數學專業&#xff0c;10年以上C/C, C#, Java等多種編程語言開發經驗&#xff0c;擁有高級工程師證書&#xff1b;擅長C/C、C#等開發語言&#xff0c;熟悉Java常用開…

LeetCode算法題(Go語言實現)_54

題目 給你兩個正整數數組 spells 和 potions &#xff0c;長度分別為 n 和 m &#xff0c;其中 spells[i] 表示第 i 個咒語的能量強度&#xff0c;potions[j] 表示第 j 瓶藥水的能量強度。 同時給你一個整數 success 。一個咒語和藥水的能量強度 相乘 如果 大于等于 success &a…

內網穿透快解析免費開放硬件集成SDK

一、行業問題 隨著物聯網技術的發展&#xff0c;符合用戶需求的智能硬件設備被廣泛的應用到各個領域&#xff0c;而智能設備的遠程運維管理也是企業用戶遇到的問題 二、快解析內網穿透解決方案 快解析是一款內網穿透產品&#xff0c;可以實現內網資源在外網訪問&#xff0c;…

Python+Word實現周報自動化的完整流程

一、技術方案概述 自動化報表解決方案基于以下技術組件&#xff1a; Python 作為核心編程語言python-docx 庫用于處理 Word 文檔pandas 庫用于數據處理和分析matplotlib 或 plotly 庫用于數據可視化Word 模版作為報表的基礎格式 這種方案的優勢在于&#xff1a;保留了 Word 文…

elastic/go-elasticsearch與olivere/elastic

在 Go 語言中&#xff0c;與 Elasticsearch 交互的客戶端庫有多種選擇&#xff0c;其中 github.com/elastic/go-elasticsearch/v8 和 github.com/olivere/elastic/v7 是兩個常用的庫。這兩個庫的功能和用途有一些差異&#xff0c;以下是它們的詳細對比&#xff1a; 1. github.c…

deepseek + kimi制作PPT

目錄 一、kimi簡介二、deepseek生成內容三、生成PPT四、編輯PPT 一、kimi簡介 kimi是一款只能ppt生成器&#xff0c;擅長將文本內容生成PPT。 在這里&#xff0c;??DeepSeek 負責內容生成與邏輯梳理??&#xff0c;??Kimi 優化表達與提供設計建議??。 二、deepseek生…

【八大排序】冒泡、直接選擇、直接插入、希爾、堆、歸并、快速、計數排序

目錄 一、排序的介紹二、排序算法的實現2.1 直接插入排序2.2 希爾排序2.3 直接選擇排序2.4 堆排序2.5 冒泡排序2.6 快速排序2.7 歸并排序2.8 比較排序算法的性能展示2.9 計數排序 個人主頁<— 數據結構專欄<— 一、排序的介紹 我們的生活中有很多排序&#xff0c;比如像…

linux 查詢目錄文件大小

? 在 Linux 系統中&#xff0c;準確地掌握目錄和文件的大小對于磁盤空間管理至關重要。?本文將詳細介紹如何使用 du&#xff08;disk usage&#xff09;命令逐層查看目錄和文件的大小&#xff0c;并結合 sort 命令對結果進行排序&#xff0c;以便有效地識別和管理占用…

如何簡單幾步使用 FFmpeg 將任何音頻轉為 MP3?

在多媒體處理領域&#xff0c;FFmpeg 以其強大的功能和靈活性而聞名。無論是視頻編輯、音頻轉換還是流媒體處理&#xff0c;它都是專業人士和技術愛好者的首選工具之一。在這篇文章中簡鹿辦公將重點介紹如何使用 FFmpeg 進行音頻格式轉換&#xff0c;提供一些常用的轉換方式&am…

通信信號分類識別

通信信號分類識別 AlexNet網絡識別InceptionV3、ResNet-18、ResNet-50網絡識別 采用短時傅里葉變換將一維信號轉換為二維信號&#xff0c;然后采用經典神經網絡進行識別 支持識別BASK,BFSK,BPSK,QPSK,8PSK,QAM和MSK。 AlexNet網絡識別 在這里插入圖片描述 InceptionV3、Re…

TPshop項目-服務器環境部署(部署環境/服務,檢查部署環境/服務,上傳TPshop項目到服務器,配置文件的更改,安裝TPshop)

目錄 部署環境/服務&#xff0c;檢查部署環境/服務 檢查部署環境/服務 上傳TPshop項目到服務器&#xff0c;配置文件的更改&#xff0c;安裝TPshop 部署環境/服務&#xff0c;檢查部署環境/服務 一般部署環境&#xff0c;會根據開發寫的部署文檔來一步一步的部署環境。 部署…

C++入門基礎:命名空間,缺省參數,函數重載,輸入輸出

命名空間&#xff1a; C語言是基于C語言的&#xff0c;融入了面向對象編程思想&#xff0c;有了很多有用的庫&#xff0c;所以接下來我們將學習C如何優化C語言的不足的。 在C/C語言實踐中&#xff0c;在全局作用域中變量&#xff0c;函數&#xff0c;類會有很多&#xff0c;這…

緩存 --- Redis基本數據類型

緩存 --- Redis基本數據類型 Redis Intro5種基礎數據類型 Redis Intro Redis&#xff08;Remote Dictionary Server&#xff09;是一款開源的高性能鍵值存儲系統&#xff0c;常用于緩存、消息中間件和實時數據處理場景。以下是其核心特點、數據類型及典型使用場景&#xff1a; …

Redis命令——list

列表類型是用來存儲多個有序的字符串&#xff0c;列表中的每個字符串稱為元素&#xff08;element&#xff09;&#xff0c;?個列表最多可以存儲個元素 在 Redis 中&#xff0c;可以對列表兩端插入&#xff08;push&#xff09;和彈出&#xff08;pop&#xff09;&#xff0c;…

Android Jetpack Compose 狀態管理解析:remember vs mutableStateOf,有啥不一樣?為啥要一起用?

&#x1f331;《Jetpack Compose 狀態管理解析&#xff1a;remember vs mutableStateOf&#xff0c;有啥不一樣&#xff1f;為啥要一起用&#xff1f;》 在 Jetpack Compose 的世界里&#xff0c;UI 是響應式的。這意味著當狀態發生變化時&#xff0c;UI 會自動重組&#xff0…

使用 PCL 和 Qt 實現點云可視化與交互

下面我將介紹如何結合點云庫(PCL)和Qt框架(特別是QML)來實現點云的可視化與交互功能&#xff0c;包括高亮選擇等效果。 1. 基本架構設計 首先需要建立一個結合PCL和Qt的基本架構&#xff1a; // PCLQtViewer.h #pragma once#include <QObject> #include <pcl/point…

mybatis plus打印sql日志到指定目錄

1、mybatis plus打印sql日志 參考文檔&#xff1a;mybatis plus打印sql日志_mybatisplus日志打印-CSDN博客 2、修改 修改InfoLevelLogger Override public void debug(String s) {// 修改這里logger.info(s);log.debug(s); } 增加&#xff1a;log.debug(s); 修改logback.x…

vue3 watch和watchEffect 的用法和區別

在 Vue 3 里&#xff0c;watch 和 watchEffect 都是用于響應式數據變化的 API&#xff0c;但它們在使用方法和應用場景上存在差異。下面詳細介紹它們的用法和區別。 用法 watch watch 用于監聽特定的響應式數據源&#xff0c;當數據源發生變化時&#xff0c;會執行相應的回調…

Qt中修改了UI設計文件后編譯不生效問題的解決辦法

復制工程過來后&#xff1a; 1、刪除build文件 2、刪除.user文件&#xff0c;恢復為文件最初的那樣 3、執行make distclean,刪除所有由先前構建過程生成的文件 4、再次打開工程&#xff0c;修改ui文件編譯生效&#xff01;

EtherCAT轉ProfiNet邊緣計算網關配置優化:汽車制造場景下PLC與機器人協同作業案例

1.行業背景與需求分析 智能汽車焊裝車間是汽車制造的核心工藝環節&#xff0c;某德國豪華品牌在其上海MEB工廠新建的焊裝車間中&#xff0c;采用西門子S7-1500PLC作為ProfiNet主站&#xff0c;負責整線協調與質量追溯&#xff1b;同時部署KUKAKR1500Titan機器人&#xff08;Eth…