redis中的hash

Redis中的hash是什么

Hash: 哈希,也叫散列,是一種通過哈希函數將鍵映射到表中位置的數據結構,哈希函數是關鍵,它把鍵轉換成索引。

Redis Hash(散列表)是一種 field-value pairs(鍵值對)集合類型,類似于 Python 中的字典、Java 中的 HashMap。一個 field 對應一個value.

Hash沖突:兩個不同的key可能會映射到同一個位置去,這種問題我們叫做哈希沖突,或者哈希碰撞
Hash沖突解決方法:主要有兩種兩種方法,開放定址法和鏈地址法。

開放定址法 :
在開放定址法中所有的元素都放到哈希表里,當一個關鍵字key用哈希函數計算出的位置沖突了,則按照某種規則找到一個沒有存儲數據
的位置進行存儲。這里的規則有三種:線性探測、二次探測、雙重探測。

鏈地址法:
開放定址法中所有的元素都放到哈希表里,鏈地址法中所有的數據不再直接存儲在哈希表中,哈希表中存儲一個指針,沒有數據映射這個位置時,這個指針為空,有多個數據映射到這個位置時,我們把這些沖突的數據鏈接成一個鏈表,掛在哈希表這個位置下面,鏈地址法也叫做拉鏈法或者哈希桶。
在這里插入圖片描述

Redis 的散列表 dict 由數組 + 鏈表構成,數組的每個元素占用的槽位叫做哈希桶,當出現散列沖突的時候就會在這個桶下掛一個鏈表,用“拉鏈法”解決散列沖突的問題。
簡單地說就是將一個 key 經過散列計算均勻的映射到散列表上。
在這里插入圖片描述

Hash數據類型底層存儲數據結構實際上有兩種。
1.dict結構。
2.在7.0版本之前使用ziplist,之后被listpack代替。

什么是listPack

Redis 在 5.0 新設計一個數據結構叫 listpack,目的是替代壓縮列表,它最大特點是 listpack 中每個節點不再包含前一個節點的長度了,壓縮列表每個節點正因為需要保存前一個節點的長度字段,就會有連鎖更新的隱患.

listpack 也叫緊湊列表,它的特點就是用一塊連續的內存空間來緊湊地保存數據,同時為了節省內存空間,listpack 列表項使用了多種編碼方式,來表示不同長度的數據,這些數據包括整數和字符串。

Redis源碼對于listpack的解釋為 A lists of strings serialization format,一個字符串列表的序列化格式,也就是將一個字符串列表進行序列化存儲。Redis listpack可用于存儲字符串或者是整型

為了避免 ziplist 引起的連鎖更新問題,listpack 中的每個列表項不再像 ziplist 列表項那樣,保存其前一個列表項的長度,它只會包含三個方面內容,分別是當前元素的編碼類型(entry-encoding)、元素數據 (entry-data),以及編碼類型和元素數據這兩部分的長度 (entry-len),如下圖所示。

在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述

  • slen,不同于ziplist,listpackEntry 中的 len 記錄的是當前 entry 的編碼類型和長度,而非上一個entry的長度。
  • *sval,當存儲的數據為字符串時,使用該成員變量
  • lval,當存儲的數據為整數,使用該成員變量
    通常情況下使用dict數據結構存儲數據,每個field-va1 ue pairs構成一個dictEntry節點來保存。

只有同時滿足以下兩個條件的時候,才會使用listpack(7.O版本之前使用ziplist)數據結構來代替dict存儲,把key-value鍵值對按照
field在前value在后,緊密相連的方式放到一次把每個鍵值對放到列表的表尾。

  • ·每個鍵值對中的field和value的字符串字節大小都小于hash-max-listpack-value配置的值(默認64)。
  • ·field-value pairs鍵值對數量小于hash-max-listpack-entries配置的值(默認512)。

每次向散列表寫數據的時候,都會調用t_hash.c中的hashTypeConvertListpack()函數來判斷是否需要轉換底層數據結構。

當插入和修改的數據不滿足以上兩個條件時,就把散列表底層存儲結構轉換成dict結構。需要注意的是,不能由dict退化成listpack。

雖然使用了listpack就無法實現O(1)時間復雜度操作數據,但是使用listpack能大大減少內存占用,而且數據量比較,小,性能并不是有太大差異。

Redis數據庫就是一個全局散列表。正常情況下,我只會使用ht_table[0]散列表,圖2-20是一個沒有進行rehash狀態下的字典。
在這里插入圖片描述

