?導(dǎo)讀
redis是一個基于內(nèi)存的key-value數(shù)據(jù)庫,相對關(guān)系型數(shù)據(jù)庫支持的數(shù)據(jù)結(jié)構(gòu)更豐富拇泛,而且操作封裝的非常簡單易用。redis也支持主從熄守、分布式、數(shù)據(jù)持久化等特性牍氛。
? ?redis在業(yè)務(wù)系統(tǒng)中經(jīng)常用作緩存系統(tǒng),即把熱點數(shù)據(jù)或高頻數(shù)據(jù)存到Redis唉擂,降低底層數(shù)據(jù)庫負(fù)載、提高應(yīng)用吞吐率空扎;redis靈活的數(shù)據(jù)結(jié)構(gòu)也能解決特定大數(shù)據(jù)統(tǒng)計中的痛點,這里結(jié)合實際項目撮慨,舉些典型應(yīng)用場景影涉,以及個人的理解,當(dāng)然也是蜻蜓點水,泛泛而談萧朝,希望大方向上能對大家有所幫助竖配,當(dāng)然有不正之處也請不吝賜教用爪。
Sets
集合的最主要特征是成員唯一性,最常用場景是一些涉及到去重的計算颇玷,比如UV計算(去重用戶數(shù)):每次當(dāng)用戶活躍時簡單的調(diào)用SADD命令向集合添加UID竭宰,然后實時的用SCARD獲取元素個數(shù)渣淳。還支持多個集合之間的交集(SINTER)、差集(SDIFF)和并集( SUNION)運算怔蚌,交集操作可以很便捷的計算留存率:(今日集合∩昨日集合)/昨日集合。集合是通過哈希表實現(xiàn)的,所以添加杖狼、刪除、查找的復(fù)雜度都是O(1),即復(fù)雜度和元素個數(shù)無關(guān)熄攘。
Sorted sets
????有序集合相比集合每個成員多了分?jǐn)?shù)屬性国拇,成員會按照分?jǐn)?shù)自動從小到大排序,當(dāng)然和集合類似忆嗜,成員也是唯一不重復(fù)的冲甘。常用查詢方法:排名在指定范圍的成員濒憋、分?jǐn)?shù)在指定范圍內(nèi)的成員裆站。應(yīng)用場景:
1本姥、TOPN排名颜屠,商品瀏覽量作為排名指標(biāo),實時查詢TOPN的商品列表,其實現(xiàn)過程是:商品每次被訪問時,用ZINCRBY增加商品瀏覽量,實時用ZREVRANGE?key 0 N-1返回集合中TOPN的商品秩霍。
2螺捐、30分鐘在線用戶數(shù)颠悬,APP矮燎、WEB都有統(tǒng)計最近在線用戶數(shù)的需求,是衡量產(chǎn)品當(dāng)前活躍度的重要指標(biāo)椿疗,有序集合也可以很容易實現(xiàn):以登錄時間戳作為用戶分?jǐn)?shù)漏峰,每次登錄時更新用戶分?jǐn)?shù),“ZADD?key 登錄時間戳 UID”铝条,然后用“ZCOUNT?key 30分鐘前時間戳 now時間戳”命令查詢最近登錄用戶數(shù)
? ? ?有序集合是通過跳表和散列表兩個數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的脾拆,添加名船、刪除元素都會執(zhí)行O(log(N))的操作(N是集合的元素個數(shù))。有序集合的關(guān)鍵是在對分?jǐn)?shù)這個屬性的理解上,從合適的角度看問題产镐,會達到事半功倍的效果丑掺。
Bitmaps
Redis允許使用二進制的數(shù)據(jù)作為Key(binary keys) 和二進制的數(shù)據(jù)作為Value(binary values)唆缴,bitmap就是用二進制的數(shù)據(jù)作為value。bitmap不是一個新的數(shù)據(jù)類型霎匈,而是在String類型上進行的擴展蚓让,相關(guān)的命令有setbit衷佃、getbit趟卸、bitcount等。
SETBIT?key offset value:設(shè)置key在第offset處的bit值(只能是0或1)
GETBIT?key offset:對key所存儲的值氏义,獲取指定offset位置的bit位(結(jié)果是0或1)
BITCOUNT?key:計算key所存儲的值锄列,被設(shè)置為1的bit位數(shù)量
上面提到集合統(tǒng)計UV的例子,如果是大數(shù)據(jù)量的統(tǒng)計惯悠,會占用很大內(nèi)存空間邻邮,如一個上億用戶量的網(wǎng)站,消耗的內(nèi)存也很恐怖克婶。bitmap也同樣可以實現(xiàn)UV統(tǒng)計:當(dāng)有用戶活躍時筒严,只需設(shè)置該用戶所在bit位為1丹泉,而計算UV數(shù)就是統(tǒng)計所有bit位為1的數(shù)量。比如用戶10086的用戶活躍:SETBIT key 10086 1鸭蛙,獲取某天的DAU:GETBIT key摹恨。
bitmap處理大數(shù)據(jù)的排序、查詢效率非常高而且能節(jié)省極大內(nèi)存空間娶视,最大1億的偏移量大約占用12M內(nèi)存晒哄,但也有幾個顯而易見缺點:1、元素是否能簡單的映射為偏移量肪获,就是待統(tǒng)計的元素是否能映射為Long類型? 2揩晴、消耗的空間取決于最大偏移量,和基數(shù)無關(guān)贪磺。
HyperLogLog
不像SET和Bitmaps是精確統(tǒng)計的硫兰,HyperLogLog(HLL)是一個概率數(shù)據(jù)結(jié)構(gòu),用于估計一個集合內(nèi)的基數(shù)(元素個數(shù))寒锚,又叫基數(shù)統(tǒng)計劫映。其統(tǒng)計是有誤差的,可能會比實際稍微多一些或者稍微少一些刹前,但會控制在合理的范圍內(nèi)泳赋,如果對誤差是可接受的,HyperLogLog是一個最佳選擇喇喉。假設(shè)是UV計算祖今,每次用戶活躍時,用PFADD添加元素到HLL拣技,隨時用PFCOUNT查看集合的基數(shù)千诬,就可以實時統(tǒng)計UV。因為不會將元素真正添加到HLL膏斤,所以不能判斷一個元素是否在HLL里存在徐绑。
Hashes
? ? 一個Hash類型有多個字段(屬性),很像一個對象莫辨,但Hashes字段數(shù)量是沒有限制的傲茄。一般是把一類數(shù)據(jù)放到一個key里,然后通過字段表示不同含義沮榜。
常用命令:HMGET:一次獲取多個hash字段的值
HINCYBY:增加hash字段的值盘榨,用于計數(shù)
原子操作
redis單個命令都是原子操作,比如INCY蟆融,多客戶端對同一個key進行INCY操作的情況下草巡,不會發(fā)生客戶端1讀取key值1,客戶端2同時讀取key值1振愿,然后客戶端1和客戶端2都對key進行加一操作捷犹,設(shè)置key的值為2弛饭;比如MSET,給多個key賦值萍歉,要么都設(shè)置成功侣颂,要么都設(shè)置失敗,不會存在一部分key設(shè)置成功枪孩,一部分可以設(shè)置失敗的情況
總結(jié)
在大數(shù)據(jù)分析架構(gòu)里憔晒,一般是spark、storm作為計算框架蔑舞,計算后的結(jié)果存到redis拒担。要對redis的數(shù)據(jù)結(jié)構(gòu)有清晰認(rèn)識,理解各自優(yōu)缺點攻询、實用場景从撼,redis價值才能最大化。
本文首發(fā)于公眾號:data之道