Redis - 那條專注於低延遲的單行道
想像一條高速公路,如果有太多交流道、紅綠燈、車子搶道,雖然看起來能同時容納很多車,但實際上常常塞爆。Redis 的設計哲學剛好相反:它選擇了一條「單行道」的路線──簡單、專注,一次只處理一件事。
因為它把所有資料放在記憶體裡,所以車子(請求)一旦進來,就能以極快的速度通過。這種設計讓 Redis 在需要低延遲的場景裡,成為最可靠的快取層。它不追求資料永遠存在(Persistence),而是保證當下的快與穩。
🍂 Redis 作為快取的典型流程(Cache-aside)一般來說我們會採用「讀取型快取」(Cache-aside)流程:
使用者要看商品列表(GET)
系統先去 Redis 看有沒有這筆快取資料
有的話(hit):直接回傳
沒的話(miss):去主資料庫拿資料 ➡ 存進 Redis(快取) ➡ 回傳結果
這種情況 Redis 就算整個掛了也沒差,系統還是能從主資料庫把資料拿回來,最多只是變慢一點(因為每次都去查資料庫)
🍂 Redis 分散式架構(Sharding)不同的 Key/Value 會放到不同的 Redis 機器上,除非你只有一台 Red ...
Plugin + Factory + Strategy 遊戲機與卡帶
在開發金流或第三方整合系統時,常會遇到這樣的狀況:今天要支援 LinePay,明天要加上 ApplePay,後天可能還有 GooglePay、PayPal…。
如果每增加一種支付方式都要打開主程式去修改,就好比一台遊戲機的遊戲被「寫死」在機器裡:每次想玩新遊戲,就得整台機器重焊一次電路。這樣不但麻煩,還很難維護。
更好的設計是:遊戲機本身保持穩定,玩家只要插上不同的卡帶,就能享受不同的遊戲。這就是 Plugin 架構(Plugin Architecture)+ 工廠(Factory)+ 策略模式(Strategy) 的精神。
它的優點在於:
彈性高:不必動到遊戲機(主程式),就能插入新卡帶(Plugin)。
可測試性強:每個卡帶都能單獨測試,不影響主機。
擴充容易:只要遵守插槽規格,就能自由新增遊戲。
常見的應用像是:
金流模組(不同支付方式 = 不同遊戲卡帶)
外掛模組(Plugin System)
Middleware(專案套件)
第三方 API 整合(物流、支付、通訊)
🪵 Plugin Pattern(外掛模式) ...
考到除草證照 5 級 !! 吉伊家長含淚喝采
那天早上,廣播突然響起 ——「各位家長請注意!吉伊寶寶順利考取除草證照 5 級!」不到三秒,家長們已經刷了滿滿的貼圖,含淚喝采
這則喜訊,像是一場同步播放的快閃演出,正在教室自習的悄悄看了手機,忍不住笑到被同桌戳了一下;咖啡廳裡打工的,拉花時多畫了一片草葉致敬;剛進辦公室的設計師,立刻在筆記本上畫了「五級除草王」的手繪海報;外送路上的長,順路把好消息送到各個巷口;還有剛下班的夜班便利商店店員,抱著零食袋邊走邊笑說:「值得熬夜等這條消息!」
如果你覺得這畫面很熟悉,那是因為它就像程式世界中的「觀察者模式(Observer Pattern)」—— 一個事件發生,所有「訂閱」它的人會同時收到通知,不用一個個去問。
同一個消息,在不同的心裡綻放成各自的顏色。
如果你覺得這畫面很熟悉,那是因為就是程式世界中的 觀察者模式(Observer Pattern) —— 當一個事件發生,所有訂閱它的人會同時收到通知,不用一個個去問。
🪵 廣播器情境想像有一台「家長廣播器」,只要一播送,所有家長都會同時聽到並作出反應。 ...
字符密語:跨越國界的編碼詩篇
在數位世界的浩瀚星海中,有一種神秘的語言穿梭於不同的系統之間,它就是 JSON。今天,讓我們踏上一場探索編碼奧秘的旅程,揭開 Unicode 轉義背後的故事。
🔑 JSON:穿越語言邊界的使者JSON(JavaScript Object Notation)如同一位精通多國語言的外交官,肩負著在不同系統、不同語言之間搭建溝通橋梁的使命。
想像這樣一個場景:後端是 .NET 的城堡,前端是 JavaScript 的王國,而客戶端則散布在中文的故鄉、英文的海島、日文的群山、以及阿拉伯文的沙漠… 在這個多元的數位世界中,JSON 承載著一個偉大的使命:確保所有的字元都能安全抵達目的地,不會在旅途中因為編碼的差異而迷失自我。
🔑 Unicode Escape:JSON 的守護神咒在 JSON 的世界中,存在著一種古老而強大的保護咒語:Unicode 轉義序列。
這個神奇的 \uXXXX 符號就像是文字的化身術,能夠將非英文字符轉化為數字密碼。比如說,當「你」這個字要穿越網路的險境時,它會化身為 \u4f60,而「好」字則變成了 \u597d。
這種變身術的智慧在於:無論是年邁的瀏 ...
EF Core - 快取
🌊 DbContext 是什麼? — 它就是你的「臨時記事本」
在 Entity Framework Core(EF Core)裡,DbContext 是一個很關鍵的角色,背後有兩個重要概念:
它是工作單位(Unit of Work)
它自帶一級快取(First-Level Cache)
當你在一個業務流程裡使用 DbContext 時,它幫你做三件事:
✅ 變更追蹤(Change Tracking)
追蹤每個被載入的 Entity 誰改了什麼,幫你記錄要更新的欄位。
✅ 一級快取(First-Level Cache)
相同主鍵的資料,只要查過一次就放在 DbContext 的快取中,後續查詢就直接從快取拿,不會再打資料庫。
✅ 單一交易(Single Transaction)
呼叫 SaveChanges() 時,會把所有變更一次送到資料庫並用同一個交易包起來,確保一致性。換句話說,DbContext 就像一個臨時記事本(背包 🧳),把這段流程需要用到的資料和變更都記錄起來,最後一次打包送到資料庫。
🌊 EF Core 的一級快取是什麼?所謂「快取」,指的是 ...
Asynchronous Programming - 第十二章:章魚的八爪例外:多執行緒的捕獲術
在深海裡,章魚的八隻腕足總是同時探向不同的方向,纏繞著礁岩、觸碰著漩渦,也悄悄在黑暗中編織出一張未被看見的網。我們的非同步程式,就像這隻章魚,當你派出無數任務游向未知,若沒有好好等待(await),有些錯誤就會像溜走的墨汁般散開,再也無法追溯。
若選擇用同步阻塞強行捕捉,例外也會被包裹成難解的聚合結,像是八爪同時纏住獵物卻黏成一團。學會如何等待,如何攤開多執行緒裡潛藏的觸手,才是馴服這隻章魚、看清每一道潛伏例外的唯一方法。
🐙
🎵 實驗一:沒 await,什麼都接不到
12345678910111213141516public static async Task ExceptionResultTest(){ try { TaskThatThrowsExceptionStringAsync(); } catch(Exception ex) { throw; }}private static async Task<string> TaskTha ...
Asynchronous Programming - 第十一章:未繭之絲:任務才是本體
在多執行緒的森林裡,有些線,早已抽離了蠶的軀殼,它們不需繭的庇護,也能沿著記憶結點游走。我們誤以為是 await 編織了非同步的絲線,卻忘了真正編織的是那些未繭的任務。只要 Task 尚在,無論繭在與否,線都還在地底延展,繼續牽動著下一個狀態機的呼吸。
🎵 非同步的本質:回傳 Task 才是真的非同步非同步的核心是 Task 或 Task 型別。只要方法回傳 Task,它就是非同步,因為 Task 代表著「進行中的工作」。是否使用 await 不影響方法本身是否非同步,await 只決定要不要在這裡把結果拿回來、接著做後續的邏輯。
await 的本質是「把非同步操作的結果,用同步的方式 等待完成後,接著執行後續的程式碼」。
沒用 await123public Task<int> GetDataAsync() { return GetDataFromDbAsync(); // 直接把 Task 回傳}
這段程式:
GetDataFromDbAsync() 會回傳一個執行中的 Task。
呼叫端收到後可以選擇:先做其他事 → 等需要時再 ...
Asynchronous Programming - 第十章:未完成的回聲
在每一個任務被派遣出去的夜裡,總有一些聲音,無法即刻歸來。它們在平行的執行緒裡交錯穿行,有的抵達了終點,返回一聲輕快的完成;有的在等待中腐蝕,成為無聲的阻塞;有的半途拋下誓言,消失在取消的荒野裡。你以為程式碼寫好了,流向已然明朗,卻不知每個 Task 都像流浪的信件,封存著可能,也埋藏著未竟。
TPL,不只是一套平行的工具,它是一場關於 等待與命運 的實驗,每一個 WaitAll、WhenAny、Result,都是開啟分支與結局的咒語。當結果未歸,回聲仍在。在執行緒的深處,有些任務,終將完成;有些回聲,永遠未完。
🎵 簡單的建立一個 Task先用最簡單的 Task.Run 建立一個任務,看看它跟一般程式碼的執行順序有什麼不一樣。
1234567891011121314151617static void Main(string[] args){ SimpleTask();}public static void SimpleTask(){ Task.Run(() => { Thread.Sleep(100 ...
Asynchronous Programming - 第九章:平行之風,併發之歌
有些風,獨自穿梭林間,沿著樹影與地面爬行,沒有分身,沒有回音,只將時間吹得靜謐。
有些風,輕輕裂成數萬縷絲線,從山脊滲入溪谷,從枝頭滲入土壤,它們彼此不糾纏,卻同時為大地帶來不同的聲響。
也有些種子,懂得在雲後潛伏,等待雨季將它們喚醒;一顆未必只能開一朵花,它可以把等待切碎,併發成無數顆更小的種子,在時間的縫隙裡生根發芽。
當我們談論分割與合流,等待與釋放,這片風與影子的地圖,就是平行之風,併發之歌。那些藏在核心深處的秘密,終究會在一次又一次的呼吸裡,被我們拆解、重組、散播,直到有一天,學會怎樣用一秒去換取另一秒。
用.NET展現多核威力(1) - 從ThreadPool翻船談起
🧪 實驗這個實驗想要透過一個簡單的數學運算(Math.Log10),用 單執行緒(Single Thread)、平行迴圈(Parallel.For)、以及 Task-based 併發(async/await + Task.WhenAll) 三種方式,分別執行相同的 100 萬次運算,並多輪重複測量執行時間。
目的是比較:
順序執行 vs. 多核心平行 vs. 多任務併發 在 CPU-boun ...
轉型
有一塊碎石,曾在河岸邊靜靜沉睡百年。它堅硬、粗糙、不懂流動。直到有一天,一條溪水與它擦身而過。
「你怎麼總是不動?」水問。
「我就是這樣被造的,不像你,總能輕盈地轉彎、改道。」碎石低聲說。
「但你知道嗎?」水輕聲笑道,「我之所以能走那麼遠,不是因為我比你強,而是我願意轉。」
碎石沉默良久,忽然覺得,那句話像是一道光,悄悄劃過它堅硬的內裡。它開始想:如果有一天,我也能在某個時刻學會轉型 —— 也許,我也能成為某種形式的流動看看這個世界更多的樣貌。
在程式的語法中,我們見證數字從一種型態變成另一種形態、物件從一個面貌蛻變為更適配的角色。這些「轉型」,看似只是語法上的操作,實則承載著如何讓資料 順勢而生、應需而變 的深意。
而我們,是否也能從中學會,如何在對的時機,捨去執念、跨越邊界?如何在堅固與柔軟之間,找到最合宜的模樣?
🌺 隱含轉型 (Implicit Casting)
商業情境一個電子商務網站的購物車系統。你需要計算訂單的總金額。商品數量是整數 (int),但商品單價可能是小數 (decimal,用於金融計算更精確)。在計算總價時,整數會被自動轉換為小數類型。
12345 ...