1. 程式人生 > >redis詳解(二)-- 資料型別詳解

redis詳解(二)-- 資料型別詳解

Redis常用資料型別詳解

1,Redis最為常用的資料型別主要有以下:

  • String
  • Hash
  • List
  • Set
  • Sorted set
  • pub/sub
  • Transactions

在具體描述這幾種資料型別之前,我們先通過一張圖瞭解下Redis內部記憶體管理中是如何描述這些不同資料型別的:

首先Redis內部使用一個redisObject物件來表示所有的key和value,redisObject最主要的資訊如上圖所示:type代表一個value物件具體是何種資料型別,encoding是不同資料型別在redis內部的儲存方式,比如:type=string代表value儲存的是一個普通字串,那麼對應的encoding可以是raw或者是int,如果是int則代表實際redis內部是按數值型類儲存和表示這個字串的,當然前提是這個字串本身可以用數值表示,比如:"123" "456"這樣的字串。

這裡需要特殊說明一下vm欄位,只有打開了Redis的虛擬記憶體功能,此欄位才會真正的分配記憶體,該功能預設是關閉狀態的,該功能會在後面具體描述。通過上圖我們可以發現Redis使用redisObject來表示所有的key/value資料是比較浪費記憶體的,當然這些記憶體管理成本的付出主要也是為了給Redis不同資料型別提供一個統一的管理介面,實際作者也提供了多種方法幫助我們儘量節省記憶體使用,我們隨後會具體討論。

2.  各種資料型別應用和實現方式

下面我們先來逐一的分析下這7種資料型別的使用和內部實現方式:

  • String:
Strings 資料結構是簡單的key-value型別,value其實不僅是String,也可以是數字.

常用命令:   set,get,decr,incr,mget 等。

應用場景: String是最常用的一種資料型別,普通的key/ value 儲存都可以歸為此類.即 可以完全實現目前 Memcached 的功能,並且效率更高。還可以享受Redis的定時持久化,操作日誌及 Replication等功能。除了提供與 Memcached 一樣的get、set、incr、decr 等操作外,Redis還提供了下面一些操作:

    • 獲取字串長度
    • 往字串append內容
    • 設定和獲取字串的某一段內容
    • 設定及獲取字串的某一位(bit)
    • 批量設定一系列字串的內容

實現方式: String在redis內部儲存預設就是一個字串,被redisObject所引用,當遇到incr,decr等操作時會轉成數值型進行計算,此時redisObject的encoding欄位為int。

  • Hash

常用命令: hget,hset,hgetall 等。

應用場景: 在Memcached中,我們經常將一些結構化的資訊打包成HashMap,在客戶端序列化後儲存為一個字串的值,比如使用者的暱稱、年齡、性別、積分等,這時候在需要修改其中某一項時,通常需要將所有值取出反序列化後,修改某一項的值,再序列化儲存回去。 這樣不僅增大了開銷,也不適用於一些可能併發操作的場合 (比如兩個併發的操作都需要修改積分)。而Redis的Hash結構可以使你像在資料庫中Update一個屬性一樣只修改某一項屬性值。

        我們簡單舉個例項來描述下Hash的應用場景,比如我們要儲存一個使用者資訊物件資料,包含以下資訊:

使用者ID為查詢的key,儲存的value使用者物件包含姓名,年齡,生日等資訊,如果用普通的key/value結構來儲存,主要有以下2種儲存方式:

 

第一種方式將使用者ID作為查詢key,把其他資訊封裝成一個物件以序列化的方式儲存,這種方式的缺點是,增加了序列化/反序列化的開銷,並且在需要修改其中一項資訊時,需要把整個物件取回,並且修改操作需要對併發進行保護,引入CAS等複雜問題。


第二種方法是這個使用者資訊物件有多少成員就存成多少個key-value對兒,用使用者ID+對應屬性的名稱作為唯一標識來取得對應屬性的值,雖然省去了序列化開銷和併發問題,但是使用者ID為重複儲存,如果存在大量這樣的資料,記憶體浪費還是非常可觀的。

