一文搞懂 Redis 架構演化之路

来源:https://www.cnblogs.com/88223100/archive/2022/07/26/An-article-to-understand-the-evolution-of-Redis-architecture.html
-Advertisement-
Play Games

現如今 Redis 變得越來越流行,幾乎在很多項目中都要被用到,不知道你在使用 Redis 時,有沒有思考過,Redis 到底是如何穩定、高性能地提供服務的? 我使用 Redis 的場景很簡單,只使用單機版 Redis 會有什麼問題嗎? 我的 Redis 故障宕機了,數據丟失了怎麼辦?如何能保證我的... ...


現如今 Redis 變得越來越流行,幾乎在很多項目中都要被用到,不知道你在使用 Redis 時,有沒有思考過,Redis 到底是如何穩定、高性能地提供服務的?

  • 我使用 Redis 的場景很簡單,只使用單機版 Redis 會有什麼問題嗎?
  • 我的 Redis 故障宕機了,數據丟失了怎麼辦?如何能保證我的業務應用不受影響?
  • 為什麼需要主從集群?它有什麼優勢?
  • 什麼是分片集群?我真的需要分片集群嗎?
  • ...

如果你對 Redis 已經有些瞭解,肯定也聽說過「數據持久化、主從複製、哨兵、分片集群」這些概念,它們之間又有什麼區別和聯繫呢?

如果你存在這樣的疑惑,這篇文章,我會從 0 到 1,再從 1 到 N,帶你一步步構建出一個穩定、高性能的 Redis 集群。

在這個過程中,你可以瞭解到 Redis 為了做到穩定、高性能,都採取了哪些優化方案,以及為什麼要這麼做?

掌握了這些原理,這樣平時你在使用 Redis 時,就能夠做到「游刃有餘」。

從最簡單的開始:單機版 Redis

首先,我們從最簡單的場景開始。

假設現在你有一個業務應用,需要引入 Redis 來提高應用的性能,此時你可以選擇部署一個單機版的 Redis 來使用,就像這樣:

 

 

這個架構非常簡單,你的業務應用可以把 Redis 當做緩存來使用,從 MySQL 中查詢數據,然後寫入到 Redis 中,之後業務應用再從 Redis 中讀取這些數據,由於 Redis 的數據都存儲在記憶體中,所以這個速度飛快。

如果你的業務體量並不大,那這樣的架構模型基本可以滿足你的需求。是不是很簡單?

隨著時間的推移,你的業務體量逐漸發展起來了,Redis 中存儲的數據也越來越多,此時你的業務應用對 Redis 的依賴也越來越重。

突然有一天,你的 Redis 因為某些原因宕機了,這時你的所有業務流量,都會打到後端 MySQL 上,MySQL 壓力劇增,嚴重的話甚至會壓垮 MySQL。

 

 

這時你應該怎麼辦?

我猜你的方案肯定是,趕緊重啟 Redis,讓它可以繼續提供服務。

但是,因為之前 Redis 中的數據都在記憶體中,儘管你現在把 Redis 重啟了,之前的數據也都丟失了(假設沒開持久化)。重啟後的 Redis 雖然可以正常工作,但是由於 Redis 中沒有任何數據,業務流量還是都會打到後端 MySQL 上,MySQL 的壓力還是很大。

有沒有什麼好的辦法解決這個問題?

既然 Redis 只把數據存儲在記憶體中,那是否可以把這些數據也寫一份到磁碟上呢?

如果採用這種方式,當 Redis 重啟時,我們把磁碟中的數據快速「恢復」到記憶體中,這樣它就可以繼續正常提供服務了。

是的,這是一個很好的解決方案,這個把記憶體數據寫到磁碟上的過程,就是「數據持久化」。

數據持久化:有備無患

現在,你設想的 Redis 數據持久化是這樣的:

 

 

但是,數據持久化具體應該怎麼做呢?

