本文目錄一覽:
Redis — 八種數據類型(基本命令)
String、Hash、List、Set和Zset。
等同於java中的, MapString,String string 是redis裡面的最基本的數據類型,一個key對應一個value。
應用場景 :String是最常用的一種數據類型,普通的key/value存儲都可以歸為此類,如用戶信息,登錄信息和配置信息等;
實現方式 :String在redis內部存儲默認就是一個字元串,被redisObject所引用,當遇到incr、decr等操作(自增自減等原子操作)時會轉成數值型進行計算,此時redisObject的encoding欄位為int。
Redis雖然是用C語言寫的,但卻沒有直接用C語言的字元串,而是自己實現了一套字元串。目的就是為了提升速度,提升性能。 Redis構建了一個叫做簡單動態字元串(Simple Dynamic String),簡稱SDS。
Redis的字元串也會遵守C語言的字元串的實現規則,即 最後一個字元為空字元。然而這個空字元不會被計算在len裡頭。
Redis動態擴展步驟:
Redis字元串的性能優勢
常用命令 :set/get/decr/incr/mget等,具體如下;
ps:計數器(字元串的內容為整數的時候可以使用),如 set number 1。
補充:
等同於java中的: MapString,MapString,String ,redis的hash是一個string類型的field和value的映射表, 特別適合存儲對象。 在redis中,hash因為是一個集合,所以有兩層。第一層是key:hash集合value,第二層是hashkey:string value。所以判斷是否採用hash的時候可以參照有兩層key的設計來做參考。並且注意的是, 設置過期時間只能在第一層的key上面設置。
應用場景 :我們要存儲一個用戶信息對象數據,其中包括用戶ID、用戶姓名、年齡和生日,通過用戶ID我們希望獲取該用戶的姓名或者年齡或者生日;
實現方式 :Redis的Hash實際是內部存儲的Value為一個HashMap,並提供了直接存取這個Map成員的介面。如,Key是用戶ID, value是一個Map。 這個Map的key是成員的屬性名,value是屬性值 。這樣對數據的修改和存取都可以直接通過其內部Map的Key(Redis里稱內部Map的key為field), 也就是通過 key(用戶ID) + field(屬性標籤) 就可以操作對應屬性數據。 當前HashMap的實現有兩種方式 :當HashMap的成員比較少時Redis為了節省內存會採用類似一維數組的方式來緊湊存儲,而不會採用真正的HashMap結構,這時對應的value的redisObject的encoding為zipmap,當成員數量增大時會自動轉成真正的HashMap,此時redisObject的encoding欄位為int。
常用命令 :hget/hset/hgetall等,具體如下:
等同於java中的 MapString,ListString ,list 底層是一個鏈表,在redis中,插入list中的值,只需要找到list的key即可,而不需要像hash一樣插入兩層的key。 list是一種有序的、可重複的集合。
應用場景 :Redis list的應用場景非常多,也是Redis最重要的數據結構之一,比如twitter的關注列表,粉絲列表等都可以用Redis的list結構來實現;
實現方式 :Redis list的實現為一個 雙向鏈表 ,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷,Redis內部的很多實現,包括 發送緩衝隊列 等也都是用的這個數據結構。
常用命令 :lpush/rpush/lpop/rpop/lrange等,具體如下:
性能總結 :
它是一個字元串鏈表,left、right都可以插入添加。
等同於java中的 MapString,SetString ,Set 是一種無序的,不能重複的集合。並且在redis中,只有一個key它的底層由hashTable實現的,天生去重。
應用場景 :Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動去重的,當你需要存儲一個列表數據,又不希望出現重複數據時,set是一個很好的選擇,並且 set提供了判斷某個成員是否在一個set集合內的重要介面 ,這個也是list所不能提供的;如保存一些標籤的名字。標籤的名字不可以重複,順序是可以無序的。
實現方式 :set 的內部實現是一個 value永遠為null的HashMap,實際就是通過計算hash的方式來快速排重的,這也是set能提供判斷一個成員是否在集合內的原因。
常用命令 :sadd/spop/smembers/sunion等,具體如下:
ZSet(Sorted Set:有序集合) 每個元素都會關聯一個double類型的分數score,分數允許重複,集合元素按照score排序( 當score相同的時候,會按照被插入的鍵的字典順序進行排序 ),還可以通過 score 的範圍來獲取元素的列表。
應用場景 :Redis sorted set的使用場景與set類似,區別是set不是自動有序的,而sorted set可以 通過用戶額外提供一個優先順序(score)的參數來為成員排序,並且是插入有序的,即自動排序。 當你需要一個有序的並且不重複的集合列表,那麼可以選擇sorted set數據結構,比如twitter 的public timeline可以以發表時間作為score來存儲,這樣獲取時就是自動按時間排好序的。
底層實現 : zset 是 Redis 提供的一個非常特別的數據結構,常用作排行榜等功能,以用戶 id 為 value ,關注時間或者分數作為 score 進行排序。實現機制分別是 zipList 和 skipList 。規則如下:
zipList:滿足以下兩個條件
skipList:不滿足以上兩個條件時使用跳錶、組合了hash和skipList
為什麼用skiplist不用平衡樹?
主要從內存佔用、對範圍查找的支持和實現難易程度這三方面總結的原因。
拓展:mysql為什麼不用跳錶?
常用命令 :zadd/zrange/zrem/zcard等;
官網地址:
可以用來推算兩地之間的距離,方圓半徑內的人。
關於經度緯度的限制:
一般我們使用Hyperloglog做基數統計。
什麼是基數?就是一個集合中不重複的數的個數。
集合A:{1,3,5,7,9,7}
集合B:{1,3,5,7,9}
AB集合的基數都是5
應用:統計網站的訪問量(一個人訪問網站很多次仍然算作一次)。
優點:佔用的內存是固定的,找2^64次方個數的基數,只需要12KB內存。
缺點:有0.81%的錯誤率,可以忽略不計
概述: bitmap 存儲的是連續的二進位數字(0 和 1),通過 bitmap, 只需要一個 bit 位來表示某個元素對應的值或者狀態,key 就是對應元素本身 。 我們知道 8 個 bit 可以組成一個 byte,所以 bitmap 本身會極大的節省儲存空間。
應用場景: 適合需要保存狀態信息(比如是否簽到、是否登錄…)並需要進一步對這些信息進行分析的場景。比如用戶簽到情況、活躍用戶情況、用戶行為統計(比如是否點贊過某個視頻)。
針對上面提到的一些場景,這裡進行進一步說明。
使用場景一:用戶行為分析 很多網站為了分析你的喜好,需要研究你點贊過的內容。
使用場景二:統計活躍用戶
使用時間作為 key,然後用戶 ID 為 offset,如果當日活躍過就設置為 1
那麼我該如果計算某幾天/月/年的活躍用戶呢(暫且約定,統計時間內只有有一天在線就稱為活躍),有請下一個 redis 的命令
使用場景三:用戶在線狀態
對於獲取或者統計用戶在線狀態,使用 bitmap 是一個節約空間效率又高的一種方法。
只需要一個 key,然後用戶 ID 為 offset,如果在線就設置為 1,不在線就設置為 0。
補充 :
巨人的肩膀:
redis是使用c語言開發的么
Redis(Remote Dictionary Server ),即遠程字典服務,是一個開源的使用ANSI C語言編寫、支持網路、可基於內存亦可持久化的日誌型、Key-Value資料庫。
詳解Redis 主從複製及主從複製原理
Redis是一個開源的使用ANSI C語言編寫、支持網路、可基於內存亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。從2010年3月15日起,Redis的開發工作由VMware主持。從2013年5月開始,Redis的開發由Pivotal贊助。
概述
在現有企業中80%公司大部分使用的是redis單機服務,在實際的場景當中單一節點的redis容易面臨風險。
2、容量瓶頸。 當我們有需求需要擴容 Redis 內存時,從 16G 的內存升到 64G,單機肯定是滿足不了。當然,你可以重新買個 128G 的新機器。
解決辦法
要實現分散式資料庫的更大的存儲容量和承受高並發訪問量,我們會將原來集中式資料庫的數據分別存儲到其他多個網路節點上。
Redis 為了解決這個單一節點的問題,也會把數據複製多個副本部署到其他節點上進行複製,實現 Redis的高可用,實現對數據的冗餘備份,從而保證數據和服務的高可用。
主從複製
什麼是主從複製
主從複製,是指將一台Redis伺服器的數據,複製到其他的Redis伺服器。前者稱為主節點(master),後者稱為從節點(slave),數據的複製是單向的,只能由主節點到從節點。
默認情況下,每台Redis伺服器都是主節點;且一個主節點可以有多個從節點(或沒有從節點),但一個從節點只能有一個主節點。
主從複製的作用
1、數據冗餘: 主從複製實現了數據的熱備份,是持久化之外的一種數據冗餘方式。
2、故障恢復: 當主節點出現問題時,可以由從節點提供服務,實現快速的故障恢復;實際上是一種服務的冗餘。
3、負載均衡: 在主從複製的基礎上,配合讀寫分離,可以由主節點提供寫服務,由從節點提供讀服務(即寫Redis數據時應用連接主節點,讀Redis數據時應用連接從節點),分擔伺服器負載;尤其是在寫少讀多的場景下,通過多個從節點分擔讀負載,可以大大提高Redis伺服器的並發量。
4、讀寫分離: 可以用於實現讀寫分離,主庫寫、從庫讀,讀寫分離不僅可以提高伺服器的負載能力,同時可根據需求的變化,改變從庫的數量。
5、高可用基石: 除了上述作用以外,主從複製還是哨兵和集群能夠實施的基礎,因此說主從複製是Redis高可用的基礎。
主從複製啟用
從節點開啟主從複製,有3種方式:
1、配置文件: 在從伺服器的配置文件中加入 slaveofmasteripmasterport。
2、啟動命令: redis-server啟動命令後加入 –slaveofmasteripmasterport。
3、客戶端命令: Redis伺服器啟動後,直接通過客戶端執行命令 slaveofmasteripmasterport,則該Redis實例成為從節點。
通過 info replication 命令可以看到複製的一些信息。
主從複製原理
主從複製過程大體可以分為3個階段:連接建立階段(即準備階段)、數據同步階段、命令傳播階段。
在從節點執行 slaveof 命令後,複製過程便開始運作,下面圖示可以看出複製過程大致分為6個過程。
主從配置之後的日誌記錄也可以看出這個流程。
1、保存主節點(master)信息
執行 slaveof 後 Redis 會列印如下日誌:
2、從節點與主節點建立網路連接
從節點(slave)內部通過每秒運行的定時任務維護複製相關邏輯,當定時任務發現存在新的主節點後,會嘗試與該節點建立網路連接。
從節點與主節點建立網路連接。
從節點會建立一個 socket 套接字,從節點建立了一個埠為51234的套接字,專門用於接受主節點發送的複製命令。從節點連接成功後列印如下日誌:
如果從節點無法建立連接,定時任務會無限重試直到連接成功或者執行 slaveofnoone 取消複製。
關於連接失敗,可以在從節點執行 info replication 查看 master_link_down_since_seconds 指標,它會記錄與主節點連接失敗的系統時間。從節點連接主節點失敗時也會每秒列印如下日誌,方便發現問題:
3、發送 ping 命令
連接建立成功後從節點發送 ping 請求進行首次通信, ping 請求主要目的如下:
如果發送 ping 命令後,從節點沒有收到主節點的 pong 回復或者超時,比如網路超時或者主節點正在阻塞無法響應命令,從節點會斷開複製連接,下次定時任務會發起重連。
從節點發送的 ping 命令成功返回,Redis 列印如下日誌,並繼續後續複製流程:
4、許可權驗證
如果主節點設置了 requirepass 參數,則需要密碼驗證,從節點必須配置 masterauth 參數保證與主節點相同的密碼才能通過驗證。如果驗證失敗複製將終止,從節點重新發起複制流程。
5、同步數據集
主從複製連接正常通信後,對於首次建立複製的場景,主節點會把持有的數據全部發送給從節點,這部分操作是耗時最長的步驟。
6、命令持續複製
當主節點把當前的數據同步給從節點後,便完成了複製的建立流程。接下來主節點會持續地把寫命令發送給從節點,保證主從數據一致性。
作者:LoyaltyLu
鏈接:
4、Redis高性能的根本原理
內存的讀寫速度很快
Epoll 模型
常用的五大Redis的數據結構,及他們各自的底層實現結構
string hash list set sortset(zset)
string 的底層實現是 簡單動態字元串(SDS -simple dynamic string)
hash 的底層實現是 hash表 或則 壓縮列表(ziplist)
list 的底層實現是 雙向列表(quicklist) 或者 壓縮列表
set 的底層實現是 hash表(hashtable) 或者 整數數組
sortset(zset) 的底層實現是 壓縮列表 或者 跳錶
各個數據結構的底層實現概覽
value是 string 類型的時候分為三種情況
(1)、當設置的值是整數類型的時候,redis底層會將 string 類型轉化為 int 來存儲
(2)、設置的值小於等於44個位元組的時候,使用的編碼是 embstr
(3)、設置的值大於44個位元組的時候,使用的編碼是 raw
redis是用C語言編寫的,在C語言中 string 類型是用字元數組 char[] 來實現的。redis實現字元串的底層並沒有直接使用C語言中的字元數組的形式,而是進行了改造,構造出了一種SDS的數據結構
list的底層使用 快速雙向鏈表quicklist 或者 壓縮鏈表ziplist 來實現的。
list的底層並沒有使用傳統的雙向鏈表的結構是因為
(1)、雙向鏈表需要有一個 前指針 和 後指針 ,每個指針佔用的空間分別都是8byte, 佔用內存 比較多
(2)、雙向鏈表所通用的一個問題是會形成很多的 內存碎片
壓縮鏈表 ziplist 結構是
快速雙向鏈表 quicklist 結構
hash的底層實現為 hashtable 或者 ziplist 。
hashtable的底層實現
當數據量比較小或者單個元素的時候,底層使用的是ziplist存儲,具體可以通過配置來制定
1、 hashtable 是無序的 ziplist 是有序的
2、在能使用 hash 的情況下優先使用 hash ,不要使用 String ,因為使用太多的 String ,則會創建出過多的 key ,當 key 大量的時候,就會容易發生 hash碰撞 ,所以就需要頻繁的 rehash ,每次 rehash 就會創建2倍的內存,造成內存浪費
hash的底層實現為 整數數組intset 或者 hashtable 。
當set都為整數的時候,set的底層實現都是使用 intset 結構實現
如果set中存在字元串的值,則使用 hashtable 來實現
intset 是有序的, hashtable 是無序的
sortset 底層使用 壓縮列表ziplist 或 跳錶skiplist 的結構實現
當數據量小的情況下,使用 ziplist 實現,當數據量大的情況下使用 ziplist 實現,具體可以通過配置設置
默認設置下的底層結構
skiplist 的底層實現
查找對應元素的時候,先從最高的索引層找,例如找c 150,則先從L1找,L1的指針指向b,查看b120小於150,則繼續往後找,b的指針指向null,則向下一層找,向下一層b的指針指向c,查看c的score為150,所以找到對應的元素c
1、
什麼是redis呢,求通俗解釋
Redis是一個開源的使用ANSI C語言編寫、支持網路、可基於內存亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。從2010年3月15日起,Redis的開發工作由VMware主持。
redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字元串)、list(鏈表)、set(集合)、zset(sorted set –有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁碟或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。
Redis 是一個高性能的key-value資料庫。 redis的出現,很大程度補償了memcached這類key/value存儲的不足,在部 分場合可以對關係資料庫起到很好的補充作用。它提供了Python,Ruby,Erlang,PHP客戶端,使用很方便。[1]
Redis支持主從同步。數據可以從主伺服器向任意數量的從伺服器上同步,從伺服器可以是關聯其他從伺服器的主伺服器。這使得Redis可執行單層樹複製。從盤可以有意無意的對數據進行寫操作。由於完全實現了發布/訂閱機制,使得從資料庫在任何地方同步樹時,可訂閱一個頻道並接收主伺服器完整的消息發布記錄。同步對讀取操作的可擴展性和數據冗餘很有幫助。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/231405.html