那麼Redis提供的Hash很好的解決了這個問題,Redis的Hash實際是內部儲存的Value為一個HashMap,並提供了直接存取這個Map成員的介面,如下圖:


也就是說,Key仍然是使用者ID, value是一個Map,這個Map的key是成員的屬性名,value是屬性值,這樣對資料的修改和存取都可以直接通過其內部Map的Key(Redis裡稱內部Map的key為field), 也就是通過 key(使用者ID) + field(屬性標籤) 就可以操作對應屬性資料了,既不需要重複儲存資料,也不會帶來序列化和併發修改控制的問題。很好的解決了問題。

這裡同時需要注意,Redis提供了介面(hgetall)可以直接取到全部的屬性資料,但是如果內部Map的成員很多,那麼涉及到遍歷整個內部Map的操作,由於Redis單執行緒模型的緣故,這個遍歷操作可能會比較耗時,而另其它客戶端的請求完全不響應,這點需要格外注意。

實現方式:

上面已經說到Redis Hash對應Value內部實際就是一個HashMap,實際這裡會有2種不同實現,這個Hash的成員比較少時Redis為了節省記憶體會採用類似一維陣列的方式來緊湊儲存,而不會採用真正的HashMap結構,對應的value redisObject的encoding為zipmap,當成員數量增大時會自動轉成真正的HashMap,此時encoding為ht。

  • List

常用命令: lpush,rpush,lpop,rpop,lrange等。

應用場景:

Redis list的應用場景非常多,也是Redis最重要的資料結構之一,比如twitter的關注列表,粉絲列表等都可以用Redis的list結構來實現。

Lists 就是連結串列,相信略有資料結構知識的人都應該能理解其結構。使用Lists結構,我們可以輕鬆地實現最新訊息排行等功能。Lists的另一個應用就是訊息佇列, 
可以利用Lists的PUSH操作,將任務存在Lists中,然後工作執行緒再用POP操作將任務取出進行執行。Redis還提供了操作Lists中某一段的api,你可以直接查詢,刪除Lists中某一段的元素。

實現方式:

Redis list的實現為一個雙向連結串列,即可以支援反向查詢和遍歷,更方便操作,不過帶來了部分額外的記憶體開銷,Redis內部的很多實現,包括髮送緩衝佇列等也都是用的這個資料結構。

  • Set

常用命令:

sadd,spop,smembers,sunion 等。

應用場景:

Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動排重的,當你需要儲存一個列表資料,又不希望出現重複資料時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要介面,這個也是list所不能提供的。

Sets 集合的概念就是一堆不重複值的組合。利用Redis提供的Sets資料結構,可以儲存一些集合性的資料,比如在微博應用中,可以將一個使用者所有的關注人存在一個集合中,將其所有粉絲存在一個集合。Redis還為集合提供了求交集、並集、差集等操作,可以非常方便的實現如共同關注、共同喜好、二度好友等功能,對上面的所有集合操作,你還可以使用不同的命令選擇將結果返回給客戶端還是存集到一個新的集合中。

實現方式:

set 的內部實現是一個 value永遠為null的HashMap,實際就是通過計算hash的方式來快速排重的,這也是set能提供判斷一個成員是否在集合內的原因。

  • Sorted Set

常用命令:

zadd,zrange,zrem,zcard等

使用場景:

Redis sorted set的使用場景與set類似,區別是set不是自動有序的,而sorted set可以通過使用者額外提供一個優先順序(score)的引數來為成員排序,並且是插入有序的,即自動排序。當你需要一個有序的並且不重複的集合列表,那麼可以選擇sorted set資料結構,比如twitter 的public timeline可以以發表時間作為score來儲存,這樣獲取時就是自動按時間排好序的。

另外還可以用Sorted Sets來做帶權重的佇列,比如普通訊息的score為1,重要訊息的score為2,然後工作執行緒可以選擇按score的倒序來獲取工作任務。讓重要的任務優先執行。

