您好,登錄后才能下訂單哦!
怎樣解決Redis的問題,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
Redis 本質上是一個 Key-Value 類型的內存數據庫, 整個數據庫加載在內存當中進行操作, 定期通過異步操作把數據庫數據 flush 到硬盤上進行保存。
因為是純內存操作, Redis 的性能非常出色, 每秒可以處理超過 10 萬次讀寫操作, 是已知性能
最快的 Key-Value DB。
Redis 的出色之處不僅僅是性能, Redis 最大的魅力是支持保存多種數據結構, 此外單個
value 的最大限制是 1GB, 不像 memcached 只能保存 1MB 的數據, 因此 Redis 可以用
來實現很多有用的功能,比方說用他的 List 來做 FIFO 雙向鏈表,實現一個輕量級的高性 能
消息隊列服務, 用他的 Set 可以做高性能的 tag 系統等等。
另外 Redis 也可以對存入的Key-Value 設置 expire 時間, 因此也可以被當作一 個功能加強版的 memcached 來用。
Redis 的主要缺點是數據庫容量受到物理內存的限制, 不能用作海量數據的高性能讀寫, 因此 Redis 適合的場景主要局限在較小數據量的高性能操作和運算上
(1) memcached 所有的值均是簡單的字符串, Redis 作為其替代者, 支持更為豐富的數據類型
(2)Redis 的速度比 memcached 快很多
(3) Redis 可以持久化其數據
Remote Dictionary Server。
String、 List、 Set、 Sorted Set、 hashes
鴻蒙官方戰略合作共建——HarmonyOS技術社區
noeviction:返回錯誤當內存限制達到并且客戶端嘗試執行會讓更多內存被使用的命令(大部分的寫入指令, 但 DEL 和幾個例外)
allkeys-lru: 嘗試回收最少使用的鍵(LRU), 使得新添加的數據有空間存放。
volatile-lru: 嘗試回收最少使用的鍵(LRU), 但僅限于在過期集合的鍵,使得新添加的數據有空間存放。
allkeys-random: 回收隨機的鍵使得新添加的數據有空間存放。
volatile-random: 回收隨機的鍵使得新添加的數據有空間存放,但僅限于在過期集合的鍵。
volatile-ttl: 回收在過期集合的鍵, 并且優先回收存活時間(TTL) 較短的鍵,使得新添加的數據有空間存放
在做范圍查找的時候,平衡樹比skiplist操作要復雜。在平衡樹上,我們找到指定范圍的小值之后,還需要以中序遍歷的順序繼續尋找其它不超過大值的節點。如果不對平衡樹進行一定的改造,這里的中序遍歷并不容易實現。而在skiplist上進行范圍查找就非常簡單,只需要在找到小值之后,對第1層鏈表進行若干步的遍歷就可以實現。
平衡樹的插入和刪除操作可能引發子樹的調整,邏輯復雜,而skiplist的插入和刪除只需要修改相鄰節點的指針,操作簡單又快速。
從內存占用上來說,skiplist比平衡樹更靈活一些。一般來說,平衡樹每個節點包含2個指針(分別指向左右子樹),而skiplist每個節點包含的指針數目平均為1/(1-p),具體取決于參數p的大小。如果像Redis里的實現一樣,取p=1/4,那么平均每個節點包含1.33個指針,比平衡樹更有優勢。
查找單個key,skiplist和平衡樹的時間復雜度都為O(log n),大體相當;而哈希表在保持較低的哈希值沖突概率的前提下,查找時間復雜度接近O(1),性能更高一些。所以我們平常使用的各種Map或dictionary結構,大都是基于哈希表實現的。
從算法實現難度上來比較,skiplist比平衡樹要簡單得多。
HyperLogLog 是一種概率數據結構,用來估算數據的基數。數據集可以是網站訪客的 IP 地址,E-mail 郵箱或者用戶 ID。
基數就是指一個集合中不同值的數目,比如 a, b, c, d 的基數就是 4,a, b, c, d, a 的基數還是 4。雖然 a 出現兩次,只會被計算一次。
使用 Redis 統計集合的基數一般有三種方法,分別是使用 Redis 的 HashMap,BitMap 和 HyperLogLog。前兩個數據結構在集合的數量級增長時,所消耗的內存會大大增加,但是 HyperLogLog 則不會。
Redis 的 HyperLogLog 通過犧牲準確率來減少內存空間的消耗,只需要12K內存,在標準誤差0.81%的前提下,能夠統計2^64個數據。所以 HyperLogLog 是否適合在比如統計日活月活此類的對精度要不不高的場景。
這是一個很驚人的結果,以如此小的內存來記錄如此大數量級的數據基數。
Redis 為了達到最快的讀寫速度將數據都讀到內存中, 并通過異步的方式將數據寫入磁盤。
所以 Redis 具有快速和數據持久化的特征。 如果不將數據放在內存中, 磁盤 I/O 速度為嚴重
影響 Redis 的性能。 在內存越來越便宜的今天, Redis 將會越來越受歡迎。
String字符串:
格式: set key value
string類型是二進制安全的。意思是redis的string可以包含任何數據。比如jpg圖片或者序列化的對象 。
string類型是Redis最基本的數據類型,一個鍵最大能存儲512MB。
Hash(哈希)
格式: hmset name key1 value1 key2 value2
Redis hash 是一個鍵值(key=>value)對集合。
Redis hash是一個string類型的field和value的映射表,hash特別適合用于存儲對象。
List(列表)
Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)
格式: lpush name value
在 key 對應 list 的頭部添加字符串元素
格式: rpush name value
在 key 對應 list 的尾部添加字符串元素
格式: lrem name index
key 對應 list 中刪除 count 個和 value 相同的元素
格式: llen name
返回 key 對應 list 的長度
Set(集合)
格式: sadd name value
Redis的Set是string類型的無序集合。
集合是通過哈希表實現的,所以添加,刪除,查找的復雜度都是O(1)。
zset(sorted set:有序集合)
格式: zadd name score value
Redis zset 和 set 一樣也是string類型元素的集合,且不允許重復的成員。
不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。
zset的成員是唯一的,但分數(score)卻可以重復。
獲取長度:c字符串并不記錄自身長度,所以獲取長度只能遍歷一遍字符串,redis直接讀取len即可。
緩沖區安全:c字符串容易造成緩沖區溢出,比如:程序員沒有分配足夠的空間就執行拼接操作。而redis會先檢查sds的空間是否滿足所需要求,如果不滿足會自動擴充。
內存分配:由于c不記錄字符串長度,對于包含了n個字符的字符串,底層總是一個長度n+1的數組,每一次長度變化,總是要對這個數組進行一次內存重新分配的操作。因為內存分配涉及復雜算法并且可能需要執行系統調用,所以它通常是比較耗時的操作。
雙端、無環、帶長度記錄、
多態:使用 void* 指針來保存節點值, 可以通過 dup 、 free 、 match 為節點值設置類型特定函數, 可以保存不同類型的值。
其實字典這種數據結構也內置在很多高級語言中,但是c語言沒有,所以redis自己實現了。
應用也比較廣泛,比如redis的數據庫就是字典實現的。不僅如此,當一個哈希鍵包含的鍵值對比較多,或者都是很長的字符串,redis就會用字典作為哈希鍵的底層實現。
LRU全稱是Least Recently Used,即最近最久未使用的意思。
LRU算法的設計原則是:如果一個數據在最近一段時間沒有被訪問到,那么在將來它被訪問的可能性也很小。也就是說,當限定的空間已存滿數據時,應當把最久沒有被訪問到的數據淘汰。
redis原始的淘汰算法簡單實現:當需要淘汰一個key時,隨機選擇3個key,淘汰其中間隔時間最長的key。**基本上,我們隨機選擇key,淘汰key效果很好。后來隨機3個key改成一個配置項"N隨機key"。但把默認值提高改成5個后效果大大提高。考慮到它的效果,你根本不用修改他。
鴻蒙官方戰略合作共建——HarmonyOS技術社區
RDB持久化可以手動執行,也可以配置定期執行,可以把某個時間的數據狀態保存到RDB文件中,反之,我們可以用RDB文件還原數據庫狀態。
AOF持久化是通過保存服務器執行的命令來記錄狀態的。還原的時候再執行一遍即可。
一般來說, 如果想達到足以媲美 PostgreSQL 的數據安全性, 你應該同時使用兩種持久
化功能。 如果你非常關心你的數據, 但仍然可以承受數分鐘以內的數據丟失, 那么你可以
只使用 RDB 持久化。
有很多用戶都只使用 AOF 持久化, 但并不推薦這種方式: 因為定時生成 RDB 快照
(snapshot) 非常便于進行數據庫備份, 并且 RDB 恢復數據集的速度也要比 AOF 恢復
的速度要快, 除此之外, 使用 RDB 還可以避免之前提到的 AOF 程序的 bug。
1.twemproxy, 大概概念是, 它類似于一個代理方式, 使用方法和普通 Redis 無任何區別,
設 置 好它 下 屬 的多 個 Redis 實 例 后, 使 用 時在 本 需 要 連接 Redis 的 地 方改 為 連接
twemproxy, 它會以一個代理的身份接收請求并使用一致性 hash 算法, 將請求轉接到具
體 Redis, 將結果再返回 twemproxy。 使用方式簡便(相對 Redis 只需修改連接端口), 對
舊項目擴展的首選。 問題: twemproxy 自身單端口實例的壓力, 使用一致性 hash 后, 對
Redis 節點數量改變時候的計算值的改變, 數據無法自動移動到新的節點。
2. codis, 目前用的最多的集群方案, 基本和 twemproxy 一致的效果, 但它支持在 節點
數量改變情況下, 舊節點數據可恢復到新 hash 節點。
3. Redis cluster3.0 自帶的集群, 特點在于他的分布式算法不是一致性 hash, 而是 hash
槽的概念, 以及自身支持節點設置從節點。 具體看官方文檔介紹。
4.在業務代碼層實現, 起幾個毫無關聯的 Redis 實例, 在代碼層, 對 key 進行 hash 計算,
然后去對應的 Redis 實例操作數據。 這種方式對 hash 層代碼要求比較高, 考慮部分包括,
節點失效后的替代算法方案, 數據震蕩后的自動腳本恢復, 實例的監控, 等等
MySQL 里有 2000w 數據, Redis 中只存 20w 的數據,
如何保證 Redis 中的數據都是熱點數據?
Redis 內存數據集大小上升到一定大小的時候, 就會施行數據淘汰策略
(1)、 會話緩存(Session Cache)
最常用的一種使用 Redis 的情景是會話緩存(session cache)。 用 Redis 緩存會話比其他
存儲(如 Memcached) 的優勢在于: Redis 提供持久化。 當維護一個不是嚴格要求一致性
的緩存時, 如果用戶的購物車信息全部丟失, 大部分人都會不高興的, 現在, 他們還會這樣
嗎?
幸運的是, 隨著 Redis 這些年的改進, 很容易找到怎么恰當的使用 Redis 來緩存會話的文
檔。 甚至廣為人知的商業平臺 Magento 也提供 Redis 的插件。
(2)、 全頁緩存(FPC)
除基本的會話 token 之外, Redis 還提供很簡便的 FPC 平臺。 回到一致性問題, 即使重啟
了 Redis 實例, 因為有磁盤的持久化, 用戶也不會看到頁面加載速度的下降, 這是一個極
大改進, 類似 PHP 本地 FPC。
再次以 Magento 為例, Magento 提供一個插件來使用 Redis 作為全頁緩存后端。
此外, 對 WordPress 的用戶來說, Pantheon 有一個非常好的插件 wp-Redis, 這個插件
能幫助你以最快速度加載你曾瀏覽過的頁面。
(3)、 隊列
Reids 在內存存儲引擎領域的一大優點是提供 list 和 set 操作,這使得 Redis 能作為一個
很好的消息隊列平臺來使用。 Redis 作為隊列使用的操作, 就類似于本地程序語言(如
Python) 對 list 的 push/pop 操作。
如果你快速的在 Google 中搜索“Redis queues”, 你馬上就能找到大量的開源項目, 這些
項目的目的就是利用 Redis 創建非常好的后端工具, 以滿足各種隊列需求。 例如, Celery
有一個后臺就是使用 Redis 作為 broker, 你可以從這里去查看。
(4)、 排行榜/計數器
Redis在內存中對數字進行遞增或遞減的操作實現的非常好。集合(Set)和有序集合(Sorted
Set) 也使得我們在執行這些操作的時候變的非常簡單, Redis 只是正好提供了這兩種數據
結構。 所以, 我們要從排序集合中獲取到排名最靠前的 10 個用戶–我們稱之為
“user_scores”, 我們只需要像下面一樣執行即可:
當然, 這是假定你是根據你用戶的分數做遞增的排序。 如果你想返回用戶及用戶的分數, 你
需要這樣執行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games 就是一個很好的例子, 用 Ruby 實現的, 它的排行榜就是使用 Redis 來存儲
數據的, 你可以在這里看到。
(5)、 發布/訂閱
最后 是 Redis 的發布/訂閱功能。 發布/訂閱的使用場景確實非
常多。 我已看見人們在社交網絡連接中使用, 還可作為基于發布/訂閱的腳本觸發器, 甚至
用 Redis 的發布/訂閱功能來建立聊天系統。
說說 Redis 哈希槽的概念?
Redis 集群沒有使用一致性 hash,而是引入了哈希槽的概念, Redis 集群有 16384 個哈希槽,
每個 key 通過 CRC16 校驗后對 16384 取模來決定放置哪個槽, 集群的每個節點負責一部分
hash 槽
(1)如果槽位為65536,發送心跳信息的消息頭達8k,發送的心跳包過于龐大。
如上所述,在消息頭中,最占空間的是myslots[CLUSTER_SLOTS/8]。 當槽位為65536時,這塊的大小是: 65536÷8÷1024=8kb 因為每秒鐘,redis節點需要發送一定數量的ping消息作為心跳包,如果槽位為65536,這個ping消息的消息頭太大了,浪費帶寬。
(2)redis的集群主節點數量基本不可能超過1000個。
如上所述,集群節點越多,心跳包的消息體內攜帶的數據越多。如果節點過1000個,也會導致網絡擁堵。因此redis作者,不建議redis cluster節點數量超過1000個。 那么,對于節點數在1000以內的redis cluster集群,16384個槽位夠用了。沒有必要拓展到65536個。
(3)槽位越小,節點少的情況下,壓縮比高
Redis主節點的配置信息中,它所負責的哈希槽是通過一張bitmap的形式來保存的,在傳輸過程中,會對bitmap進行壓縮,但是如果bitmap的填充率slots / N很高的話(N表示節點數),bitmap的壓縮率就很低。 如果節點數很少,而哈希槽數量很多的話,bitmap的壓縮率就很低。
Redis 并不能保證數據的強一致性, 這意味這在實際中集群在特定的條件下可能會丟失寫操
作。
1.twemproxy,大概概念是,它類似于一個代理方式, 使用時在本需要連接 redis 的地方改為連接 twemproxy, 它會以一個代理的身份接收請求并使用一致性 hash 算法,將請求轉接到具體 redis,將結果再返回 twemproxy。
缺點: twemproxy 自身單端口實例的壓力,使用一致性 hash 后,對 redis 節點數量改變時候的計算值的改變,數據無法自動移動到新的節點。
2.codis,目前用的最多的集群方案,基本和 twemproxy 一致的效果,但它支持在 節點數量改變情況下,舊節點數據可恢復到新 hash 節點
3.redis cluster3.0 自帶的集群,特點在于他的分布式算法不是一致性 hash,而是 hash 槽的概念,以及自身支持節點設置從節點。具體看官方文檔介紹。
分區可以讓 Redis 管理更大的內存, Redis 將可以使用所有機器的內存。 如果沒有分區, 你
最多只能使用一臺機器的內存。 分區使 Redis 的計算能力通過簡單地增加計算機得到成倍提
升,Redis 的網絡帶寬也會隨著計算機和網卡的增加而成倍增長。
涉及多個 key 的操作通常不會被支持。 例如你不能對兩個集合求交集, 因為他們可能被存
儲到不同的 Redis 實例(實際上這種情況也有辦法, 但是不能直接使用交集指令)。
同時操作多個 key,則不能使用 Redis 事務.
分區使用的粒度是key,不能使用一個非常長的排序key存儲一個數據集(The partitioning
granularity is the key, so it is not possible to shard a dataset with a single huge
key like a very big sorted set) .
當使用分區的時候, 數據處理會非常復雜, 例如為了備份你必須從不同的 Redis 實例和主
機同時收集 RDB / AOF 文件。
分區時動態擴容或縮容可能非常復雜。 Redis 集群在運行時增加或者刪除 Redis 節點, 能
做到最大程度對用戶透明地數據再平衡,但其他一些客戶端分區或者代理分區方法則不支持
這種特性。 然而, 有一種預分片的技術也可以較好的解決這個問題。
Redis 有著更為復雜的數據結構并且提供對他們的原子性操作,這是一個不同于其他數據庫
的進化路徑。 Redis 的數據類型都是基于基本數據結構的同時對程序員透明, 無需進行額外
的抽象。
Redis 運行在內存中但是可以持久化到磁盤,所以在對不同數據集進行高速讀寫時需要權衡
內存, 應為數據量不能大于硬件內存。 在內存數據庫方面的另一個優點是, 相比在磁盤上
相同的復雜的數據結構, 在內存中操作起來非常簡單, 這樣 Redis 可以做很多內部復雜性
很強的事情。 同時, 在磁盤格式方面他們是緊湊的以追加的方式產生的, 因為他們并不需
要進行隨機訪問
如果達到設置的上限, Redis 的寫命令會返回錯誤信息(但是讀命令還可以正常返回。) 或
者你可以將 Redis 當緩存來使用配置淘汰機制,當 Redis 達到內存上限時會沖刷掉舊的內容。
可以在同一個服務器部署多個 Redis 的實例, 并把他們當作不同的服務器來使用, 在某些時
候, 無論如何一個服務器是不夠的,
所以, 如果你想使用多個 CPU, 你可以考慮一下分片(shard)。
一個 Redis 實例最多能存放多少的 keys? List、 Set、Sorted Set 他們最多能存放多少元素?
理論上 Redis 可以處理多達 232 的 keys, 并且在實際中進行了測試, 每個實例至少存放了 2億 5 千萬的 keys。 我們正在測試一些較大的值。
任何 list、 set、 和 sorted set 都可以放 232 個元素。
換句話說, Redis 的存儲極限是系統中的可用內存值
針對運行實例, 有許多配置選項可以通過 CONFIG SET 命令進行修改, 而無需執行任何
形式的重啟。 從 Redis 2.2 開始, 可以從 AOF 切換到 RDB 的快照持久性或其他方式
而不需要重啟 Redis。 檢索 ‘CONFIG GET *’ 命令獲取更多信息。
但偶爾重新啟動是必須的, 如為升級 Redis 程序到新的版本, 或者當你需要修改某些目前
CONFIG 命令還不支持的配置參數的時候
Redis sentinel 是一個分布式系統中監控 redis 主從服務器,并在主服務器下線時自動進行故障轉移。其中三個特性:
監控(Monitoring): Sentinel 會不斷地檢查你的主服務器和從服務器是否運作正常。
提醒(Notification): 被監控的某個 Redis 服務器出現問題時, Sentinel 可以通過 API 向管理員或者其他應用程序發送通知。
自動故障遷移(Automatic failover): 當一個主服務器不能正常工作時, Sentinel 會開始一次自動故障遷移操作。
特點:
1、保證高可用
2、監控各個節點
3、自動故障遷移
缺點:主從模式,切換需要時間丟數據
沒有解決 master 寫的壓力
一般的緩存系統,都是按照key去緩存查詢,如果不存在對應的value,就去后端系統查找(比如DB)。
一些惡意的請求會故意查詢不存在的key,請求量很大,就會對后端系統造成很大的壓力。這就叫做緩存穿透。
如何避免?
1:對查詢結果為空的情況也進行緩存,這樣,再次訪問時,緩存層會直接返回空值。緩存時間設置短一點,或者該key對應的數據insert了之后清理緩存。
2:對一定不存在的key進行過濾。具體請看布隆過濾器
是針對緩存中沒有但數據庫有的數據。
場景是,當Key失效后,假如瞬間突然涌入大量的請求,來請求同一個Key,這些請求不會命中Redis,都會請求到DB,導致數據庫壓力過大,甚至扛不住,掛掉。
解決辦法
1、設置熱點Key,自動檢測熱點Key,將熱點Key的過期時間加大或者設置為永不過期,或者設置為邏輯上永不過期
2、加互斥鎖。當發現沒有命中Redis,去查數據庫的時候,在執行更新緩存的操作上加鎖,當一個線程訪問時,其它線程等待,這個線程訪問過后,緩存中的數據會被重建,這樣其他線程就可以從緩存中取值。
是指大量Key同時失效,對這些Key的請求又會打到DB上,同樣會導致數據庫壓力過大甚至掛掉。
解決辦法
1)讓Key的失效時間分散開,可以在統一的失效時間上再加一個隨機值,或者使用更高級的算法分散失效時間。
2)構建多個redis實例,個別節點掛了還有別的可以用。
3)多級緩存:比如增加本地緩存,減小redis壓力。
4)對存儲層增加限流措施,當請求超出限制,提供降級服務(一般就是返回錯誤即可)
單線程的redis為什么這么快
(一)純內存操作
(二)單線程操作,避免了頻繁的上下文切換
(三)采用了非阻塞I/O多路復用機制
(其實就是歷史遺留問題,非要吹的這么好。。。)
redis采用的是定期刪除+惰性刪除策略。
為什么不用定時刪除策略?
定時刪除,用一個定時器來負責監視key,過期則自動刪除。雖然內存及時釋放,但是十分消耗CPU資源。在大并發請求下,CPU要將時間應用在處理請求,而不是刪除key,因此沒有采用這一策略.
定期刪除+惰性刪除是如何工作的呢?
定期刪除,redis默認每個100ms檢查,是否有過期的key,有過期key則刪除。需要說明的是,redis不是每個100ms將所有的key檢查一次,而是隨機抽取進行檢查(如果每隔100ms,全部key進行檢查,redis豈不是卡死)。因此,如果只采用定期刪除策略,會導致很多key到時間沒有刪除。
于是,惰性刪除派上用場。也就是說在你獲取某個key的時候,redis會檢查一下,這個key如果設置了過期時間那么是否過期了?如果過期了此時就會刪除。
對于Redis而言,命令的原子性指的是:一個操作的不可以再分,操作要么執行,要么不執行。
Redis的操作之所以是原子性的,是因為Redis是單線程的。
Redis本身提供的所有API都是原子操作,Redis中的事務其實是要保證批量操作的原子性。
不一定, 將get和set改成單命令操作,incr 。使用Redis的事務,或者使用Redis+Lua==的方式實現.
不要使用redis去做消息隊列,這不是redis的設計目標。但實在太多人使用redis去做去消息隊列,redis的作者看不下去。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。