dict字典在源代碼dict.h中使用dict結構體表示。
在這里插入圖片描述

1.dictType *type

  • 這是一個指向 dictType 結構的指針,dictType 通常定義了哈希表的操作接口,包括哈希函數、鍵值的比較函數、釋放鍵值的函數等。這使得哈希表可以針對不同的數據類型進行定制化操作。

2.dictEntry **ht_table[2]

  • 這是一個包含兩個指針的數組,每個指針指向一個哈希表(ht_table[0] 和 ht_table[1])。這種設計是為了支持漸進式重新哈希(Incremental Rehashing)。當哈希表的負載因子(即 ht_used[0] / ht_table[0] 的大小)超過某個閾值時,Redis 會開始將數據從 ht_table[0] 重新哈希到 ht_table[1]。這種漸進式重新哈希可以避免一次性重新哈希帶來的性能問題。
  • dictEntry是哈希表中存儲鍵值對的結構,通常包含鍵、值和指向下一個哈希沖突的指針。

3.unsigned long ht_used[2]

  • 這是一個包含兩個元素的數組,分別記錄 ht_table[0] 和 ht_table[1] 中存儲的鍵值對數量。ht_used[0] 表示 ht_table[0] 中的元素數量,ht_used[1] 表示 ht_table[1] 中的元素數量。

4.long rehashidx

  • 這是一個索引值,用于記錄當前重新哈希操作的進度。當哈希表正在進行重新哈希時,rehashidx 表示當前正在處理的桶索引。如果 rehashidx 為 -1,表示沒有正在進行的重新哈希操作。

5.int16_t pauserehash

  • 這是一個標志位,用于控制重新哈希操作是否暫停。在某些情況下,Redis 可能需要暫停重新哈希操作,以避免對性能的影響。例如,當 Redis 正在執行 RDB(Redis Database Backup)操作時,可能會暫停重新哈希。

6.signed char ht_size_exp[2]

  • 這是一個包含兩個元素的數組,分別記錄 ht_table[0] 和 ht_table[1] 的大小指數。Redis 的哈希表大小通常是 2 的冪次方,ht_size_exp[0] 和 ht_size_exp[1] 分別表示 ht_table[0] 和 ht_table[1] 的大小指數。例如,如果 ht_size_exp[0] 為 4,則 ht_table[0] 的大小為 24=16。
    在這里插入圖片描述

·*key指針指向鍵值對中的鍵,實際上指向一個SDS實例。
雖然Redis是用c實現的,但是他們的string結構并不相同,Redis中的字符串是可以修改的字符串,在內存中它是以字節數組的形式存在的Redis 的。字符串叫sds,也就是 Simple Dynamic String,是一個帶長度信息的字節數組
在這里插入圖片描述

·v是一個uon聯合體,表示鍵值對中的值,同一時刻只有一個字段有值,用聯合體的目是節省內存。

  • ·val 如果值是非數字類型,那就使用這個指針存儲。
  • ·uint64tu64, 值是無符號整數的時候使用這個字段存儲。
  • ·int64ts64, 值是有符號整數時,使用該字段存儲。
  • ·dob1ed, 值是浮點數是,使用該字段存儲。
    *next指向下一個節點指針,當散列表數據增加,可能會出現不同的key得到的哈希值相等,也就是說多個key對應在一個哈希桶里面,這就是哈希沖突。Redis使用拉鏈法,也就是用鏈表將數據串起來。

為什么說v是一個uo聯合體,表示鍵值對中的值,同一時刻只有一個字段有值,用聯合體的目是節省內存?

1.節省內存

  • union 聯合體是一種特殊的數據結構,它允許在同一個內存位置存儲不同的數據類型。所有成員共享同一塊內存,因此在任何時刻,union 中只有一個成員有值。寫入一個成員會覆蓋其他成員的內容.
  • 在 dictEntry 中,v 的大小由其最大的成員決定。例如,void *val、uint64_t u64、int64_t s64 和 double d 的大小都是 8 字節(在 64 位系統中)。因此,v 的大小也是 8 字節,無論存儲哪種類型的數據,都不會占用額外的內存。

2.靈活存儲不同類型的數據

  • Redis 的哈希表需要存儲多種類型的數據,包括指針、整數和浮點數。通過使用 union,v 可以靈活地存儲這些不同類型的數據,而不需要為每種類型分配單獨的內存空間。
  • 這種設計使得 dictEntry 能夠高效地處理不同類型的數據,同時保持內存占用的最小化。