實現方式:

Redis sorted set的內部使用HashMap和跳躍表(SkipList)來保證資料的儲存和有序,HashMap裡放的是成員到score的對映,而跳躍表裡存放的是所有的成員,排序依據是HashMap裡存的score,使用跳躍表的結構可以獲得比較高的查詢效率,並且在實現上比較簡單。

  • Pub/Sub

Pub/Sub 從字面上理解就是釋出(Publish)與訂閱(Subscribe),在Redis中,你可以設定對某一個key值進行訊息釋出及訊息訂閱,當一個key值上進行了訊息釋出後,所有訂閱它的客戶端都會收到相應的訊息。這一功能最明顯的用法就是用作實時訊息系統,比如普通的即時聊天,群聊等功能。

  • Transactions

誰說NoSQL都不支援事務,雖然Redis的Transactions提供的並不是嚴格的ACID的事務(比如一串用EXEC提交執行的命令,在執行中伺服器宕機,那麼會有一部分命令執行了,剩下的沒執行),但是這個Transactions還是提供了基本的命令打包執行的功能(在伺服器不出問題的情況下,可以保證一連串的命令是順序在一起執行的,中間有會有其它客戶端命令插進來執行)。Redis還提供了一個Watch功能,你可以對一個key進行Watch,然後再執行Transactions,在這過程中,如果這個Watched的值進行了修改,那麼這個Transactions會發現並拒絕執行。

相關推薦

redis-- 資料型別

Redis常用資料型別詳解 1,Redis最為常用的資料型別主要有以下: StringHashListSetSorted setpub/subTransactions 在具體描述這幾種資料型別之前,我們先通過一張圖瞭解下Redis內部記憶體管理中是如何描述這些不同資

redis-- 資料型別

1.String(字串) string型別是二進位制安全的。意思是redis的string可以包含任何資料。比如jpg圖片或者序列化的物件 。 string型別是Redis最基本的資料型別,一個redis中字串value最多可以是512M 2.Hash(雜湊)

C語言1資料型別

資料型別 關於C語言詳解系列部落格的目錄:https://blog.csdn.net/snake_lp/article/details/78630717點選開啟連結一,概述資料型別就是固定記憶體大小空間

LigerUi之Grid使用——資料編輯(計算每列之和之類的)

qdjianghao2015-2-3 16:13:05閱讀(1064)評論(0) 一、問題概述   在開發web資訊管理系統時,使用Web前端框架可以幫助我們快速搭建一組風格統一的介面效果,而且能夠解決大多數瀏覽器相容問題,提升開發效率。所以上一篇文章為大家介紹了

Golang學習筆記資料型別

Go的資料型別與Java等語言的資料型別幾乎一致 //byte其實就是uint8的別名 var aaa byte = 100 // rune其實就是int32的別名 var bbb rune = 200 //可以給一個字元,計算ascll碼 var ddd byte = 'a' var c

MySQL學習資料型別