我猜你最容易想到的一個方案是,Redis 每一次執行寫操作,除了寫記憶體之外,同時也寫一份到磁碟上,就像這樣:

 

 

沒錯,這是最簡單直接的方案。

但仔細想一下,這個方案有個問題:客戶端的每次寫操作,既需要寫記憶體,又需要寫磁碟,而寫磁碟的耗時相比於寫記憶體來說,肯定要慢很多!這勢必會影響到 Redis 的性能。

如何規避這個問題?

這時我們需要分析寫磁碟的細節問題了。

我們都知道,要把記憶體數據寫到磁碟,其實是分 2 步的:

  1. 程式寫文件的 PageCache(write)
  2. 把 PageCache 刷到磁碟(fsync)

具體就是下圖這樣:

 

 

 

數據持久化最粗暴的思路就是上面提到的那樣,寫完 Redis 記憶體後,同步寫 PageCache + fsync 磁碟,當然,這樣肯定因為磁碟拖慢整個寫入速度。

如何優化?也很簡單,我們可以這樣做:Redis 寫記憶體由主線程來做,寫記憶體完成後就給客戶端返回結果,然後 Redis 用「另一個線程」去寫磁碟,這樣就可以避免主線程寫磁碟對性能的影響。

 

 

這種持久化方案,其實就是我們經常聽到的 Redis AOF(Append Only File)。

Redis AOF 持久化提供了 3 種刷盤機制:

  1. appendfsync always:主線程同步 fsync
  2. appendfsync no:由 OS fsync
  3. appendfsync everysec:後臺線程每間隔1秒 fsync

解決了數據實時持久化,我們還會面臨另一個問題,數據實時寫入 AOF,隨著時間的推移,AOF 文件會越來越大,那使用 AOF 恢復時變得非常慢,這該怎麼辦?

Redis 很貼心地提供了 AOF rewrite 方案,俗稱 AOF 「瘦身」,顧名思義,就是壓縮 AOF 的體積。

因為 AOF 里記錄的都是每一次寫命令,例如執行 set k1 v1,set k1 v2,其實我們只關心數據的最終版本 v2 就可以了。AOF rewrite 正是利用了這個特點,在 AOF 體積越來越大時(超過設定閾值),Redis 就會定期重寫一份新的 AOF,這個新的 AOF 只記錄數據的最終版本就可以了。

 

 

這樣就可以壓縮 AOF 體積。

除此之外,我們可以換個角度,思考一下還有什麼方式可以持久化數據?

這時你就要結合 Redis 的使用場景來考慮了。

回憶一下,我們在使用 Redis 時,通常把它用作什麼場景?

是的,緩存。

把 Redis 當做緩存來用,意味著儘管 Redis 中沒有保存全量數據,對於不在緩存中的數據,我們的業務應用依舊可以通過查詢後端資料庫得到結果,只不過查詢後端數據的速度會慢一點而已,但對業務結果其實是沒有影響的。

基於這個特點,我們的 Redis 數據持久化還可以用「數據快照」的方式來做。

那什麼是數據快照呢?

簡單來講,你可以這麼理解:

  1. 你把 Redis 想象成一個水杯,向 Redis 寫入數據,就相當於往這個杯子里倒水
  2. 此時你拿一個相機給這個水杯拍一張照片,拍照的這一瞬間,照片中記錄到這個水杯中水的容量,就是水杯的數據快照

 

 

也就是說,Redis 的數據快照,是記錄某一時刻下 Redis 中的數據,然後只需要把這個數據快照寫到磁碟上就可以了。

它的優勢在於,只在需要持久化時,把數據「一次性」寫入磁碟,其它時間都不需要操作磁碟。

基於這個方案,我們可以「定時」給 Redis 做數據快照,把數據持久化到磁碟上。

 

 

 

這種方案就是我們經常聽到的 Redis RDB,RDB 採用「定時快照」的方式進行數據持久化,它的優點是:

  1. 持久化文件體積小(二進位 + 壓縮)
  2. 寫盤頻率低(定時寫入)