為啥ht_table[2]存放了兩個指向散列表的指針?用一個散列表不就夠了嗎?

默認使用ht_tab:1e[0]進行讀寫數據,當散列表的數據越來越多的時候,哈希沖突嚴重會出現哈希桶的鏈表比較長,導致查詢性能下降。

為了唯快不破想了一個法子,當散列表保存的鍵值對太多或者太少的時候,需要通過「rehash(重新散列)對散列表進行擴容或者縮容。

擴容和縮容

1.為了高性能,減少哈希沖突,會創建一個大小等于ht_used[0]*2的散列表ht_tab1e[1],也就是每次擴容時根據散列表ht_tab1e[0]已使用空間擴大一倍創建一個新散列表ht_tab1e[1]。反之,如果是縮容操作,就根據ht_tab1e[0]已使用空間縮小一倍創建一個新的散列表。

2.重新計算鍵值對的哈希值,得到這個鍵值對在新散列表ht_tab1e[1]的桶位置,將鍵值對遷移到新的散列表上。

3.所有鍵值對遷移完成后,修改指針,釋放空間。具體是把ht_tab1e[0]指針指向擴容后的散列表,回收原來小的散列表內存空間,ht_tab1e[1]指針指向NULL,為下次擴容或者縮容做準備。

什么時候會觸發擴容?

1.當前沒有執行BGSAVE或者BGREWRITEAOF命令,同時負載因子大于等于1。也就是當前沒有RDB子進程和AOF重寫子進程在工作,畢競這倆操作還是比較容易對性能造成影響的,就不擴容火上澆油了。

2.正在執行BGSAVE或者BGREWRITEA0F命令,負載因子大于等于5。(這時候哈希沖突太嚴重了,再不觸發擴容,查詢效率太慢了)。負載因子=散列表存儲dictEntry節點數量/散列表桶個數。完美情況下,每個哈希桶存儲一個dictEntry節點,這時候負載因子=1。

BGSAVE 和 BGREWRITEAOF 是 Redis 中的兩個重要命令,它們分別用于實現 Redis 的兩種持久化機制:RDB(Redis Database Backup) 和 AOF(Append Only File)。這兩種機制用于將內存中的數據持久化到磁盤,以防止數據丟失。

BGREWRITEAOF 命令觸發一個后臺進程(子進程)來重寫 AOF 文件,以壓縮和優化 AOF 文件的大小,同時避免阻塞主進程。

需要遷移數據量很大,rehash操作豈不是會長時間阻塞主線程?

為了防止阻塞主線程造成性能問題,我并不是一次性把全部的key遷移,而是分多次,將遷移操作分散到每次情求中,避免集中式rehash造成長時間阻塞,這個方式叫漸進式rehash。

在執行漸進式rehash期間,dict會同時使用ht_table[0]和ht_table[1]兩個散列表,rehash具體步如下:

1.將rehashidxi設置成0,表示rehash開始執行。

2.在rehash期間,服務端每次處理客戶端對dict散列表執行添加、查找、刪除或者更新操作時,除了執行指定操作以外,還會檢查當前dict是否處于rehash狀態,是的話就把散列表ht_table[0]上索引位置為rehashidx的桶的鏈表的所有鍵值對rehash到散列表ht_table[1]上,這個哈希桶的數據遷移完成,就把rehashidx的值加1,表示下一次要遷移的桶所在位置。

3.當所有的鍵值對遷移完成后,將rehashidxi設置成-1,表示rehash操作已完成。

rehash過程中,字典的刪除、查找、更新和添加操作,要從兩個ht_table都搞一遍嗎?

刪除、修改和查找可能會在兩個散列表進行,第一個散列表沒找到就到第二個散列表進行查找。但是增加操作只會在新的散列表上進行。

如果請求比較少,豈不是會很長時間都要使用兩個散列表?

在Redis Server園初始化時,會注冊一個時間事件,定時執行serverCron函數,其中包含rehash操作用于輔助遷移,避免這個問題。
serverCron函數除了做rehash以外,主要處理如下工作。

  • 過期key刪除。
  • 監控服務運行狀態。
  • 更新統計數據。
  • 漸進式rehash。
  • 觸發BGSAVE/AOF rewrite以及停止子進程。
  • 處理客戶端超時。

擴容過程:

在 Redis 的哈希表(Hash)rehash 過程中,數據遷移是分步驟、漸進式進行的,這樣做是為了避免一次性遷移大量數據造成的服務器阻塞。以下是 rehash 過程中數據遷移的具體步驟:
1. 創建新的哈希表
當觸發 rehash 條件時(例如,負載因子超過設定閾值),Redis 會創建一個新的哈希表 ht[1],其大小通常是 ht[0](當前哈希表)大小的兩倍。

2. 初始化 rehash 索引
在 dict 結構中,rehashidx 被初始化為 0。這個索引用于跟蹤 rehash 過程中已經遷移的桶的數量。

3. 漸進式遷移
Redis 使用一個定時任務或者在處理命令時的空閑時間來執行 rehash 操作。在每次 rehash 操作中,會遷移一定數量的桶(通常是一個或幾個),而不是一次性遷移所有桶。具體步驟如下:

  • 從 ht[0] 中取出一個桶(通過 rehashidx 定位)。
  • 遍歷桶中的所有 dictEntry(如果有鏈表,則遍歷鏈表中的所有條目)。
  • 重新計算每個 dictEntry 的哈希值,并將其插入到 ht[1] 中對應的桶中。
  • 更新 rehashidx,指向下一個需要遷移的桶。

4. 更新 rehash 狀態
每次遷移一定數量的桶后,Redis 會更新 rehashidx,使其指向下一個桶。這樣,下一次 rehash 操作可以從上次停止的地方繼續。

5. 完成 rehash
當 rehashidx 超過 ht[0] 的大小時,表示所有桶都已遷移到 ht[1]。此時,Redis 會進行以下操作:

  • 將 ht[1] 設置為新的 ht[0],即讓新的哈希表成為當前使用的哈希表。
  • 釋放舊的 ht[0] 占用的內存。
  • 將 rehashidx 重置為 -1,表示 rehash 操作已完成。

6. 處理命令時的 rehash
在 rehash 過程中,Redis 仍然可以處理客戶端的命令。當命令涉及到哈希表操作時,Redis 會同時在 ht[0] 和 ht[1] 中查找或插入數據,確保數據的一致性。
通過這種漸進式的 rehash 機制,Redis 能夠在不影響服務器性能的情況下,平滑地完成哈希表的擴容操作。

BGSAVE和BGREWRITEAOF是什么意思?

BGSAVE 和 BGREWRITEAOF 是 Redis 中的兩個重要命令,它們分別用于實現 Redis 的兩種持久化機制:RDB(Redis Database Backup) 和 AOF(Append Only File)。這兩種機制用于將內存中的數據持久化到磁盤,以防止數據丟失。
1. BGSAVE(RDB 持久化)
RDB 持久化

  • 定義:RDB 是一種快照持久化機制,它會定期將內存中的數據集快照保存到磁盤上的一個 RDB 文件中。

  • 優點:

    • 數據恢復速度快:RDB 文件是一個緊湊的二進制文件,恢復數據時速度較快。
    • 適合全量備份:適合用于全量數據備份,可以方便地將數據備份到其他存儲介質或遠程服務器。
  • 缺點:

  • 數據丟失風險:如果 Redis 服務器在兩次快照之間發生故障,可能會丟失最后一次快照之后的數據。

  • 阻塞風險:生成 RDB 文件的過程可能會阻塞主進程,尤其是在數據量較大時。

BGSAVE 命令

  • 作用:觸發一個后臺進程(子進程)來生成 RDB 文件,而主進程繼續處理客戶端請求,避免阻塞。

  • 執行過程:

    a.主進程創建一個子進程。
    b.子進程將當前內存中的數據集快照寫入到一個新的 RDB 文件中。
    c.子進程完成寫入后,用新生成的 RDB 文件替換舊的 RDB 文件。

  • 觸發方式:

    • 手動觸發:可以通過命令 BGSAVE 手動觸發。
    • 自動觸發:Redis 會根據配置的策略自動觸發 BGSAVE。例如,可以配置 Redis 每隔一定時間或在數據變更達到一定數量時自動執行 BGSAVE。

2. BGREWRITEAOF(AOF 持久化)
AOF 持久化

  • 定義:AOF 是一種日志持久化機制,它會將每個寫操作命令追加到一個日志文件(AOF 文件)中。
  • 優點:
    • 數據安全性高:AOF 文件記錄了每個寫操作,即使 Redis 服務器發生故障,也可以通過重放 AOF 文件中的命令恢復數據。
    • 可配置性強:可以配置不同的同步策略(如每秒同步一次、每次寫操作同步一次等),以平衡性能和數據安全性。
  • 缺點:
    • 文件體積大:AOF 文件會不斷增長,可能會占用大量磁盤空間。
    • 恢復速度慢:AOF 文件是文本格式,恢復數據時速度相對較慢。