擷取書中內容留作學習。。。。 1、整數型別 2、浮點數與定點數型別 3、日期時間型別   向資料庫中插入當前系統時間:CURRENT_TIME或者NOW() 4、文字字串型別   MySQL列舉型別:create table test(enm E

新手初入Java資料型別、變數和常量以及拆包和

資料型別、變數和常量以及拆包和裝包 一、資料型別 Java資料型別分為基本型別(primitive types)和引用型別(reference type),其中基本型別又分為數值型、字元型、布林型。引用型別又分為類型別、介面型別、陣列型別、null型別。這兩種大的型別包含了int

Linux Shell命令 資料型別 表示式

字串 字串是shell程式設計中最常用最有用的資料型別(除了數字和字串,也沒啥其它型別好用了),字串可以用單引號,也可以用雙引號,也可以不用引號。單雙引號的區別跟PHP類似。 單引號 str='this is a string' 單引號字串的限制: 單引號裡的任何字元

lua設計與實現資料型別

lua中的資料型別 //lua.h /* ** basic types */ #define LUA_TNONE (-1) #define LUA_TNIL 0 #define LUA_TBOOLEAN 1 #define LUA_TLIGHTUSERD

Python自動化運維開發----基礎資料型別

一、Python資料型別有三種 (1)數值型別 (2)字串型別 (3)布林型別 二、數值型別  1.分類: (1)整數型 (2)浮點型 (3)正數 (4)負數 2.數值型別的四則運算(加、減、乘、除、整除、餘、冪) >>> 1 +&nb

資料庫資料型別

一、SQL資料型別使用MySQL資料庫儲存資料時,不同的資料型別決定了MySQL儲存資料方式的不同. MySQL中定義資料欄位的型別對你資料庫的優化是非常重要的 MySQL支援所有標準SQL數值資料型別 MySQL支援多種型別,大致可以分為三類 ①數值型別:in

MySQL資料庫---資料型別資料表、約束

資料型別 資料型別是指列、儲存過程引數、表示式和區域性變數的資料特徵,它決定了資料的儲存格式,代表了不同的資訊型別。 整形 TINYINT SMALLINT MEDIUMINT INT BIGINT 浮點型 M是數字總位數 D是小數

資料型別data type

資料型別(data type) 資料型別分為基本資料型別和引用資料型別。 1、基本資料型別 8種基本資料型別。各個基本型別之間是平等的,不存在大小和父子類的關係。它們之間的大小隻是從儲存資料所佔用的空間來比較的。 1.數值型 ​ 1.在Java

redis入門指南—— 資料操作相關命令

寫在前面   以下絕大部分內容取材於《redis入門指南》,部分結合個人知識,實踐後得出。   只記錄重要,明確,屬於新知的相關內容,杜絕冗餘和重複。   字串   1、字串型別是redis中最常見的型別,目前字串資料的最大容量是512M。   2、取值、賦值     SET key value

Redis

redis sentinal redis集群 redis主從 redis事務 一、redis認證二、redis事務三、Connection&server相關命令四、Redis的發布與訂閱//充當mq的功能五、Redis持久化六、redis復制七、master-slave實現八、se

Redis------ redis的配置文件介紹

sha 變化 模塊 arr bin 詳細 特性 disable 是個   上一篇博客我們介紹了如何安裝Redis,在Redis的解壓目錄下有個很重要的配置文件 redis.conf (/opt/redis-4.0.9目錄下),關於Redis的很多功能的配置都在此文件中完成的

Redis底層 字串

一、sds字串概述         sds 字串即 Simple Dynamic String(即簡單動態字串),其中動態的含義是記憶體的分配是動態的,sds的定義如下:        它採用一段連續

資料分析需要學的知識

在上一篇文章中我們提到的需要獲取外部資料和不需要獲取外部資料的資料分析師所需要學習的技能,他們所需學習的技能知識之間差了一個Python爬蟲。當然了,還是需要學習很多的知識的,在這篇文章中就有小編為大家詳細解答一下資料分析師需要學習的知識,其可以分為兩個部分——第一是資料獲取,第二是資料存取。 首先給大

java程式設計師菜鳥進階oracle基礎oracle查詢語句和資料排序

本文所以練習都是基於oracle自帶提供的一個數據庫進行的。資料庫中包含員工表emp。部門資訊表dept。員工工資工總表下面是三個表的表結構:一:基本查詢語句1.最簡單的查詢所有列語句Select * from emp;2.查詢指定列表的查詢語句Select empno ,e

資料分析的資料架構知識

我們在前面的文章中提到了BI系統,從文章中我們不難發現BI系統處理資料的時候都是很有效的,但是當資料量過大的時候,我們系統的效能就會弱了很多。當然了,如果我們處理的資料在TB或者TB以上的資料量的時候,這個系統根本就不能夠正常執行,所以,我們就需要解決這個問題。 大家都知道資料庫的規則是有很多的,資料庫