今天的內容主要對針對Redis再進行一些討論,主要的大綱如下:
那麼我們開始。
SQL Connection Pool 是什麼? SQL Connection Pool 是指 今天Web應用程式透過DAO朝DB發出請求時,應用程式與DB就會建立一次連線,連線會隨著請求的回傳而中斷。而在大量請求湧入後端時,應用程式就不斷地對資料庫重複建立連線、斷開連線的行為。因為不斷建立又斷開的開銷很大,所以SQL Connection Pool的概念應運而生。
Connection Pool是在應用程式與資料庫之間建立一個物件池,當今天請求結束後,不讓連線立刻關閉,並在一些條件下 ( 例如連線字串相同的狀況下) 讓這些連線可以被重複利用,以此減少對SQL的系統負擔。目前各家SQL都有使用這樣的方法。
Redis Connection Pool 也基於同樣的概念,除此之外,Redis 也可以設定 Redis的最大連線數等等,而如果在最大連線數情況下,請求將被迫等候,超過最大容忍時間後則會Timeout。在一些高併發的場景中會被使用。
主要使用Connection Pool的好處如下:
SQL ACID的 原子性,指的是一筆對資料庫的交易必須是全數成功或是全數失敗、若執行到中途遭遇失敗則要觸發資料庫的Rollback,確保不會發生部分成功部分失敗的問題。
而Redis是單執行緒的,也就是說對同一筆資料同時間只會有一個Process去存取它,其他的Process是無法同時存取的。雖然操作是獨立不受影響的,但Redis因為不支援Rollback,所以結論是不符合原子性。
舉例來說,在Redis中,一個交易的生命週期如下:
在Redis中,錯誤分為兩種,一種是在EXEC指令執行前,因為尚未執行,所以可以確保原子性 ( 失敗就是全部失敗 )。另一種是在EXEC後,Redis會除了發生錯誤的部分不執行外,其他都執行,進而破壞了原子性。
Redis中有交易,但這個交易不同於SQL的交易,Redis的交易主要是為了把多個請求裝在同一個交易中一次執行,而不是確保符合原子性。
再來,因為Redis存放的資料格式可以隨意被更動,完整性可被更改,所以Redis不支援一致性。
隔離性的部分,Redis可以透過WATCH指令去檢測的值有沒有被更動,簡言之就是使用樂觀鎖去確保交易間的隔離性。
持久性需要實作功能才能確保符合持久性,如: RDB 和 AOF模式
總之,Redis在很多層面不同於傳統的SQL,結論是不太適用ACID的原則。
在RedisTemplate,針對多個命令的執行,有不少種的方法,為了避免混淆,我稍微研究了一下,並分出他們的差別。
redisTemplate.executeWithStickyConnection(connection -> {
connection.set(redisTemplate.getStringSerializer().serialize("key1"),
redisTemplate.getStringSerializer().serialize("value1"));
connection.set(redisTemplate.getStringSerializer().serialize("key2"),
redisTemplate.getStringSerializer().serialize("value2"));
return null;
});
redisTemplate.execute((RedisCallback<Object>) connection -> {
connection.multi(); // 開啟事務
connection.set(redisTemplate.getStringSerializer().serialize("key1"),
redisTemplate.getStringSerializer().serialize("value1"));
connection.set(redisTemplate.getStringSerializer().serialize("key2"),
redisTemplate.getStringSerializer().serialize("value2"));
connection.exec(); // 提交事務
return null;
});
redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
connection.set(redisTemplate.getStringSerializer().serialize("key1"),
redisTemplate.getStringSerializer().serialize("value1"));
connection.set(redisTemplate.getStringSerializer().serialize("key2"),
redisTemplate.getStringSerializer().serialize("value2"));
return null;
});
以上是一些Redis的特性,Redis雖然使用起來很簡便,但是學問遠比我想像得要來得多,只能說學無止盡…
今天的部分就到此為止了,明天見吧。
參考資源:
https://bear-1111.medium.com/redis-acid-特性討論-566c7f7bcba1
https://blog.csdn.net/yangbindxj/article/details/123475569