BGREWRITEAOF 命令

  • 作用:觸發一個后臺進程(子進程)來重寫 AOF 文件,以壓縮和優化 AOF 文件的大小,同時避免阻塞主進程。

  • 執行過程:

    a.主進程創建一個子進程。
    b.子進程讀取當前內存中的數據集,并將其轉換為一系列優化后的寫操作命令,寫入到一個新的 AOF 文件中。
    c.子進程完成寫入后,用新生成的 AOF 文件替換舊的 AOF 文件。

  • 觸發方式:

    • 手動觸發:可以通過命令 BGREWRITEAOF 手動觸發。
    • 自動觸發:Redis 會根據配置的策略自動觸發 BGREWRITEAOF。例如,可以配置 Redis 在 AOF 文件大小達到一定比例時自動執行 BGREWRITEAOF。

總結

  • BGSAVE:用于生成 RDB 文件,適合全量數據備份,恢復速度快,但可能會丟失最后一次快照之后的數據。
  • BGREWRITEAOF:用于重寫 AOF 文件,優化 AOF 文件的大小,數據安全性高,但文件體積大,恢復速度相對較慢。
    這兩種持久化機制可以單獨使用,也可以結合使用,具體選擇取決于應用場景和對數據安全性的要求。

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

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

相關文章

彈簧質點系統(C++實現)

本文實現一個簡單的物理算法:彈簧質點系統(Mass-Spring System)。這是一個經典的物理模擬算法,常用于模擬彈性物體(如布料、彈簧等)的行為。我們將使用C來實現這個算法,并結合鏈表數據結構來管理…

領域大模型