缺點也很明顯,因為是定時持久化,數據肯定沒有 AOF 實時持久化完整,如果你的 Redis 只當做緩存,對於丟失數據不敏感(可從後端的資料庫查詢),那這種持久化方式是非常合適的。

如果讓你來選擇持久化方案,你可以這樣選擇:

  1. 業務對於數據丟失不敏感,選 RDB
  2. 業務對數據完整性要求比較高,選 AOF

理解了 RDB 和 AOF,我們再進一步思考一下,有沒有什麼辦法,既可以保證數據完整性,還能讓持久化文件體積更小,恢復更快呢?

回顧一下我們前面講到的,RDB 和 AOF 各自的特點:

  1. RDB 以二進位 + 數據壓縮方式存儲,文件體積小
  2. AOF 記錄每一次寫命令,數據最全

我們可否利用它們各自的優勢呢?

當然可以,這就是 Redis 的「混合持久化」。

要想數據完整性更高,肯定就不能只用 RDB 了,重點還是要放在 AOF 優化上。

具體來說,當 AOF 在做 rewrite 時,Redis 先以 RDB 格式在 AOF 文件中寫入一個數據快照,再把在這期間產生的每一個寫命令,追加到 AOF 文件中。

因為 RDB 是二進位壓縮寫入的,這樣 AOF 文件體積就變得更小了。

 

 

因為 AOF 體積進一步壓縮,你在使用 AOF 恢複數據時,這個恢復時間就會更短了!

Redis 4.0 以上版本才支持混合持久化。

註意:混合持久化是對 AOF rewrite 的優化,這意味著使用它必須基於 AOF + AOF rewrite。

這麼一番優化,你的 Redis 再也不用擔心實例宕機了,當發生宕機時,你就可以用持久化文件快速恢復 Redis 中的數據。

但這樣就沒問題了嗎?

仔細想一下,雖然我們已經把持久化的文件優化到最小了,但在恢複數據時依舊是需要時間的,在這期間你的業務應用無法提供服務,這怎麼辦?

一個實例宕機,只能用恢複數據來解決,那我們是否可以部署多個 Redis 實例,然後讓這些實例數據保持實時同步,這樣當一個實例宕機時,我們在剩下的實例中選擇一個繼續提供服務就好了。

沒錯,這個方案就是接下來要講的「主從複製:多副本」。

主從複製:多副本

你可以部署多個 Redis 實例,架構模型就變成了這樣:

 

 

我們這裡把實時讀寫的節點叫做 master,另一個實時同步數據的節點叫做 slave。

採用多副本的方案,它的優勢是:

  1. 縮短不可用時間:master 發生宕機,我們可以手動把 slave 提升為 master 繼續提供服務
  2. 提升讀性能:讓 slave 分擔一部分讀請求,提升應用的整體性能

 

 

這個方案不錯,不僅節省了數據恢復的時間,還能提升性能。

但它的問題在於:當 master 宕機時,我們需要「手動」把 slave 提升為 master,這個過程也是需要花費時間的。

雖然比恢複數據要快得多,但還是需要人工介入處理。一旦需要人工介入,就必須要算上人的反應時間、操作時間,所以,在這期間你的業務應用依舊會受到影響。

我們是否可以把這個切換的過程,變成自動化?

 

哨兵:故障自動切換

要想自動切換,肯定不能依賴人了。

現在,我們可以引入一個「觀察者」,讓這個觀察者去實時監測 master 的健康狀態,這個觀察者就是「哨兵」。

具體如何做?

  1. 哨兵每間隔一段時間,詢問 master 是否正常
  2. master 正常回覆,表示狀態正常,回覆超時表示異常
  3. 哨兵發現異常,發起主從切換

 

 

有了這個方案,就不需要人去介入處理了,一切就變得自動化了,是不是很爽?

但這裡還有一個問題,如果 master 狀態正常,但這個哨兵在詢問 master 時,它們之間的網路發生了問題,那這個哨兵可能會「誤判」。

 

 

