<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                - 消息堆太多內存暴漲 - 用redis mode 實現高可用 > 為什么需要緩存 一般使用目的是通過緩存數據庫查詢結果,減少數據庫訪問次數,以提高動態 Web 應用的速度、提高可擴展性。像首頁頻繁訪問的數據,搜索篩選列表以及表格數據,每次都去請求數據庫,不僅查詢速度慢,頻率高的話還會造成阻塞甚至服務宕機. 即使第二次查詢數據庫會有緩存,但是讀寫速度還是很難達到 Redis 的十分之一。 > Redis 和 Memcached 對比分析 對于緩存技術,提到最多的是 Redis 和 Memcached,兩者都是將數據存放在內存中(內存數據庫)。 Memcached 數據結構就一種,add/set 去添加/修改鍵值對,以及圍繞鍵值對的追加,刪除等指令操作,適合緩存大對象數據,列如圖片,視頻等等。在早些時候是不支持數據持久化的,服務重啟會導致緩存數據丟失,在 1.5.18 和之后版本可以在服務重啟時恢復緩存數據,新版本還通過 DAX 文件系統掛載來實現緩存持久性功能。 - Tips:在搜索 Memcached 資料時,會出現 Memcache 和 Memcached,用的軟件是 Memcached。PHP 在操作 Memcached 時有兩個擴展一個是 Memcache,另一個是 Memcached。 Redis 不僅支持簡單的 k/v 類型的數據,同時還支持 list、set、zset、sorted set、hash 等數據結構的存儲和 Redis Modules 實現自己的數據類型,使得它擁有更廣闊的應用場景。 > 數據結構 Redis 有五種基本數據結構,分別是字符串(String)、 哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)。高級數據結構 HyperLogLog 用來做基數統計的算法,GEO 將用戶給定的地理位置(經度和緯度)信息儲存起來,并對這些信息進行操作,pub/sub 發布訂閱的通信模式。另外還可以用 Redis Modules 外部模塊進行功能性擴展,像 BloomFilter(布隆過濾器),RediSearch(搜索引擎),Redis-ML(機器學習)…… - 更多模塊:[https://redis.io/modules](https://redis.io/modules) - [Redis 數據結構應用場景](https://www.cnblogs.com/pangzizhe/tag/Redis/) > 有序集合、消息隊列、延遲隊列、訂閱模式 Redis 使用雙向鏈表實現 List 數據結構,可以在列表的頭部(左邊)或者尾部(右邊)添加或移除元素(LPush RPush LPop RPop)我們可以用 List 模擬出 棧,有限集合,隊列,消息隊列。 ~~~ RPush + RPop = Statck (棧) //當然用 LPush + LPop 也是可以的, 符合先進先去 RPush + RTrim = Capped Collection(有限集合) RPush + LPop = Queue(隊列) //RPush 生成消息, LPop 消費消息, 在沒有消息的時候需要 Sleep 一會再重試 //BLPop 在沒有消息的時候,它會阻塞主直到有消息來 RPush + BLPop = Message Queue(消息隊列) ~~~ 延遲隊列是用 SortedSet 數據結構模擬的,時間戳作為 Score,消息的內容作為 Key,調用 Zadd 來生成消息,消費者使用 ZRangeByScore 指令獲取 N 秒之前的數據今夕處理,處理完后再獲取 N+M 下一個時間段數據進行處理。Redis 發布訂閱是實時消費的,服務端不會保存生產的消息,也不會記錄客戶端消費到哪一條。如果客戶端宕機,消息就會丟失。這時就需要用到高級的消息隊列,如 RocketMQ、Kafka 等。 > 內存淘汰策略 Redis 的內存淘汰策略有八種,默認策略是不會淘汰數據,當內存不足以容納新入數據時,新寫入操作就會報錯,要修改的數據比原來大很多也是會報錯的,但是查詢類請求可以正常操作。 ![](https://img.kancloud.cn/92/c9/92c9f260d9d264ac75fbce46036d69af_736x497.png) 前面根據策略選出要淘汰的 key,這時還沒有刪除 Key,相當于給 Key 做了個標記。對于 Key 的刪除,Redis 有三種策略,如下: * 定時刪除:在創建 Key 的時候,設置了 Key 的過期時間(一過期就刪除,內存占用時間少,但定時器的創建需要占用更多 CPU 時間) * 定期刪除:每隔一頓時間去刪除標記過的 Key * 惰性刪除:Key 標記完后不去管它, 每次獲取 Key 的時候再去檢查它是否有標記,有就刪除,返回 null > * 內存占用時間:定時 < 定期 < 惰性 > * CPU 占用時間:定時 > 定期 > 惰性 定時刪除是主動設置的。在刪除標記 Key 方面,Redis 是同時使用了惰性刪除和定期刪除。另外 Redis 中的淘汰機制是從性能和可用性方面考慮的,并不是完全可靠,我們在開發中應盡量對不需要永久保存的數據主動設置或更新 key 的過期時間。通過主動刪除這部分數據,來提升 Redis 整體性能和空間。 > 緩存雪崩、擊穿、穿透 Redis 緩存雪崩、擊穿、穿透造成的主要原因是在高并發下繞過 Redis 直接請求數據庫造成的。如果本身不加緩存,數據庫都扛得了,現先加上 Redis 提高性能,這樣是不會造成緩存雪崩、擊穿、穿透的。 緩存雪崩是因為在設置 Key 的時候加了過期時間,并且這些 Key 的過期時間是一樣的。在某一時間點,這些 Key 都過期了,在高并發請求的時候,發現 Key 不存在,就會直接打在數據庫上,數據庫支撐不了而崩潰。多個服務的緩存同時過期,每一個服務就像一個雪球在那里滾,最終造成緩存雪崩。解決方案是給 Key 設置過期時間的時候再加個隨機值,保證同一時間緩存不會大面積失效。或者設置這些熱點數據的 Key 永不過期,當數據發生變化的時候再去主動更新緩存。 緩存擊穿和緩存雪崩類似,緩存雪崩說的多個熱點 Key 過期,而緩存擊穿說的是一個熱點 Key 過期。緩存雪崩是造成大面積緩存失效,基本上是所有服務都不能用了。緩存擊穿只是對某個服務或某個功能用到這個 Key 的訪問異常。解決的方案是設置熱點數據的 Key 永不過期,數據發生變化的時候再去主動更新緩存。 緩存穿透式是用戶不斷發送請求數據庫中不存在的數據,數據庫都沒有的數據,Redis 也不會有,就可以繞過 Redis,直接訪問數據庫,導致數據庫壓力過大,甚至擊垮數據庫。解決方案是增加參數校驗或者用 BloomFilter(布隆過濾器),利用高效的數據結構和算法快速判斷這個 Key 是否存在數據庫中。 > 數據持久化 RDB 和 AOF 以及機器斷電對數據的影響 Redis 支持兩種持久化方式: 全量模式 RDB 冷備份(Snapshot 內存快照)和 增量模式 AOF 熱備份(append only file 文件追加) RDB 是默認的持久化方式,按照配置里的策略將內存中的數據生成快照保存到磁盤。自動觸發時 Redis 主進程會 fork 一個子進程將數據保存到 RDB 文件中,同步完數據之后,對原文件進行替換,然后通知主進程完成同步。如下圖,Redis 默認是 900 秒內有 1 個 key 發送變化或 300 秒內有 10 個 key 發生變化或者 60 秒內有 1W 個 key 發生變化就會觸發機制。在只開啟 RDB 情況下服務宕機了,最多只會丟失 15 分鐘數據,不超過 1W 個 Key 的修改。這時候如果想重啟 Redis 服務,又不想丟失數據,可以手動執行 save 或 bgsave 命令觸發機制。其中 save 命令是阻塞的,bgsave 和 自動觸發一樣會 fork 一個子進程將數據保存到 RDB 文件中。 ![](https://img.kancloud.cn/62/99/6299c62810803af21d30e07ff12c59fe_566x369.png) AOF 默認是不開啟的,在啟動時 Redis 會將每一個收到的修改命令通過 Write 函數追加到文件最后,追加的數據如下圖 1。寫入的頻率一般設置成每秒寫一次(如下圖 2),如果 Redis 宕機了,最多就丟失 1 秒的數據。如果設置成每條命令執行一次寫入,就只會丟失一條命令,但寫入太頻繁從而影響性能。Redis 實例在跑一段時間后,AOF 可能增加到幾百 M,甚至幾個 G。有些操作命令是對某個 key 頻繁操作,關一個 Key 就增加了幾十 M 數據。這時可以配置 auto-aof-rewrite-min-size 當達到某個閥值自動重寫或手動執行 bgrewriteaof 命令執行重寫。重寫的時候關于這個 Key 的幾十 M 數據最終會被重寫成這個 key 最新一個值的命令。 ![](https://img.kancloud.cn/83/8b/838b35aa326c5a6a1652ca3d4d4dfac9_840x515.png) ![](https://img.kancloud.cn/85/11/851190f06a71b0aaa52ef53d070822a4_787x520.png) RDB 文件小,適合定時備份,用于災難恢復。因為 RDB 文件存儲的是內存數據,而 AOF 文件存儲的是一條條命。在恢復的時候,Redis 加載 RDB 文件的速度比 AOF 快很多。一般在使用的過程中 RDB 和 AOF 兩個都是開啟的,如果 Redis 宕機了,在恢復的時候先用 RDB 的最后一個備份實例,再用 AOF 去逐條更新最近的數據。開啟混合模式時,AOF 文件內容如下如圖: ![](https://img.kancloud.cn/e5/b1/e5b164053467c41f834d9627569f5a6b_852x514.png) > Redis Sentinel 和 Redis Cluster Redis Sentinel(哨兵模式)是 Redis 官方推薦的高可用方案,當 Master 宕機時會自動將 Slave 提升為 Master,從而繼續提供服務。如下表格,我們只需要連接 Sentinel 就可有去訪問 Redis 服務。Sentinel 會去監控這三臺 Redis,當主的 Redis 宕機后,會從可用的 Slave 里選舉出新的 Master。當然 Sentinel 服務也有可能宕機,所以要配置多臺。 | 服務類型 | IP 地址 | 端口 | | --- | --- | --- | | Redis | 192.168.1.170 | 6379 | | Redis | 192.168.1.171 | 6379 | | Redis | 192.168.1.172 | 6379 | | Sentinel | 192.168.1.170 | 26379 | | Sentinel | 192.168.1.171 | 26379 | | Sentinel | 192.168.1.172 | 26379 | 在使用的過程中,業務不斷的增加,這就不可避免需要對 Redis 進行擴容。擴容的方式有兩種分別是垂直擴容和水平擴容,垂直擴容是通過加內存方式來增加整個緩存體系的容量比,但是機器的內存是有限的,不能一直增加。水平擴容是通過增加 Redis 機器數來增加整個緩存體系的容量。Redis Sentinel 對于水平擴容是個難點,針對這個問題,Redis Cluster 就應運而生。 Redis Cluster 是 Redis 的分布式解決方案,采用哈希劃分槽到每一個 Redis 服務。Redis Cluster 槽的范圍是 0~16383,所有的 Key 根據哈希函數映射到 0~16383,計算公式是: ~~~ slot = CRC16(key)&16383 ~~~ 如下文本內容是 Redis Cluster 的創建過程,六臺 Redis 機器三主三從。三臺主的 Slots 區間分別是 0~5460、5461~10922、10923~16383。在操作 Key 的時候,會算出這個 Key 對應的 slot,在從對應 slot 區間的 Master 服務里存取數據。 ~~~ [root@VM_0_17_centos redis-5.0.4]# /usr/local/redis-5.0.4/src/redis-cli --cluster create 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003 127.0.0.1:8004 127.0.0.1:8005 127.0.0.1:8006 --cluster-replicas 1c >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 127.0.0.1:8005 to 127.0.0.1:8001 Adding replica 127.0.0.1:8006 to 127.0.0.1:8002 Adding replica 127.0.0.1:8004 to 127.0.0.1:8003 >>> Trying to optimize slaves allocation for anti-affinity [WARNING] Some slaves are in the same host as their master M: bb5a9dc1bacad9ded849c2c6293e8569c39a9946 127.0.0.1:8001 slots:[0-5460] (5461 slots) master M: 075b6e5666712947871bfffdd49208ad7ca700ec 127.0.0.1:8002 slots:[5461-10922] (5462 slots) master M: ead7c5022960fbb157f512bc9059f32d724d2d2c 127.0.0.1:8003 slots:[10923-16383] (5461 slots) master S: 47ab708ffb95ccfb2981e72ccd0e7e077801305b 127.0.0.1:8004 replicates 075b6e5666712947871bfffdd49208ad7ca700ec S: 9249c68d60568378e877d579539e940d7b2c0dda 127.0.0.1:8005 replicates ead7c5022960fbb157f512bc9059f32d724d2d2c S: 5071a01e39deead8d42a0812388d0b5a2697fa28 127.0.0.1:8006 replicates bb5a9dc1bacad9ded849c2c6293e8569c39a9946 Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join .... >>> Performing Cluster Check (using node 127.0.0.1:8001) M: bb5a9dc1bacad9ded849c2c6293e8569c39a9946 127.0.0.1:8001 slots:[0-5460] (5461 slots) master 1 additional replica(s) M: 075b6e5666712947871bfffdd49208ad7ca700ec 127.0.0.1:8002 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: 5071a01e39deead8d42a0812388d0b5a2697fa28 127.0.0.1:8006 slots: (0 slots) slave replicates bb5a9dc1bacad9ded849c2c6293e8569c39a9946 S: 9249c68d60568378e877d579539e940d7b2c0dda 127.0.0.1:8005 slots: (0 slots) slave replicates ead7c5022960fbb157f512bc9059f32d724d2d2c M: ead7c5022960fbb157f512bc9059f32d724d2d2c 127.0.0.1:8003 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 47ab708ffb95ccfb2981e72ccd0e7e077801305b 127.0.0.1:8004 slots: (0 slots) slave replicates 075b6e5666712947871bfffdd49208ad7ca700ec [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. [root@VM_0_17_centos redis-5.0.4]# ~~~ > 操作集群有時能成功, 有時出現類似 MOVED 6373 127.0.0.1:8002 錯誤 在連接 Redis Cluste 集群的時候, 如果是用單機 Redis 的連接方式去操作是不會報錯的, 但是你要操作的這個 Key 算出來的 slot 不屬于這臺單機的 Redis 的 slot 區間時, 會提示類似 MOVED 6373 127.0.0.1:8002 錯誤,6373 是這個 key 算出來的 slot 值,對應的 Redis 機器是 127.0.0.1:8002。如果算出來的 slot 值屬于當前 Redis 則操作成功。另外從的只負責同步數據,往這個 Key 對應的 slot 的從數據庫寫入數據也是會提示錯誤的。 > 總結 在部署 Redis Cluster 開了六個 Redis 實例,三主三從交叉配對在三臺服務器上。三對主從實例,只要不是同一對主從 Redis 實例都掛了,服務可以正常運行。代碼連接 Redis 時,填了六臺 Redis 的地址。當然填一臺也是可以的,因為可以從這一臺 Redis 里獲取到集群 Redis 主從信息和 slot。要是剛好你配的這一臺 Redis 宕機了,你就連不上 Redis 了,集群是可以正常提供服務的。 有一段時間我在困惑是不是 Redis Sentinel 和 Redis Cluste 要搭配使用,這樣代碼就可以通過一個哨兵 IP 地址去訪問六 Redis 服務。NO,NO,NO,這是兩種模式,不能配合使用的。我動手試了下,配置完后 Redis 服務啟動不了了,有個配置項沖突了。Redis Sentinal 需要設置 cluster-enabled no,Redis Cluster 需要設置 cluster-enabled yes。而且就算你配置成功了,一臺哨兵有可能宕機,作為高可用你還得配置多臺哨兵,然后在代碼上用哨兵的連接方式寫上多臺哨兵的地址,那還不是一樣要陪多臺 IP。如果想要連接的時候只配置一個 IP 地址,可以用虛擬 VIP+Keeplived+Haproxy 的方式,但是虛擬 IP 不是所有云服務器運營商都由提供,但是一般會提供收費的負載均衡 SLB 服務 總的來說 Redis Sentinel 通過哨兵確保高可用,Redis Cluster 通過 slot 分配確保高并發,內置哨兵機制,主的宕機了會自動切換到從,所以也是高可用。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看