# Redis ## NoSQL (NOT only SQL) NoSQL 的意思是它不僅僅是SQL,所以他可以做到類似SQL的關聯式結構,而redis的效能好的原因是他不需要依賴業務邏輯去儲存資料,而是以key and value方式,因為大大增加料的擴展能力,例如主從式架構,db資料的拷貝,相對SQL來說非常容易,但redis或是NOSQL還是有一些使用上的限制如下 * 不遵循SQL標準 * 不支持ACID * 遠超過SQL的性能 這裡補充一下不支持ACID準則,不代表他無法做事務機制,redis之類的nosql還是有自己對應的事物操作。 [redis cheat sheet](https://quickref.me/redis.html) ## Server 演進 在 web 1.0時期屬於單體示架構,一台server對應一台db  但隨著ap架構增長,單體是架構就會出現內存壓力與db io 壓力等問題  而NoSQL目的就是要解決以上的壓力問題,以session為例子,以往我的的session需要拷貝到不同server上,這樣會造成,數據的冗余節點越多浪費更大,甚至多個節點你需要多個IO去拉取db來達到同步  下圖就是透過NOSQL去同步多台server的session資料,減少資料拷貝次數,同時減少IO壓力,這也是NoSQl很常拿來做db cache的原因,無需透過IO操作就可以同步資料  NoSQL也可以透過破壞一定程度的業務邏輯來達到性能的提升,目的其實就是減少IO  Redis 是一個開源的內存資料庫系統,支援多種資料結構(如字串、列表、哈希、集合、有序集合等)並提供高效的查詢和快速的讀寫性能。Redis 支援兩種不同的持久化方式,即 RDB(Redis Database)和 AOF(Append-Only File),它們各自有優點和缺點。 ### RDB 的優點: 效能較好:RDB 是一種快速且高效的持久化方式,它會將 Redis 的資料集快照存儲到磁碟上,並在需要的時候可以快速地恢復資料。這使得 RDB 在恢復大型資料集時非常快速,並且對於備份和複製資料庫也非常有效。 資料壓縮:RDB 支援資料壓縮,可以將資料集壓縮後存儲在磁碟上,節省了磁碟空間。 簡單:RDB 的配置和使用相對簡單,適合於快速設置和使用。 ### RDB 的缺點: 適合大型資料集的定期快照:RDB 使用的是定期快照的方式來保存資料,因此在發生故障時可能會損失最近的資料更新。 資料恢復時可能較慢:當資料集很大時,RDB 的資料恢復速度可能會比較慢,因為需要讀取整個快照並將其還原到內存中。 不適合高頻率的資料更新:如果資料集需要經常更新,那麼 RDB 的快照會比較頻繁,這可能會對系統的性能產生一些影響。 ### AOF 的優點: 高可靠性:AOF 是一種寫日誌(Write-Ahead Log)的方式,它記錄了每一次對資料庫的寫操作,因此可以提供更高的資料可靠性,即使發生故障也可以輕鬆地從日誌中恢復資料。 恢復精確度高:由於 AOF 記錄了每一次寫操作,因此資料恢復時可以更加精確地還原資料的 狀態,避免了資料丟失的風險。 適合高頻率的資料更新:AOF 可以選擇不同的同步策略,包括每次寫操作都同步到磁碟,或者定期同步到磁碟,這使得 AOF 在高頻率的資料更新場景中更加適用,可以提供更好的資料一致性和持久性。 ### AOF 的缺點: 效能較低:AOF 的寫入操作需要追加到日誌文件中,這會導致寫入操作的速度相對較慢,因此相較於 RDB,AOF 的效能可能會稍低。 文件大小較大:由於 AOF 需要記錄每一次寫操作,因此 AOF 文件的大小通常會比 RDB 文件的大小大,這會占用更多的磁碟空間。 恢復速度相對較慢:AOF 的資料恢復速度相對於 RDB 來說可能會比較慢,因為需要逐行解析並還原資料,尤其在資料集較大的情況下,恢復時間可能會較長。 綜合而言,RDB 適合對資料一致性要求不高、資料集較大且資料讀取比較頻繁的場景,而 AOF 適合對資料一致性要求較高、資料更新較為頻繁的場景。選擇哪種持久化方式應根據實際應用場景的需求來進行選擇。在某些情況下,也可以同時使用 RDB 和 AOF 來實現資料的雙重持久化,提供更高的資料保證和可靠性。 ### zset zset在redis是一個有序的集合,裡面的值不會重複,但對應到的score是可以的,適合用在做排行榜的資料。 ```javascript // zadd 新增key topn redis > zadd topn 200 java 300 c++ 400 mysql 500 php //列出所有內容 redis > zrange topn 0 -1 1) "java" 2) "c++" 3) "mysql" 4) "php" //列出前兩筆資料,排序是由小到大 redis > zrange topn 0 1 1) "java" 2) "c++" //透過withscores 可以清楚看到值得大小 redis > zrange topn 0 2 withscores 1) "java" 2) "200" 3) "c++" 4) "300" 5) "mysql" 6) "400" //可以看到在該範圍內的value redis > zrangebyscore topn 100 200 1) "java" //為key內部的value加值 redis > zincrby topn 50 java "250" //這時候value就改變了 redis > zrangebyscore topn 250 250 1) "java" //刪除key成員 redis > zrem topn php //列出成員中value的範圍個數 redis > zcount topn 100 250 (integer) 1 //查看排名 redis > zrank topn php (integer) 3 ``` SortedSet (zset)底層結構類似為java Map<String,Double>,內部的元素value賦予一個權重score進行排序,透過map的hash關聯找到對應的值,達到快速查詢的效果 ### redis many to many sample hset 類似於 js object sadd 類似於 js array ```javascript # Here are my categories > hset category:1 name cinema ... more fields ... > hset category:2 name music ... more fields ... > hset category:3 name sports ... more fields ... > hset category:4 name nature ... more fields ... # Here are my users > hset user:1 name Jack ... more fields ... > hset user:2 name John ... more fields ... > hset user:3 name Julia ... more fields ... # Let's establish the many-to-many relationship # Jack likes cinema and sports # John likes music and nature # Julia likes cinema, music and nature # For each category, we keep a set of reference on the users > sadd category:1:users 1 3 > sadd category:2:users 2 3 > sadd category:3:users 1 > sadd category:4:users 2 3 # For each user, we keep a set of reference on the categories > sadd user:1:categories 1 3 > sadd user:2:categories 2 4 > sadd user:3:categories 1 2 4 ``` ```javascript # Categories of Julia > smembers user:3:categories 1) "1" 2) "2" 3) "4" # Users interested by music > smembers category:2:users 1) "2" 2) "3" # Users interested by both music and cinema > sinter category:1:users category:2:users 1) "3" ``` ### redis 分布式存儲 #### 億萬級數據的數據存儲 當數據更多單一server勢必無法承受大規模的吞吐量,解決方式有二: **垂直整合:** 加大單一機台硬體設備效能,但肯定會有附載上限,例如 google 、 amazon 等這些大廠肯定背後不止一台 server 運行。 為了解決垂直整合的上限,這時就有分部式存儲觀念,分布式存儲就是實作 db 的 load balancer ,方法有以下三點: **水平擴充:** #### hash 取餘數 用戶透過固定 hash 算法,% N台機器節點數量,計算hash 值將讀寫操作映射到相對的 redis server 身上,由於 redis key 是獨立的,這也確保每次的讀寫都是到特定的 server 中。 **優點:** 簡單快速達到負載均衡效果,只需劃分好機台數量。 **缺點:** 當單一機台掛掉或是增加機台,分母數量變化,原本選好的 server 位置將重新計算,資料可能會有缺失,甚至 db migrate 、集群擴縮容會因為server 掛掉導致數據不一致與資料遺失而產生實作問題。 #### 一致性 hash 目的是當服務器數量發生變化,勁量減少影響客戶端到服務器的映射關係,解決hash 取餘 server 節點掛掉資料遺失問題,以及節點數量變化的數據遷移。 一致性 hash 算法不同於 hash 取餘根據 server 節點數量外,是透過將 hash算法擴大至 0 ~2^32 首尾相連的原型數據,並根據 hash 結果找到最接近的節點。為什麼是 2^32是因為 redis 理論上可以容納的最大節點數就是 2^32 。  一致性 hash 可以夠過 ip 地址換算找到對應的節點位置,找到 key hash 位置,key 落點的位置順時針走遇到的第一個 server 位置就是要存儲的地方 **優點:** server 掛掉並不會導致所有節點位置都需要重算,增加server容錯率跟擴展性,例如服務器2掛掉,那剩下的請求將會順時針改存儲到服務器3,影響的數據只會是服務器2跟服務器3的資料,其餘都是正常。 **缺點:** 數據傾斜問題,你會發現 c-b 之間位置較大,這時 c server可以要處理更多請求,導致 c server需要應付更多的吞吐量。   ### hash slot 分配 在數據跟節點之間多了一個中介層,用於數據分配,一個集群最多有 16384個 slot 默認,redis 集群式透過 hash slot 去分配數據而不是用一致性 hash,解決數據傾斜問題,原本在一致性 hash 算法中的落點在hash slot 中的slot。 
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.