Redis数据结构以及对应存储策略
生活随笔
收集整理的這篇文章主要介紹了
Redis数据结构以及对应存储策略
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
redis數據結構:
- String 可以是字符串也可以是數字,以及浮點數
- List,一個鏈表,鏈表上每一個節點都包含一個字符串
- set 包含字符串的無序手機其,特點是每一個字符都是唯一的
- hash,包含鍵值對的無序散列,類似map
- ZSet,字符串成員,在set的基礎上是順序的,元素的順序由分值來決定
- redis的發布與訂閱的特性(重點):
- subscribe channel命令 訂閱給定的一個或者多個頻道
- pushlish channel message 給指定頻道發送消息,
- 通過這兩個命令redis可以實現發布與訂閱功能
- redis的基本事務功能
- redis通過multi和exec命令來實現事務的特性,在執行multi命令之后,redis會將這個客戶端之后發送的所有命令存儲在一個隊列中,直到接受到exec命令為止。然后會在不被打斷的情況下執行這些操作
- redis鍵過期時間:使用expiration設置key存活的時間,之后自動刪除
重要的數據結構
- hyperLogLog:基數計算概念:通常用來統計一個集合中不重復元素個數,比如用來統計網站的UV,或者網站搜索關鍵字的數量。最簡單的辦法是用給一個集合做統計,判斷新詞是否存在,然后添加存在兩個問題,數據量會變很大,判斷成本會變得很高。bitMap存儲1 億個數據大概要12M內存,redis中HyperLogLog(HLL)中只需要1K內存就能做到
- hyperLogLog原理(簡析):將需要統計的數據進行HASH,得到每個數據對應二進制串,統計得到的二進制串中從低位開始第一次出現1的情況并且進行統計,統計每個key的這種1 的位置,讓后用概率和統計的方法推到出統計和數據量之間的關系,HyperLogLog核心在于集合中每個實體對應的Hash串,通過這種統計來預估整體的量,可以大大減少內存的耗費,所以這種方式并沒有存儲所有的樣本,而是通過樣本估算的方式推算出總體大小。(數學原理 伯努力分布)
- GEO redis3.2中的新特性用來存儲和獲取經緯度,以及地理位置,還有位置距離計算等內容 如下操作
- redis modules:redis4.0 曾加了自定義模塊的開發,類似于3.X版本中lua腳本的兼容,但是lua有一定學習量,在4.0中提供了一系列模塊源碼: https://github.com/RedisLabsModules/redex ,可以通過命令將對應的模塊代碼導入到redis中,就可以使用對應自定義命令
- BloomFilter:主要功能是用來做去重,我們可以用來對訪問UV和購買UV的實時去重,具體原理如下:
- BloomFilter過濾器會將key做一次Hash,將hash后得到的int分布到一個大的Bit數組中對應的位,判斷一個Key是否存在,只要看Hash對應的bit數組位置是否是1,1則被占用,0不被占用
- 而且redis2.0 以后就支持bigMap的操作,以及Bit操作中的AND,OR,NOT,XOR操作,bitMap支持232 大小,也就是512M,下標最大232-1,可以存2億左右數據
- Redis Search:基于redis的搜索插件,可以用來做全局key值的模糊查詢,并且可以兼容一部分通配符
- Redis-ML :用來做機器學習的
redis數據安全與性能保障
-
redis提供兩種不同持久化方式來將數據存儲到硬盤:
-
快照模式(RDB)可以將存在某一個時間點上所有數據寫入硬盤
- RDB模式通過配置信息來啟動,并且設置觸發的配置,比如save 60 10000 在最近一次快照算起,60秒以內有10000次寫操作,自動執行一次BGSAVE命令做備份
- 快照生成一個rdb文件,可以拷貝,但是在心快照創建完畢之前,redis,系統,硬件有一個出現問題,那么redis將會丟失最近一次快照之后的所有寫入數據。
- 可以手動創建快照:通過BGSAVE命令,redis會調用fork來創建一個子進程,他來完成寫入,父子進程共享內存,直到父進程有寫入操作的時候共享結束
- 只適合哪些可以容忍少部分數據丟失的業務場景
- rdb方式需要找到save配置的點,因為如果過于頻繁會浪費資源,過于稀少可能丟失大量數據,我們一般做法是在測試機器上盡量模擬線上環境
- 執行BGSAVE會使redis停頓一定時間取決于系統以及硬件
-
追加文件模式(AOF),在執行寫命令時候將這條命令復制到硬盤
- AOF方式也可以通過配置方式打開,他會將所有寫命令追加到aof文件末尾,redis只需要執行一次aof文件就可以恢復所有記錄。
- 配置寫入頻率:always:每個寫入都同步aof文件到硬盤,效率極低。everysec:每一秒同步一次 no:讓操作系統來決定何時同步。
- 一般使用everysec,每秒執行一次和不適用任何持久化的性能比差不多,這樣可以保證做多丟失一秒的數據
- aof文件可能會變得很大甚至沾滿硬盤,這時候redis重啟需要執行AOF文件中所有命令這個執行時間會很長
- 可以通過向redis發送BGREWRITEAOF命令來移除榮譽的命令,來重寫aof文件,但是如果文件太大,刪除一個十幾G的文件redis可能會處于掛起狀態數秒
-
方式可以同時使用也可以單獨,也可以不用
-
redis過期策略
- volatile-lru:從已經設置過期時間的數據集合中通過LRU算法淘汰數據,3.0以前的默認策略:
- volatile-ttl:從過期數據集合中挑選過期時間最小的數據刪掉
- volatile-random:從已過期集合中所見刪除數據
- allkey-lru:從所有數據聚合中通過lru刪掉
- allkey-random:從所有數據集合中隨機刪除
- noenviction:禁止從內存中刪除數據 3.0默認策略
- redis過期策略只在主庫中進行所有很容易在從庫中讀到臟數據:以下方式避免
- 通過sca命令掃庫,相當于訪問這個key,充分發揮惰性刪除,但是確定在于會在掃庫的時候給數據庫帶來一定壓力,所有需要找好時間點去執行。
- 升級redis到3.0版本,在3.0 以后的版本中修復了這個問題,可以在源碼中看到,曾加了對key值的主從庫的判斷,然后key為空,擇返回null
redis緩存遇到的問題
-
緩存穿透:一般緩存系統按照key去緩存查詢,value不存在,就去后端系統查找,如果key對應的value不存在,并且這個key訪問量巨大,這樣會給后端DB造成很大的壓力,這就叫緩存穿透:
- 解決方案一:對查詢結果為空的情況也進行緩存一個null,之后如果insert了之后在清理這個null的緩存
- 對一定不存在的key進行過濾,放到一個足夠大的bitMap中,不存在數據會被這個bitMap攔截
-
緩存雪崩:如果我們設置緩存時候在同一個時刻過期,導致某一個時刻緩存幾乎失效,請求都裝法DB,DB瞬時壓力過大雪崩
- 解決方案:如果需要集中社會緩存過期時間,那么我們一般會在緩存失效時間的計算上加一個隨機數,這樣緩存到期時間就可以分散開
-
緩存擊穿:對于設置了過期時間的key,如果這些key在某些時間點被高超并發訪問,這個時候必須考慮唄擊穿的問題,和雪崩區別在于這是某一個key,正好過期的時候高并發訪問一個key
- 解決方案一:使用互斥鎖,mutex key,就是在緩存失效的時候并不立馬去load db,而是先使用緩存工具中某一些帶成功操作返回值的操作,比如 redis的setNx實現的互斥鎖,他去set一個mutex key,當操作返回成功之后在去load db并且設置到緩存中,如果返回失敗,重試get方法,這樣就可以只有一個請求到DB層,代碼如下
- 解決方案二:可以設置無過期時間,做邏輯過期,在redis上不做過期的設置,就不會出現這種情況,但是在value中設置一個過期的時間,在獲取value之后判斷是否過期,過期擇重新load到cache,這樣可能會有其他線程讀到過期的數據,但是應該影響不大
redis 分布式鎖
- redis中有一個命令 setNx(key存在時候設置值),成功返回1,可以用setNx來爭奪鎖,在通過expire來設置過期時間防止忘記釋放,也可以直接通過redis.setnx(key_mutex, 1, 3 * 60),同時設置值與時間,如下jedisclient源碼:
redis可能有的問題
- redis中有1億個key,其中10萬個是一樣的前綴開頭,如何全部找出來:
- 可以用keys命令,因為redis是單線程的,如果用keys會造成服務停頓
- 用scan遍歷所有key,可以無阻塞的提取指定模式的列表,但是可能會有重復,時間更長
- Redis做異步消息隊列:
- 用list結構可以,通過repush生產消息,lpop消費消息,沒有消息可以sleep之后再做,或者用blpop命令,他會阻塞直到獲取消息。
- 可以用pub/sub命令做消息隊列并且可以實現一次消息消費多次 1:N
- 延遲隊列可以用sort命令對一個set進行排序,排期的對象是時間戳,這樣我們可以通過邏輯去匹配一定時間之前的消息。
- 大量的key需要設置同一時間過期一般需要注意緩存雪崩效應:
- 所有值統一時刻過期,導致直接到DB查詢,可以通過隨機值,分散過期的時間
- redis如何做數據持久化:
- rdb模式我們可以通過bgsave方式主動去觸發,同時也做aof做持久化,bgsave會持續一段時間,不夠實時性,如果機器有問題可能會丟比較多的數據,aof是記錄寫命令,這個丟失的數據比較少,在重啟的時候,會用bgsave的文件進行數據恢復,然后在用aof來恢復沒有備份到文件中的數據,這樣做到最小丟失。
- rdb原理如上:redis通過fork出一個子進程來做bgsave操作,父子進程共享內存直到父進程有寫操作,共享結束。
- redis同步機制:
- redis一般是主從同步,從從同步,master在同步時候,先bgsave一次,期間所有寫入都在緩存buffer,然后將rdb文件同步到從節點,從節點loader到內存,通知主節點將緩存中的寫入同步。
redis集群
- redis3.0 的新特性就是自帶集群功能,3.0 下的集群沒有中心節點,RedisCluster 將所有的key映射到16385個slot中,每一個redis實例負責一部分最少三個實例一個集群,業務程序通過任務一個redisCluster都可以訪問所有的數據,如果數據不再這個節點,那么這個節點會引導客戶端去對應節點獲取信息,redisCluster的管理實通過節點之間的通訊完成,定期交互,定期更新
- 每一個節點都可以配置一個從節點,集群中三個redisCluster某個掛了,從節點將頂替他的位置,,主從復制的功能 和單機的時候一直,所以叫他基于主從配置的redis集群。
總結
以上是生活随笔為你收集整理的Redis数据结构以及对应存储策略的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吃蘑菇可以减肥吗
- 下一篇: Redis和DB数据一致性解决方案