這個問題怎麼解決?

既然一個哨兵會誤判,那我們可以部署多個哨兵,讓它們分佈在不同的機器上,讓它們一起監測 master 的狀態,流程就變成了這樣:

 

 

  1. 多個哨兵每間隔一段時間,詢問 master 是否正常
  2. master 正常回覆,表示狀態正常,回覆超時表示異常
  3. 一旦有一個哨兵判定 master 異常(不管是否是網路問題),就詢問其它哨兵,如果多個哨兵(設置一個閾值)都認為 master 異常了,這才判定 master 確實發生了故障
  4. 多個哨兵經過協商後,判定 master 故障,則發起主從切換

所以,我們用多個哨兵互相協商來判定 master 的狀態,這樣,就可以大大降低誤判的概率。

哨兵協商判定 master 異常後,這裡還有一個問題:由哪個哨兵來發起主從切換呢?

答案是,選出一個哨兵「領導者」,由這個領導者進行主從切換。

問題又來了,這個領導者怎麼選?

想象一下,在現實生活中,選舉是怎麼做的?

是的,投票。

在選舉哨兵領導者時,我們可以制定這樣一個選舉規則:

  1. 每個哨兵都詢問其它哨兵,請求對方為自己投票
  2. 每個哨兵只投票給第一個請求投票的哨兵,且只能投票一次
  3. 首先拿到超過半數投票的哨兵,當選為領導者,發起主從切換

這個選舉的過程就是我們經常聽到的:分散式系統領域中的「共識演算法」。

什麼是共識演算法?

我們在多個機器部署哨兵,它們需要共同協作完成一項任務,所以它們就組成了一個「分散式系統」。

在分散式系統領域,多個節點如何就一個問題達成共識的演算法,就叫共識演算法。

在這個場景下,多個哨兵共同協商,選舉出一個都認可的領導者,就是使用共識演算法完成的。

這個演算法還規定節點的數量必須是奇數個,這樣可以保證系統中即使有節點發生了故障,剩餘超過「半數」的節點狀態正常,依舊可以提供正確的結果,也就是說,這個演算法還相容了存在故障節點的情況。

共識演算法在分散式系統領域有很多,例如 Paxos、Raft,哨兵選舉領導者這個場景,使用的是 Raft 共識演算法,因為它足夠簡單,且易於實現。

好,到這裡我們先小結一下。

你的 Redis 從最簡單的單機版,經過數據持久化、主從多副本、哨兵集群,這一路優化下來,你的 Redis 不管是性能還是穩定性,都越來越高,就算節點發生故障,也不用擔心了。

Redis 以這樣的架構模式部署,基本上就可以穩定運行很長時間了。

...

隨著時間的發展,你的業務體量開始迎來了爆炸性增長,此時你的架構模型,還能夠承擔這麼大的流量嗎?

我們一起來分析一下:

  1. 數據怕丟失:持久化(RDB/AOF)
  2. 恢復時間久:主從副本(副本隨時可切)
  3. 手動切換時間長:哨兵集群(自動切換)
  4. 讀存在壓力:擴容副本(讀寫分離)
  5. 寫存在壓力一個 mater 扛不住怎麼辦?

可見,現在剩下的問題是,當寫請求量越來越大時,一個 master 實例可能就無法承擔這麼大的寫流量了。

要想完美解決這個問題,此時你就需要考慮使用「分片集群」了。

 

分片集群:橫向擴展

什麼是「分片集群」?

簡單來講,一個實例扛不住寫壓力,那我們是否可以部署多個實例,然後把這些實例按照一定規則組織起來,把它們當成一個整體,對外提供服務,這樣不就可以解決集中寫一個實例的瓶頸問題嗎?

所以,現在的架構模型就變成了這樣:

 

 

現在問題又來了,這麼多實例如何組織呢?