領域技術標準文檔或領域相關數據是領域模型Continue PreTrain的關鍵。 現有大模型在預訓練過程中都會加入書籍、論文等數據,那么在領域預訓練時這兩種數據其實也是必不可少的,主要是因為這些數據的數據質量較高、領域強相關、知識覆蓋率(密度…

Wincc項目被鎖定無法打開

Wincc項目被鎖定無法打開 解決方法 解決方法 一般這種情況是因為項目打開的時候直接關機導致的。 刪除項目文件夾的ProjectOpened.lck的文件夾即可 然后即可正常打開項目

SpringBoot3筆記

簡介: springboot整合了springframework,整合了許多配置,讓我們能夠快速創建一個以springframework為基礎的項目。 問題: 到目前為止,你已經學習了多種配置Spring程序的方式。但是無論使用XML、注解、Java配置類還是…

DeepSeek和文心一言的區別

文章目錄 1.開發公司:2.應用場景:3.訓練數據:4.模型架構:5.技術特點:6.語言風格:7.開源性:8.界面與用戶體驗: 1.開發公司: DeepSeek 由杭州深度求索人工智能基礎技術研究…

Windows 10 安裝Mysql 8

安裝準備 下載 MySQL Windows ZIP版(無安裝程序): 進入官網:https://dev.mysql.com/downloads/mysql/ 選擇 Windows → 下載 ZIP Archive,例如: mysql-8.0.34-winx64.zip 如果你的電腦沒有安裝 VC Redi…

ARM分揀機vs傳統PLC:實測數據揭示的4倍效率差

在蘇州某新能源汽車零部件倉庫,凌晨3點的分揀線上依然燈火通明。8臺搭載ARM Cortex-A72處理器的智能分揀機正在以每秒3件的速度處理著形狀各異的電池包組件,它們通過MES系統接收訂單信息,自主規劃最優路徑,將不同規格的零部件精準…

使用python訪問mindie部署的vl多模態模型

說明 今天使用mindie1.0部署了qwen2_7b_vl模型,測試過程出現一些問題,這里總結下。 問題1:transformers版本太低 報錯信息: [ERROR] [model_deploy_config.cpp:159] Failed to get vocab size from tokenizer wrapper with ex…

vscode 跳轉失敗之c_cpp_properties.json解析

{"configurations": [{"name": "Linux", // 配置名稱,對應當前平臺,VS Code 中可選"includePath": ["${workspaceFolder}/**", // 包含當前工作區下所有文件夾的頭文件(遞歸&…

飛速(FS)解決方案驗證實驗室搬遷升級,賦能客戶技術服務

飛速(FS)解決方案驗證實驗室近日順利完成搬遷升級,標志著飛速(FS)在解決方案可行性驗證、質量保障以及定制化需求支持方面邁上新臺階,進一步提升了產品競爭力和客戶信任度。 全新升級的實驗室定位為技術驗證…

安裝kerberos認證的cdh環境

1、服務端安裝 1.1 安裝wget yum -y install wget 由于本地已安裝過wget,所以顯示Nothing to do 1.2 進入 home 目錄 cd /home 1.3 下載centos6.7.iso文件,并掛載 wget https://archive.kernel.org/centos-vault/6.7/isos/x86_64/CentOS-6.7-x86_64…

MySQL基礎 [六] - 內置函數+復合查詢+表的內連和外連

內置函數一般要用select調用 內置函數 日期函數 current_date函數 current_date函數用于獲取當前的日期。如下: current_time函數 current_time函數用于獲取當前的時間。如下: now函數 now函數用于獲取當前的日期時間。如下: date函數 dat…

CS內網滲透 - 如何通過冰蝎 Webshell 上線 Weblogic 服務器到 Cobalt Strike 并繞過殺軟檢測(360、火絨)?

目錄 1. 冰蝎連接上 Weblogic 服務器如何上線到 Cobalt Strike 2. 服務器安裝殺毒工具如何繞過殺軟上線到 Cobalt Strike 2.1 殺軟對 Webshell 命令執行的檢測及繞過 2.2 殺軟對 Cobalt Strike 上線木馬的檢測及繞過 2.3 殺軟對這兩方面的限制及綜合繞過 3. 如何生成免殺…

[ctfshow web入門] web10

前置知識 cookie Cookie是網站存儲在瀏覽器中的小數據片段,用于識別用戶、保持登錄狀態或記住偏好設置。 也就是說,我以會員A的身份登錄了網站,網站會發送一段cookie(會員卡)給我,上面寫著會員卡A,下一次我再訪問&am…

藍橋杯:日期統計

文章目錄 問題描述解法一遞歸解法二:暴力破解 問題描述 首先我們要了解什么是子序列,就是一個序列之中可以忽略元素但是不能改變順序之后獲得的序列就叫做子序列。 如"123"就是"11234"的子序列而不是"11324"的子序列 解法…

藍橋杯 C/C++ 組歷屆真題合集速刷(一)

一、1.單詞分析 - 藍橋云課 &#xff08;模擬、枚舉&#xff09;算法代碼&#xff1a; #include <bits/stdc.h> using namespace std;int main() {string s;cin>>s;unordered_map<char,int> mp;for(auto ch:s){mp[ch];}char result_charz;int max_count0;fo…

重塑知識的引擎:人工智能如何改變知識的生產與傳播

一、引言&#xff1a;知識的邊界正在被人工智能重構 千百年來&#xff0c;人類對于“知識”的獲取方式一直遵循著某種路徑依賴&#xff1a;感知現實 → 歸納總結 → 文字表達 → 教育傳承 → 學術沉淀。這一過程復雜而緩慢&#xff0c;需要經過代際的努力才能實現知識的積累與…

list的底層:

我們之前講解了list&#xff0c;今天我們來看一下list的底層&#xff1a; list底層是一個雙向帶頭循環的鏈表&#xff0c;之前我們學習數據結構的時候&#xff0c;我們就學過。 迭代器的封裝&#xff1a; 我們看這個圖片&#xff0c;我們的鏈表的指針可以達到鏈表的迭代器能力…

遵循IEC62304YY/T0664:確保醫療器械軟件生命周期合規性

一、EC 62304與YY/T 0664的核心定位與關系 IEC 62304&#xff08;IEC 62304&#xff09;是國際通用的醫療器械軟件生命周期管理標準&#xff0c;適用于所有包含軟件的醫療器械&#xff08;如嵌入式軟件、獨立軟件、移動應用等&#xff09;&#xff0c;其核心目標是確保軟件的安…

【next函數python】`next()`函數

在Python中&#xff0c;next()函數結合生成器表達式用于高效地查找序列中第一個符合條件的元素。以下是如何理解和編寫類似代碼的步驟&#xff1a; 1. 生成器表達式 生成器表達式&#xff08;如 (e for e in energy3 if e ! 0)&#xff09;是一種惰性計算的迭代結構。它不會一…