我們制定規則如下:

  1. 每個節點各自存儲一部分數據,所有節點數據之和才是全量數據
  2. 制定一個路由規則,對於不同的 key,把它路由到固定一個實例上進行讀寫

數據分多個實例存儲,那尋找 key 的路由規則需要放在客戶端來做,具體就是下麵這樣:

 

 

這種方案也叫做「客戶端分片」,這個方案的缺點是,客戶端需要維護這個路由規則,也就是說,你需要把路由規則寫到你的業務代碼中。

如何做到不把路由規則耦合在客戶端業務代碼中呢?

繼續優化,我們可以在客戶端和服務端之間增加一個「中間代理層」,這個代理就是我們經常聽到的 Proxy,路由轉發規則,放在這個 Proxy 層來維護。

這樣,客戶端就無需關心服務端有多少個 Redis 節點了,只需要和這個 Proxy 交互即可。

Proxy 會把你的請求根據路由規則,轉發到對應的 Redis 節點上,而且,當集群實例不足以支撐更大的流量請求時,還可以橫向擴容,添加新的 Redis 實例提升性能,這一切對於你的客戶端來說,都是透明無感知的。

業界開源的 Redis 分片集群方案,例如 Twemproxy、Codis 就是採用的這種方案。

 

 

這種方案的優點在於,客戶端無需關心數據轉發規則,只需要和 Proxy 打交道,客戶端像操作單機 Redis 那樣去操作後面的集群,簡單易用。

架構演進到目前為止,路由規則無論是客戶端來做,還是 Proxy 來做,都是「社區」演進出來的分片解決方案,它們的特點是集群中的 Redis 節點,都不知道對方的存在,只有客戶端或 Proxy 才會統籌數據寫到哪裡,從哪裡讀取,而且它們都依賴哨兵集群負責故障自動切換。

也就是說我們其實就是把多個孤立的 Redis 節點,自己組合起來使用。

Redis 在 3.0 其實就推出了「官方」的 Redis Cluster 分片方案,但由於推出初期不穩定,所以用的人很少,也因此業界涌現出了各種開源方案,上面講到的 Twemproxy、Codis 分片方案就是在這種背景下誕生的。

但隨著 Redis Cluster 方案的逐漸成熟,業界越來越多的公司開始採用官方方案(畢竟官方保證持續維護,Twemproxy、Codis 目前都逐漸放棄維護了),Redis Cluster 方案比上面講到的分片方案更簡單,它的架構如下。

 

 

Redis Cluster 無需部署哨兵集群,集群內 Redis 節點通過 Gossip 協議互相探測健康狀態,在故障時可發起自動切換。

另外,關於路由轉發規則,也不需要客戶端自己編寫了,Redis Cluster 提供了「配套」的 SDK,只要客戶端升級 SDK,就可以和 Redis Cluster 集成,SDK 會幫你找到 key 對應的 Redis 節點進行讀寫,還能自動適配 Redis 節點的增加和刪除,業務側無感知。

雖然省去了哨兵集群的部署,維護成本降低了不少,但對於客戶端升級 SDK,對於新業務應用來說,可能成本不高,但對於老業務來講,「升級成本」還是比較高的,這對於切換官方 Redis Cluster 方案有不少阻力。

於是,各個公司有開始自研針對 Redis Cluster 的 Proxy,降低客戶端的升級成本,架構就變成了這樣:

 

 

這樣,客戶端無需做任何變更,只需把連接地址切到 Proxy 上即可,由 Proxy 負責轉發數據,以及應對後面集群增刪節點帶來的路由變更。

至此,業界主流的 Redis 分片架構已經成型,當你使用分片集群後,對於未來更大的流量壓力,也都可以從容面對了!

 

總結

總結一下,我們是如何從 0 到 1,再從 1 到 N 構建一個穩定、高性能的 Redis 集群的,從這之中你可以清晰地看到 Redis 架構演進的整個過程。

  1. 數據怕丟失 -> 持久化(RDB/AOF)
  2. 恢復時間久 -> 主從副本(副本隨時可切)
  3. 故障手動切換慢 -> 哨兵集群(自動切換)
  4. 讀存在壓力 -> 擴容副本(讀寫分離)
  5. 寫存在壓力/容量瓶頸 -> 分片集群
  6. 分片集群社區方案 ->  Twemproxy、Codis(Redis 節點之間無通信,需要部署哨兵,可橫向擴容)
  7. 分片集群官方方案 ->  Redis Cluster (Redis 節點之間 Gossip 協議,無需部署哨兵,可橫向擴容)
  8. 業務側升級困難 -> Proxy + Redis Cluster(不侵入業務側)

至此,我們的 Redis 集群才得以長期穩定、高性能的為我們的業務提供服務。

希望這篇文章可以幫你更好的理解 Redis 架構的演進之路。

 

作者:ryetan,騰訊 CSIG 後臺開發工程師

本文來自博客園,作者:古道輕風,轉載請註明原文鏈接:https://www.cnblogs.com/88223100/p/An-article-to-understand-the-evolution-of-Redis-architecture.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.簡介 jq 是一款非常強大的 JSON 命令行處理工具。其官網地址為:https://stedolan.github.io/jq/ 2.安裝 以CentOS為例: 1.線上安裝 yum install -y epel-release && yum install -y jq 2.離線安裝 訪問官 ...
  • Tampermonkey插件Mac版是一款瀏覽器腳本管理插件,支持大多常見瀏覽器,結合腳本大全網站 greasyfork,能夠方便的實現腳本旳一鍵安裝、自動更新、快速啟用等便捷功能,通過用戶腳本可以實現很多實用或有趣的功能。 詳情:Tampermonkey for Mac(油猴Safari瀏覽器插件 ...
  • 常用安全技術 3A: 認證:身份確認 授權:許可權分配 審計:監控做了什麼 安全通信 加密演算法和協議 對稱加密: 非對稱加密 單向加密:哈希(hash)加密 認證協議 對稱加密: 加密和解密使用的是同一個密鑰 是通過將原始數據分割成若幹塊來逐個進行加密 特點:效率高、速度快 缺點:加密解密使用的密鑰相 ...
  • magnet mac版是一款運行在蘋果電腦上的一款優秀的視窗大小控制工具,拖拽視窗到屏幕邊緣可以自動半屏,全屏或者四分之一屏幕,還可以設定快捷鍵完成分屏。這款專業的視窗管理工具當您每次將內容從一個應用移動到另一應用時,當您需要併排比較數據時,或是以其他方式進行多任務處理時,它都可以幫您妥善解決! 詳 ...
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 kalibr標定板(棋盤格)用師兄的(長這樣) 步驟一:建立的ROS中的Kalibr的工作空間,建立一個名為:checkerboard.yaml的文件,內容為: target_type: 'checkerboard' targetCols: 11 ...
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 從kubernetes 1.24開始,dockershim已經從kubelet中移除,但因為歷史問題docker卻不支持kubernetes主推的CRI(容器運行時介面)標準,所以docker不能再作為kubernetes的容器運行時了,即從ku ...
  • 空洞的概念 linux 上普通文件的大小與占用空間是兩個概念,前者表示文件中數據的長度,後者表示數據占用的磁碟空間,通常後者大於前者,因為需要一些額外的空間用來記錄文件的某些統計信息或附加信息、以及切分為塊的數據信息 (通常不會占用太多)。文件占用空間也可以小於文件尺寸,此時文件內部就存在空洞了。 ...
  • 寫在前面 本系列的文章是博主邊學邊記錄的,可能不是特別的正確,因為會加上博主自己的理解,僅供參考。 正文: 1.磁碟的訪問時間 為了讀或者寫,磁頭必須能移動到所指定的磁軌上,並等待所指定的扇區的開始位置旋轉到磁頭下,然後開始讀取或者寫入數據。那麼可以把對磁碟的訪問時間分為以下三個部分: 1.尋道時間 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...