07-其他技術(shù)總結(jié) redis學(xué)習(xí)總結(jié)_第1頁(yè)
07-其他技術(shù)總結(jié) redis學(xué)習(xí)總結(jié)_第2頁(yè)
07-其他技術(shù)總結(jié) redis學(xué)習(xí)總結(jié)_第3頁(yè)
07-其他技術(shù)總結(jié) redis學(xué)習(xí)總結(jié)_第4頁(yè)
07-其他技術(shù)總結(jié) redis學(xué)習(xí)總結(jié)_第5頁(yè)
已閱讀5頁(yè),還剩85頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

傳智 博望侯Redis聯(lián)系方式:131 2837 781nosql簡(jiǎn)介隨著互聯(lián)網(wǎng)Web2.0網(wǎng)站的興起,傳統(tǒng)的關(guān)系數(shù)據(jù)庫(kù)在應(yīng)付Web2.0網(wǎng)站,特別是超大規(guī)模和高并發(fā)的SNS類型的Web2.0純動(dòng)態(tài)網(wǎng)站已經(jīng)顯得力不從心,暴露了很多難以克服的問(wèn)題:對(duì)數(shù)據(jù)庫(kù)高并發(fā)讀寫的需求網(wǎng)站要根據(jù)用戶個(gè)性化信息來(lái)實(shí)時(shí)生成動(dòng)態(tài)頁(yè)面和提供動(dòng)態(tài)信息,所以基本上無(wú)法使用動(dòng)態(tài)頁(yè)面靜態(tài)化技術(shù),因此數(shù)據(jù)庫(kù)并發(fā)負(fù)載非常高,往往要達(dá)到每秒上萬(wàn)次讀寫請(qǐng)求。關(guān)系數(shù)據(jù)庫(kù)應(yīng)付上萬(wàn)次SQL查詢還勉強(qiáng)頂?shù)米?,但是?yīng)付上千萬(wàn)次SQL寫數(shù)據(jù)請(qǐng)求,硬盤IO就已經(jīng)無(wú)法承受了。對(duì)海量數(shù)據(jù)的高效率存儲(chǔ)和訪問(wèn)的需求對(duì)于大型的SNS網(wǎng)站,每天用戶產(chǎn)生海量的用戶動(dòng)態(tài),以國(guó)外的Friendfeed為例,一個(gè)月就達(dá)到了2.5億條用戶動(dòng)態(tài),對(duì)于關(guān)系數(shù)據(jù)庫(kù)來(lái)說(shuō),在一張2.5億條記錄的表里面進(jìn)行SQL查詢,效率是極其低下乃至不可忍受的。對(duì)數(shù)據(jù)庫(kù)的高可擴(kuò)展性和高可用性的需求在基于Web的架構(gòu)當(dāng)中,數(shù)據(jù)庫(kù)是最難進(jìn)行橫向擴(kuò)展的,當(dāng)一個(gè)應(yīng)用系統(tǒng)的用戶量和訪問(wèn)量與日俱增的時(shí)候,你的數(shù)據(jù)庫(kù)卻沒(méi)有辦法像Web服務(wù)器和應(yīng)用服務(wù)器那樣簡(jiǎn)單的通過(guò)添加更多的硬件和服務(wù)節(jié)點(diǎn)來(lái)擴(kuò)展性能和負(fù)載能力。對(duì)于很多需要提供7*24小時(shí)不間斷服務(wù)的網(wǎng)站來(lái)說(shuō),對(duì)數(shù)據(jù)庫(kù)系統(tǒng)進(jìn)行升級(jí)和擴(kuò)展是非常痛苦的事情,往往需要停機(jī)維護(hù)和數(shù)據(jù)遷移,為什么數(shù)據(jù)庫(kù)不能通過(guò)不斷的添加服務(wù)器節(jié)點(diǎn)來(lái)實(shí)現(xiàn)擴(kuò)展呢?在上面提到的“三高”的需求面前,關(guān)系數(shù)據(jù)庫(kù)遇到了難以克服的障礙,而對(duì)于Web2.0網(wǎng)站來(lái)說(shuō),關(guān)系數(shù)據(jù)庫(kù)的很多主要特性卻往往無(wú)用武之地,例如:(1)數(shù)據(jù)庫(kù)事務(wù)一致性需求很多Web實(shí)時(shí)系統(tǒng)并不要求嚴(yán)格的數(shù)據(jù)庫(kù)事務(wù),對(duì)讀一致性的要求很低,有些場(chǎng)合對(duì)寫一致性要求也不高。因此數(shù)據(jù)庫(kù)事務(wù)管理成了數(shù)據(jù)庫(kù)高負(fù)載下一個(gè)沉重的負(fù)擔(dān)。(2)數(shù)據(jù)庫(kù)的寫實(shí)時(shí)性和讀實(shí)時(shí)性需求對(duì)關(guān)系數(shù)據(jù)庫(kù)來(lái)說(shuō),插入一條數(shù)據(jù)之后立刻查詢,是肯定可以讀出來(lái)這條數(shù)據(jù)的。并不要求這么高的實(shí)時(shí)性。(3)對(duì)復(fù)雜的SQL查詢,特別是多表關(guān)聯(lián)查詢的需求任何大數(shù)據(jù)量的Web系統(tǒng),都非常忌諱多個(gè)大表的關(guān)聯(lián)查詢,以及復(fù)雜的數(shù)據(jù)分析類型的復(fù)雜SQL報(bào)表查詢,特別是SNS類型的網(wǎng)站,從需求以及產(chǎn)品設(shè)計(jì)角度,就避免了這種情況的產(chǎn)生。往往更多的只是單表的主鍵查詢,以及單表的簡(jiǎn)單條件分頁(yè)查詢,SQL的功能被極大的弱化了。因此,關(guān)系數(shù)據(jù)庫(kù)在這些越來(lái)越多的應(yīng)用場(chǎng)景下顯得不那么合適了,為了解決這類問(wèn)題的非關(guān)系數(shù)據(jù)庫(kù)應(yīng)運(yùn)而生。NoSQL 是非關(guān)系型數(shù)據(jù)存儲(chǔ)的廣義定義。它打破了長(zhǎng)久以來(lái)關(guān)系型數(shù)據(jù)庫(kù)與ACID理論大一統(tǒng)的局面。NoSQL 數(shù)據(jù)存儲(chǔ)不需要固定的表結(jié)構(gòu)(例如以鍵值對(duì)存儲(chǔ),它的結(jié)構(gòu)不固定,每一個(gè)元組可以有不一樣的字段,每個(gè)元組可以根據(jù)需要增加一些自己的鍵值對(duì),這樣就不會(huì)局限于固定的結(jié)構(gòu),可以減少一些時(shí)間和空間的開銷),通常也不存在連接操作。NoSQL無(wú)與倫比的特點(diǎn)在大數(shù)據(jù)存取上具備關(guān)系型數(shù)據(jù)庫(kù)無(wú)法比擬的性能優(yōu)勢(shì),例如:易擴(kuò)展NoSQL數(shù)據(jù)庫(kù)種類繁多,但是一個(gè)共同的特點(diǎn)都是去掉關(guān)系數(shù)據(jù)庫(kù)的關(guān)系型特性。數(shù)據(jù)之間無(wú)關(guān)系,這樣就非常容易擴(kuò)展。也無(wú)形之間,在架構(gòu)的層面上帶來(lái)了可擴(kuò)展的能力。大數(shù)據(jù)量,高性能NoSQL數(shù)據(jù)庫(kù)都具有非常高的讀寫性能,尤其在大數(shù)據(jù)量下,同樣表現(xiàn)優(yōu)秀。這得益于它的無(wú)關(guān)系性,數(shù)據(jù)庫(kù)的結(jié)構(gòu)簡(jiǎn)單。靈活的數(shù)據(jù)模型NoSQL無(wú)需事先為要存儲(chǔ)的數(shù)據(jù)建立字段,隨時(shí)可以存儲(chǔ)自定義的數(shù)據(jù)格式。而在關(guān)系數(shù)據(jù)庫(kù)里,增刪字段是一件非常麻煩的事情。如果是非常大數(shù)據(jù)量的表,增加字段簡(jiǎn)直就是一個(gè)噩夢(mèng)。這點(diǎn)在大數(shù)據(jù)量的Web2.0時(shí)代尤其明顯。高可用NoSQL在不太影響性能的情況,就可以方便的實(shí)現(xiàn)高可用的架構(gòu)。比如Cassandra,HBase模型,通過(guò)復(fù)制模型也能實(shí)現(xiàn)高可用。綜上所述,NoSQL的非關(guān)系特性使其成為了后Web2.0時(shí)代的寵兒,助力大型Web2.0網(wǎng)站的再次起飛,是一項(xiàng)全新的數(shù)據(jù)庫(kù)革命性運(yùn)動(dòng)。Redis脫穎而出隨著應(yīng)用對(duì)高性能需求的增加,NoSQL逐漸在各大名企的系統(tǒng)架構(gòu)中生根發(fā)芽。時(shí)至今日,涌現(xiàn)出的NoSQL產(chǎn)品已經(jīng)有很多種了,例如Membase、MongoDB、Apache Cassandra、CouchDB等。不過(guò),在國(guó)內(nèi)外互聯(lián)網(wǎng)巨頭例如社交巨頭新浪微博、傳媒巨頭Viacom及圖片分享領(lǐng)域佼佼者Pinterest等名企都不約而同地采用了Redis作為其NoSQL數(shù)據(jù)庫(kù)的選擇,到底R(shí)edis是何方神圣呢?能讓如此多的名企為它而癡狂。按照官方的說(shuō)法,Redis是一個(gè)開源的,使用C語(yǔ)言編寫,面向“鍵/值”(Key/Value)對(duì)類型數(shù)據(jù)的分布式NoSQL數(shù)據(jù)庫(kù)系統(tǒng),特點(diǎn)是高性能,持久存儲(chǔ),適應(yīng)高并發(fā)的應(yīng)用場(chǎng)景。因此,可以說(shuō)Redis純粹為應(yīng)用而產(chǎn)生,它是一個(gè)高性能的key-value數(shù)據(jù)庫(kù),并且還提供了多種語(yǔ)言的API(包括我們的大C#)。那么,也許我們會(huì)問(wèn):到底性能如何呢?以下是官方的bench-mark數(shù)據(jù):測(cè)試完成了50個(gè)并發(fā)執(zhí)行100000個(gè)請(qǐng)求。設(shè)置和獲取的值是一個(gè)256字節(jié)字符串。Linux box是運(yùn)行Linux 2.6,這是X3320 Xeon 2.5 ghz。文本執(zhí)行使用loopback接口()。結(jié)果:讀的速度是110000次/s,寫的速度是81000次/s。(當(dāng)然不同的服務(wù)器配置性能也有所不同)。和Memcached類似,Redis支持存儲(chǔ)的value類型相對(duì)更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set -有序集合)和hash(哈希類型)。這些數(shù)據(jù)類型都支持push/pop、add/remove及取交集并集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎(chǔ)上,Redis支持各種不同方式的排序。與Memcached一樣,為了保證效率,數(shù)據(jù)都是緩存在內(nèi)存中。區(qū)別的是Redis會(huì)周期性的把更新的數(shù)據(jù)寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎(chǔ)上實(shí)現(xiàn)了master-slave(主從)同步(數(shù)據(jù)可以從主服務(wù)器向任意數(shù)量的從服務(wù)器上同步,從服務(wù)器可以是關(guān)聯(lián)其他從服務(wù)器的主服務(wù)器。)。因此,Redis的出現(xiàn),很大程度補(bǔ)償了Memcached這類key/value存儲(chǔ)的不足,在部分場(chǎng)合可以對(duì)關(guān)系數(shù)據(jù)庫(kù)起到很好的補(bǔ)充作用。Redis是是什么redis是一個(gè)開源的、使用C語(yǔ)言編寫的、支持網(wǎng)絡(luò)交互的、可基于內(nèi)存也可持久化的Key-Value數(shù)據(jù)庫(kù)。redis的官網(wǎng)地址,非常好記,是redis.io。(特意查了一下,域名后綴io屬于國(guó)家域名,是british Indian Ocean territory,即英屬印度洋領(lǐng)地)目前,Vmware在資助著redis項(xiàng)目的開發(fā)和維護(hù)。【redis的作者何許人也】開門見山,先看照片:是不是出乎了你的意料,嗯,高手總會(huì)有些地方與眾不同的。這位便是redis的作者,他叫Salvatore Sanfilippo,來(lái)自意大利的西西里島,現(xiàn)在居住在卡塔尼亞。目前供職于Pivotal公司。他使用的網(wǎng)名是antirez,如果你有興趣,可以去他的博客逛逛,地址是,當(dāng)然也可以去follow他的github,地址是/antirez?!菊l(shuí)在使用redis】Blizzard、digg、stackoverflow、github、flickr Redis安裝導(dǎo)入安裝包編譯(make)從redis.io下載最新版redis-X.Y.Z.tar.gz后解壓,然后進(jìn)入redis-X.Y.Z文件夾后直接make即可,安裝非常簡(jiǎn)單。make成功后會(huì)在src文件夾下產(chǎn)生一些二進(jìn)制可執(zhí)行文件,包括redis-server、redis-cli等等:$ find . -type f -executable./redis-benchmark /用于進(jìn)行redis性能測(cè)試的工具./redis-check-dump /用于修復(fù)出問(wèn)題的dump.rdb文件./redis-cli /redis的客戶端./redis-server /redis的服務(wù)端./redis-check-aof /用于修復(fù)出問(wèn)題的AOF文件./redis-sentinel /用于集群管理安裝(make install)把編譯好的文件安裝到指定目錄前端啟動(dòng)直接運(yùn)行bin/redis-server將以前端模式啟動(dòng),前端模式啟動(dòng)的缺點(diǎn)是ssh命令窗口關(guān)閉則redis-server程序結(jié)束,不推薦使用此方法。如下圖:后端啟動(dòng)修改redis.conf配置文件, daemonize yes 以后端模式啟動(dòng)。執(zhí)行如下命令啟動(dòng)redis:cd /usr/local/redis./bin/redis-server ./redis.confredis默認(rèn)使用6379端口也可更改redis.conf文件,修改端口號(hào):使用redis客戶端內(nèi)置客戶端使用redis客戶端,必須先啟動(dòng)redis服務(wù)端。/這樣來(lái)啟動(dòng)redis客戶端了$ ./redis-cli/用set指令來(lái)設(shè)置key、value:6379 set name roc OK/來(lái)獲取name的值:6379 get name roc/通過(guò)客戶端來(lái)關(guān)閉redis服務(wù)端:6379 shutdown :6379圖形化界面Redis的數(shù)據(jù)結(jié)構(gòu)redis是一種高級(jí)的key:value存儲(chǔ)系統(tǒng),其中value支持五種數(shù)據(jù)類型:1.字符串(strings)2.字符串列表(lists)3.字符串集合(sets)4.有序字符串集合(sorted sets)5.哈希(hashes)而關(guān)于key,有幾個(gè)點(diǎn)要提醒大家:1.key不要太長(zhǎng),盡量不要超過(guò)1024字節(jié),這不僅消耗內(nèi)存,而且會(huì)降低查找的效率;2.key也不要太短,太短的話,key的可讀性會(huì)降低;3.在一個(gè)項(xiàng)目中,key最好使用統(tǒng)一的命名模式,例如user:10000:passwd。Redis數(shù)據(jù)結(jié)構(gòu)之Strings命令列表命令原型時(shí)間復(fù)雜度命令描述返回值A(chǔ)PPENDkeyvalueO(1)如果該Key已經(jīng)存在,APPEND命令將參數(shù)Value的數(shù)據(jù)追加到已存在Value的末尾。如果該Key不存在,APPEND命令將會(huì)創(chuàng)建一個(gè)新的Key/Value。追加后Value的長(zhǎng)度。DECRkeyO(1)將指定Key的Value原子性的遞減1。如果該Key不存在,其初始值為0,在decr之后其值為-1。如果Value的值不能轉(zhuǎn)換為整型值,如Hello,該操作將執(zhí)行失敗并返回相應(yīng)的錯(cuò)誤信息。注意:該操作的取值范圍是64位有符號(hào)整型。遞減后的Value值。INCRkeyO(1)將指定Key的Value原子性的遞增1。如果該Key不存在,其初始值為0,在incr之后其值為1。如果Value的值不能轉(zhuǎn)換為整型值,如Hello,該操作將執(zhí)行失敗并返回相應(yīng)的錯(cuò)誤信息。注意:該操作的取值范圍是64位有符號(hào)整型。遞增后的Value值。DECRBYkey decrement O(1)將指定Key的Value原子性的減少decrement。如果該Key不存在,其初始值為0,在decrby之后其值為-decrement。如果Value的值不能轉(zhuǎn)換為整型值,如Hello,該操作將執(zhí)行失敗并返回相應(yīng)的錯(cuò)誤信息。注意:該操作的取值范圍是64位有符號(hào)整型。減少后的Value值。INCRBYkey incrementO(1)將指定Key的Value原子性的增加increment。如果該Key不存在,其初始值為0,在incrby之后其值為increment。如果Value的值不能轉(zhuǎn)換為整型值,如Hello,該操作將執(zhí)行失敗并返回相應(yīng)的錯(cuò)誤信息。注意:該操作的取值范圍是64位有符號(hào)整型。增加后的Value值。GETkeyO(1)獲取指定Key的Value。如果與該Key關(guān)聯(lián)的Value不是string類型,Redis將返回錯(cuò)誤信息,因?yàn)镚ET命令只能用于獲取string Value。與該Key相關(guān)的Value,如果該Key不存在,返回nil。SETkey valueO(1)設(shè)定該Key持有指定的字符串Value,如果該Key已經(jīng)存在,則覆蓋其原有值??偸欠祷豋K。GETSETkey valueO(1)原子性的設(shè)置該Key為指定的Value,同時(shí)返回該Key的原有值。和GET命令一樣,該命令也只能處理string Value,否則Redis將給出相關(guān)的錯(cuò)誤信息。返回該Key的原有值,如果該Key之前并不存在,則返回nil。STRLENkeyO(1)返回指定Key的字符值長(zhǎng)度,如果Value不是string類型,Redis將執(zhí)行失敗并給出相關(guān)的錯(cuò)誤信息。返回指定Key的Value字符長(zhǎng)度,如果該Key不存在,返回0。SETEXkey seconds valueO(1)原子性完成兩個(gè)操作,一是設(shè)置該Key的值為指定字符串,同時(shí)設(shè)置該Key在Redis服務(wù)器中的存活時(shí)間(秒數(shù))。該命令主要應(yīng)用于Redis被當(dāng)做Cache服務(wù)器使用時(shí)。SETNXkey valueO(1)如果指定的Key不存在,則設(shè)定該Key持有指定字符串Value,此時(shí)其效果等價(jià)于SET命令。相反,如果該Key已經(jīng)存在,該命令將不做任何操作并返回。1表示設(shè)置成功,否則0。SETRANGEkey offset valueO(1)替換指定Key的部分字符串值。從offset開始,替換的長(zhǎng)度為該命令第三個(gè)參數(shù)value的字符串長(zhǎng)度,其中如果offset的值大于該Key的原有值Value的字符串長(zhǎng)度,Redis將會(huì)在Value的后面補(bǔ)齊(offset - strlen(value)數(shù)量的0x00,之后再追加新值。如果該鍵不存在,該命令會(huì)將其原值的長(zhǎng)度假設(shè)為0,并在其后添補(bǔ)offset個(gè)0x00后再追加新值。鑒于字符串Value的最大長(zhǎng)度為512M,因此offset的最大值為536870911。最后需要注意的是,如果該命令在執(zhí)行時(shí)致使指定Key的原有值長(zhǎng)度增加,這將會(huì)導(dǎo)致Redis重新分配足夠的內(nèi)存以容納替換后的全部字符串,因此就會(huì)帶來(lái)一定的性能折損。修改后的字符串Value長(zhǎng)度。GETRANGEkey start endO(1)如果截取的字符串長(zhǎng)度很短,我們可以該命令的時(shí)間復(fù)雜度視為O(1),否則就是O(N),這里N表示截取的子字符串長(zhǎng)度。該命令在截取子字符串時(shí),將以閉區(qū)間的方式同時(shí)包含start(0表示第一個(gè)字符)和end所在的字符,如果end值超過(guò)Value的字符長(zhǎng)度,該命令將只是截取從start開始之后所有的字符數(shù)據(jù)。子字符串SETBITkey offset valueO(1)設(shè)置在指定Offset上BIT的值,該值只能為1或0,在設(shè)定后該命令返回該Offset上原有的BIT值。如果指定Key不存在,該命令將創(chuàng)建一個(gè)新值,并在指定的Offset上設(shè)定參數(shù)中的BIT值。如果Offset大于Value的字符長(zhǎng)度,Redis將拉長(zhǎng)Value值并在指定Offset上設(shè)置參數(shù)中的BIT值,中間添加的BIT值為0。最后需要說(shuō)明的是Offset值必須大于0。在指定Offset上的BIT原有值。GETBITkey offsetO(1)返回在指定Offset上BIT的值,0或1。如果Offset超過(guò)string value的長(zhǎng)度,該命令將返回0,所以對(duì)于空字符串始終返回0。在指定Offset上的BIT值。MGETkey key .O(N)N表示獲取Key的數(shù)量。返回所有指定Keys的Values,如果其中某個(gè)Key不存在,或者其值不為string類型,該Key的Value將返回nil。返回一組指定Keys的Values的列表。MSETkey value key value .O(N)N表示指定Key的數(shù)量。該命令原子性的完成參數(shù)中所有key/value的設(shè)置操作,其具體行為可以看成是多次迭代執(zhí)行SET命令。該命令不會(huì)失敗,始終返回OK。 MSETNXkey value key value .O(N)N表示指定Key的數(shù)量。該命令原子性的完成參數(shù)中所有key/value的設(shè)置操作,其具體行為可以看成是多次迭代執(zhí)行SETNX命令。然而這里需要明確說(shuō)明的是,如果在這一批Keys中有任意一個(gè)Key已經(jīng)存在了,那么該操作將全部回滾,即所有的修改都不會(huì)生效。1表示所有Keys都設(shè)置成功,0則表示沒(méi)有任何Key被修改。實(shí)例有人說(shuō),如果只使用redis中的字符串類型,且不使用redis的持久化功能,那么,redis就和memcache非常非常的像了。這說(shuō)明strings類型是一個(gè)很基礎(chǔ)的數(shù)據(jù)類型,也是任何存儲(chǔ)系統(tǒng)都必備的數(shù)據(jù)類型。我們來(lái)看一個(gè)最簡(jiǎn)單的例子:代碼如下:set mystr hello world! /設(shè)置字符串類型get mystr /讀取字符串類型 字符串類型的用法就是這么簡(jiǎn)單,因?yàn)槭嵌M(jìn)制安全的,所以你完全可以把一個(gè)圖片文件的內(nèi)容作為字符串來(lái)存儲(chǔ)。另外,我們還可以通過(guò)字符串類型進(jìn)行數(shù)值操作:代碼如下::6379 set mynum 2 OK :6379 get mynum 2 :6379 incr mynum (integer) 3 :6379 get mynum 3看,在遇到數(shù)值操作時(shí),redis會(huì)將字符串類型轉(zhuǎn)換成數(shù)值。由于INCR等指令本身就具有原子操作的特性,所以我們完全可以利用redis的INCR、INCRBY、DECR、DECRBY等指令來(lái)實(shí)現(xiàn)原子計(jì)數(shù)的效果,假如,在某種場(chǎng)景下有3個(gè)客戶端同時(shí)讀取了mynum的值(值為2),然后對(duì)其同時(shí)進(jìn)行了加1的操作,那么,最后mynum的值一定是5。不少網(wǎng)站都利用redis的這個(gè)特性來(lái)實(shí)現(xiàn)業(yè)務(wù)上的統(tǒng)計(jì)計(jì)數(shù)需求。我們還可以進(jìn)行刪除:可以發(fā)現(xiàn),刪除后獲取為nullRedis數(shù)據(jù)結(jié)構(gòu)之hashHash存儲(chǔ)結(jié)構(gòu)Hash是一個(gè)string 類型的field和value的映射表。Hash特別適合存儲(chǔ)對(duì)象,相對(duì)于將對(duì)象的每個(gè)字段存成單個(gè)string 類型。一個(gè)對(duì)象存儲(chǔ)在Hash類型中會(huì)占用更少的內(nèi)存,并且可以更方便的存取整個(gè)對(duì)象。我們簡(jiǎn)單舉個(gè)實(shí)例來(lái)描述下Hash的應(yīng)用場(chǎng)景,比如我們要存儲(chǔ)一個(gè)用戶信息對(duì)象數(shù)據(jù),包含以下信息:用戶ID為查找的key,存儲(chǔ)的value用戶對(duì)象包含姓名,年齡,生日等信息,如果用普通的key/value結(jié)構(gòu)來(lái)存儲(chǔ),主要有以下2種存儲(chǔ)方式:第一種方式將用戶ID作為查找key,把其他信息封裝成一個(gè)對(duì)象以序列化的方式存儲(chǔ),這種方式的缺點(diǎn)是,增加了序列化/反序列化的開銷,并且在需要修改其中一項(xiàng)信息時(shí),需要把整個(gè)對(duì)象取回,并且修改操作需要對(duì)并發(fā)進(jìn)行保護(hù),引入CAS等復(fù)雜問(wèn)題。第二種方法是這個(gè)用戶信息對(duì)象有多少成員就存成多少個(gè)key-value對(duì)兒,用用戶ID+對(duì)應(yīng)屬性的名稱作為唯一標(biāo)識(shí)來(lái)取得對(duì)應(yīng)屬性的值,雖然省去了序列化開銷和并發(fā)問(wèn)題,但是用戶ID為重復(fù)存儲(chǔ),如果存在大量這樣的數(shù)據(jù),內(nèi)存浪費(fèi)還是非??捎^的。因此,基于以上兩種方式的缺陷,Redis提供的Hash很好的解決了這個(gè)問(wèn)題,Redis的Hash實(shí)際是內(nèi)部存儲(chǔ)的Value為一個(gè)HashMap,并提供了直接存取這個(gè)Map成員的接口,如下圖:也就是說(shuō),Key仍然是用戶ID, value是一個(gè)Map,這個(gè)Map的key是成員的屬性名,value是屬性值,這樣對(duì)數(shù)據(jù)的修改和存取都可以直接通過(guò)其內(nèi)部Map的Key(Redis里稱內(nèi)部Map的key為field), 也就是通過(guò)key(用戶ID) + field(屬性標(biāo)簽) 就可以操作對(duì)應(yīng)屬性數(shù)據(jù)了,既不需要重復(fù)存儲(chǔ)數(shù)據(jù),也不會(huì)帶來(lái)序列化和并發(fā)修改控制的問(wèn)題,也就很好的解決了問(wèn)題命令列表命令原型時(shí)間復(fù)雜度命令描述返回值HSETkey field valueO(1)為指定的Key設(shè)定Field/Value對(duì),如果Key不存在,該命令將創(chuàng)建新Key以參數(shù)中的Field/Value對(duì),如果參數(shù)中的Field在該Key中已經(jīng)存在,則用新值覆蓋其原有值。1表示新的Field被設(shè)置了新值,0表示Field已經(jīng)存在,用新值覆蓋原有值。HGETkey fieldO(1)返回指定Key中指定Field的關(guān)聯(lián)值。返回參數(shù)中Field的關(guān)聯(lián)值,如果參數(shù)中的Key或Field不存,返回nil。HEXISTSkey fieldO(1)判斷指定Key中的指定Field是否存在。1表示存在,0表示參數(shù)中的Field或Key不存在。HLENkeyO(1)獲取該Key所包含的Field的數(shù)量。返回Key包含的Field數(shù)量,如果Key不存在,返回0。HDELkey field field .O(N)時(shí)間復(fù)雜度中的N表示參數(shù)中待刪除的字段數(shù)量。從指定Key的Hashes Value中刪除參數(shù)中指定的多個(gè)字段,如果不存在的字段將被忽略。如果Key不存在,則將其視為空Hashes,并返回0.實(shí)際刪除的Field數(shù)量。HSETNXkey field valueO(1)只有當(dāng)參數(shù)中的Key或Field不存在的情況下,為指定的Key設(shè)定Field/Value對(duì),否則該命令不會(huì)進(jìn)行任何操作。1表示新的Field被設(shè)置了新值,0表示Key或Field已經(jīng)存在,該命令沒(méi)有進(jìn)行任何操作。HINCRBYkey field incrementO(1)增加指定Key中指定Field關(guān)聯(lián)的Value的值。如果Key或Field不存在,該命令將會(huì)創(chuàng)建一個(gè)新Key或新Field,并將其關(guān)聯(lián)的Value初始化為0,之后再指定數(shù)字增加的操作。該命令支持的數(shù)字是64位有符號(hào)整型,即increment可以負(fù)數(shù)。返回運(yùn)算后的值。HGETALLkeyO(N)時(shí)間復(fù)雜度中的N表示Key包含的Field數(shù)量。獲取該鍵包含的所有Field/Value。其返回格式為一個(gè)Field、一個(gè)Value,并以此類推。Field/Value的列表。HKEYSkeyO(N)時(shí)間復(fù)雜度中的N表示Key包含的Field數(shù)量。返回指定Key的所有Fields名。Field的列表。HVALSkeyO(N)時(shí)間復(fù)雜度中的N表示Key包含的Field數(shù)量。返回指定Key的所有Values名。Value的列表。HMGETkey field field .O(N)時(shí)間復(fù)雜度中的N表示請(qǐng)求的Field數(shù)量。獲取和參數(shù)中指定Fields關(guān)聯(lián)的一組Values。如果請(qǐng)求的Field不存在,其值返回nil。如果Key不存在,該命令將其視為空Hash,因此返回一組nil。返回和請(qǐng)求Fields關(guān)聯(lián)的一組Values,其返回順序等同于Fields的請(qǐng)求順序。HMSETkey field value field value .O(N)時(shí)間復(fù)雜度中的N表示被設(shè)置的Field數(shù)量。逐對(duì)依次設(shè)置參數(shù)中給出的Field/Value對(duì)。如果其中某個(gè)Field已經(jīng)存在,則用新值覆蓋原有值。如果Key不存在,則創(chuàng)建新Key,同時(shí)設(shè)定參數(shù)中的Field/Value。實(shí)例HSET/HGET/HDEL/HEXISTS/HLEN/HSETNX#在Shell命令行啟動(dòng)Redis客戶端程序 /redis-cli #給鍵值為user的鍵設(shè)置字段為username,值為stephen。 redis :6379hset user username stephen (integer) 1 #獲取鍵值為user,字段為username的值。 redis :6379hget user username stephen #user鍵中不存在age字段,因此返回nil。 redis :6379hget user age (nil) #給user關(guān)聯(lián)的Hashes值添加一個(gè)新的字段age,其值為liu。 redis :6379hset user age liu (integer) 1 #獲取user鍵的字段數(shù)量。 redis :6379hlen user (integer) 2 #判斷user鍵中是否存在字段名為username的字段,由于存在,返回值為1。 redis :6379hexists user username (integer) 1 #刪除user鍵中字段名為username的字段,刪除成功返回1。 redis :6379hdel user username (integer) 1 #再次刪除user鍵中字段名為username的字段,由于上一條命令已經(jīng)將其刪除,因?yàn)闆](méi)有刪除,返回0。 redis :6379hdel user username (integer) 0 #判斷user鍵中是否存在username字段,由于上一條命令已經(jīng)將其刪除,因?yàn)榉祷?。 redis :6379hexists user username (integer) 0 #通過(guò)hsetnx命令給user添加新字段username,其值為stephen,因?yàn)樵撟侄我呀?jīng)被刪除,所以該命令添加成功并返回1。 redis :6379hsetnx user username stephen (integer) 1#由于user的username字段已經(jīng)通過(guò)上一條命令添加成功,因?yàn)楸緱l命令不做任何操作后返回0。 redis :6379hsetnx user username stephen(integer) 0HINCRBY #刪除該鍵,便于后面示例的測(cè)試。 redis :6379del user (integer) 1 #準(zhǔn)備測(cè)試數(shù)據(jù),該user的field字段設(shè)定值1。 redis :6379hset user field 5 (integer) 1 #給user的field字段的值加1,返回加后的結(jié)果。 redis :6379hincrby user field 1 (integer) 6 #給user的field字段的值加-1,返回加后的結(jié)果。 redis :6379hincrby user field -1 (integer) 5 #給user的field字段的值加-10,返回加后的結(jié)果。 redis :6379hincrby user field -10 (integer) -5HGETALL/HKEYS/HVALS/HMGET/HMSET #刪除該鍵,便于后面示例測(cè)試。 redis :6379del user (integer) 1 #為該鍵user,一次性設(shè)置多個(gè)字段,分別是username = hello, age = world。 redis :6379hmset user username hello age world OK #獲取user鍵的多個(gè)字段,其中field3并不存在,因?yàn)樵诜祷亟Y(jié)果中與該字段對(duì)應(yīng)的值為nil。 redis :6379hmget user username age field3 1) hello 2) world 3) (nil) #返回user鍵的所有字段及其值,從結(jié)果中可以看出,他們是逐對(duì)列出的。 redis :6379hgetall user 1) username 2) hello 3) age 4) world #僅獲取user鍵中所有字段的名字。 redis :6379hkeys user 1) username 2) age #僅獲取user鍵中所有字段的值。 redis :6379hvals user 1) hello 2) worldredis數(shù)據(jù)結(jié)構(gòu)之listsArrayList與LinkedList的區(qū)別ArrayList使用數(shù)組方式存儲(chǔ)數(shù)據(jù),所以根據(jù)索引查詢數(shù)據(jù)速度快,而新增或者刪除元素時(shí)需要設(shè)計(jì)到位移操作,所以比較慢。 LinkedList使用雙向鏈接方式存儲(chǔ)數(shù)據(jù),每個(gè)元素都記錄前后元素的指針,所以插入、刪除數(shù)據(jù)時(shí)只是更改前后元素的指針指向即可,速度非常快,然后通過(guò)下標(biāo)查詢?cè)貢r(shí)需要從頭開始索引,所以比較慢,但是如果查詢前幾個(gè)元素或后幾個(gè)元素速度比較快。Redis之lists簡(jiǎn)介redis的另一個(gè)重要的數(shù)據(jù)結(jié)構(gòu)叫做lists,翻譯成中文叫做“列表”。首先要明確一點(diǎn),redis中的lists在底層實(shí)現(xiàn)上并不是數(shù)組,而是鏈表,也就是說(shuō)對(duì)于一個(gè)具有上百萬(wàn)個(gè)元素的lists來(lái)說(shuō),在頭部和尾部插入一個(gè)新元素,其時(shí)間復(fù)雜度是常數(shù)級(jí)別的,比如用LPUSH在10個(gè)元素的lists頭部插入新元素,和在上千萬(wàn)元素的lists頭部插入新元素的速度應(yīng)該是相同的。雖然lists有這樣的優(yōu)勢(shì),但同樣有其弊端,那就是,鏈表型lists的元素定位會(huì)比較慢,而數(shù)組型lists的元素定位就會(huì)快得多。lists的常用操作包括LPUSH、RPUSH、LRANGE等。我們可以用LPUSH在lists的左側(cè)插入一個(gè)新元素,用RPUSH在lists的右側(cè)插入一個(gè)新元素,用LRANGE命令從lists中指定一個(gè)范命令列表命令原型時(shí)間復(fù)雜度命令描述返回值LPUSHkey value value .O(1)在指定Key所關(guān)聯(lián)的List Value的頭部插入?yún)?shù)中給出的所有Values。如果該Key不存在,該命令將在插入之前創(chuàng)建一個(gè)與該Key關(guān)聯(lián)的空鏈表,之后再將數(shù)據(jù)從鏈表的頭部插入。如果該鍵的Value不是鏈表類型,該命令將返回相關(guān)的錯(cuò)誤信息。插入后鏈表中元素的數(shù)量。LPUSHXkey valueO(1)僅有當(dāng)參數(shù)中指定的Key存在時(shí),該命令才會(huì)在其所關(guān)聯(lián)的List Value的頭部插入?yún)?shù)中給出的Value,否則將不會(huì)有任何操作發(fā)生。插入后鏈表中元素的數(shù)量。LRANGEkey start stopO(S+N)時(shí)間復(fù)雜度中的S為start參數(shù)表示的偏移量,N表示元素的數(shù)量。該命令的參數(shù)start和end都是0-based。即0表示鏈表頭部(leftmost)的第一個(gè)元素。其中start的值也可以為負(fù)值,-1將表示鏈表中的最后一個(gè)元素,即尾部元素,-2表示倒數(shù)第二個(gè)并以此類推。該命令在獲取元素時(shí),start和end位置上的元素也會(huì)被取出。如果start的值大于鏈表中元素的數(shù)量,空鏈表將會(huì)被返回。如果end的值大于元素的數(shù)量,該命令則獲取從start(包括start)開始,鏈表中剩余的所有元素。返回指定范圍內(nèi)元素的列表。LPOPkeyO(1)返回并彈出指定Key關(guān)聯(lián)的鏈表中的第一個(gè)元素,即頭部元素,。如果該Key不存,返回nil。鏈表頭部的元素。LLENkeyO(1)返回指定Key關(guān)聯(lián)的鏈表中元素的數(shù)量,如果該Key不存在,則返回0。如果與該Key關(guān)聯(lián)的Value的類型不是鏈表,則返回相關(guān)的錯(cuò)誤信息。鏈表中元素的數(shù)量。LREMkey count valueO(N)時(shí)間復(fù)雜度中N表示鏈表中元素的數(shù)量。在指定Key關(guān)聯(lián)的鏈表中,刪除前count個(gè)值等于value的元素。如果count大于0,從頭向尾遍歷并刪除,如果count小于0,則從尾向頭遍歷并刪除。如果count等于0,則刪除鏈表中所有等于value的元素。如果指定的Key不存在,則直接返回0。返回被刪除的元素?cái)?shù)量。LSETkey index valueO(N)時(shí)間復(fù)雜度中N表示鏈表中元素的數(shù)量。但是設(shè)定頭部或尾部的元素時(shí),其時(shí)間復(fù)雜度為O(1)。設(shè)定鏈表中指定位置的值為新值,其中0表示第一個(gè)元素,即頭部元素,-1表示尾部元素。如果索引值Index超出了鏈表中元素的數(shù)量范圍,該命令將返回相關(guān)的錯(cuò)誤信息。LINDEXkey indexO(N)時(shí)間復(fù)雜度中N表示在找到該元素時(shí)需要遍歷的元素?cái)?shù)量。對(duì)于頭部或尾部元素,其時(shí)間復(fù)雜度為O(1)。該命令將返回鏈表中指定位置(index)的元素,index是0-based,表示頭部元素,如果index為-1,表示尾部元素。如果與該Key關(guān)聯(lián)的不是鏈表,該命令將返回相關(guān)的錯(cuò)誤信息。返回請(qǐng)求的元素,如果index超出范圍,則返回nil。LTRIMkey start stopO(N)N表示被刪除的元素?cái)?shù)量。該命令將僅保留指定范圍內(nèi)的元素,從而保證鏈接中的元素?cái)?shù)量相對(duì)恒定。start和stop參數(shù)都是0-based,0表示頭部元素。和其他命令一樣,start和stop也可以為負(fù)值,-1表示尾部元素。如果start大于鏈表的尾部,或start大于stop,該命令不錯(cuò)報(bào)錯(cuò),而是返回一個(gè)空的鏈表,與此同時(shí)該Key也將被刪除。如果stop大于元素的數(shù)量,則保留從start開始剩余的所有元素。LINSERTkey BEFORE|AFTER pivot valueO(N)時(shí)間復(fù)雜度中N表示在找到該元素pivot之前需要遍歷的元素?cái)?shù)量。這樣意味著如果pivot位于鏈表的頭部或尾部時(shí),該命令的時(shí)間復(fù)雜度為O(1)。該命令的功能是在pivot元素的前面或后面插入?yún)?shù)中的元素value。如果Key不存在,該命令將不執(zhí)行任何操作。如果與Key關(guān)聯(lián)的Value類型不是鏈表,相關(guān)的錯(cuò)誤信息將被返回。成功插入后鏈表中元素的數(shù)量,如果沒(méi)有找到pivot,返回-1,如果key不存在,返回0。RPUSHkey value value .O(1)在指定Key所關(guān)聯(lián)的List Value的尾部插入?yún)?shù)中給出的所有Values。如果該Key不存在,該命令將在插入之前創(chuàng)建一個(gè)與該Key關(guān)聯(lián)的空鏈表,之后再將數(shù)據(jù)從鏈表的尾部插入。如果該鍵的Value不是鏈表類型,該命令將返回相關(guān)的錯(cuò)誤信息。插入后鏈表中元素的數(shù)量。RPUSHXkey valueO(1)僅有當(dāng)參數(shù)中指定的Key存在時(shí),該命令才會(huì)在其所關(guān)聯(lián)的List Value的尾部插入?yún)?shù)中給出的Value,否則將不會(huì)有任何操作發(fā)生。插入后鏈表中元素的數(shù)量。RPOPkeyO(1)返回并彈出指定Key關(guān)聯(lián)的鏈表中的最后一個(gè)元素,即尾部元素,。如果該Key不存,返回nil。鏈表尾部的元素。RPOPLPUSHsource destinationO(1)原子性的從與source鍵關(guān)聯(lián)的鏈表尾部彈出一個(gè)元素,同時(shí)再將彈出的元素插入到與destination鍵關(guān)聯(lián)的鏈表的頭部。如果source鍵不存在,該命令將返回nil,同時(shí)不再做任何其它的操作了。如果source和destination是同一個(gè)鍵,則相當(dāng)于原子性的將其關(guān)聯(lián)鏈表中的尾部元素移到該鏈表的頭部。返回彈出和插入的元素。實(shí)例LPUSH/LPUSHX/LRANGE/redis-cli#在Shell提示符下啟動(dòng)redis客戶端工具。 redis :6379del mykey (integer) 1#mykey鍵并不存在,該命令會(huì)創(chuàng)建該鍵及與其關(guān)聯(lián)的List,之后在將參數(shù)中的values從左到右依次插入。 redis :6379lpush mykey a b c d (integer) 4#取從位置0開始到位置2結(jié)束的3個(gè)元素。 redis :6379lrange mykey 0 2 1) d 2) c 3) b #取鏈表中的全部元素,其中0表示第一個(gè)元素,-1表示最后一個(gè)元素。 redis :6379lrange mykey 0 -1 1) d 2) c 3) b 4) a #mykey2鍵此時(shí)并不存在,因此該命令將不會(huì)進(jìn)行任何操作,其返回值為0。 redis :6379lpushx mykey2 e (integer) 0 #可以看到mykey2沒(méi)有關(guān)聯(lián)任何List Value。 redis :6379lrange mykey2 0 -1 (empty list or set) #mykey鍵此時(shí)已經(jīng)存在,所以該命令插入成功,并返回鏈表中當(dāng)前元素的數(shù)量。 redis :6379lpushx mykey e (integer) 5 #獲取該鍵的List Value的頭部元素。 redis :6379lrange mykey 0 0 1) eLPOP/LLENredis :6379lpush mykey a b c d (integer) 4 redis :6379lpop mykey d redis :6379lpop mykey c#在執(zhí)行l(wèi)pop命令兩次后,鏈表頭部的兩個(gè)元素已經(jīng)被彈出,此時(shí)鏈表中元素的數(shù)量是2 redis :6379llen mykey (integer) 2LREM/LSET/LINDEX/LTRIM#為后面的示例準(zhǔn)備測(cè)試數(shù)據(jù)。 redis :6379lpush mykey a b c d a c (integer) 6#從頭部(left)向尾部(right)變量鏈表,刪除2個(gè)值等于a的元素,返回值為實(shí)際刪除的數(shù)量。 redis :6379lrem mykey 2 a (integer) 2 #看出刪除后鏈表中的全部元素。 redis :6379lrange mykey 0 -1 1) c 2) d 3) c 4) b #獲取索引值為1(頭部的第二個(gè)元素)的元素值。 redis :6379lindex mykey 1 d #將索引值為1(頭部的第二個(gè)元素)的元素值設(shè)置為新值e。 redis :6379lset mykey 1 e OK #查看是否設(shè)置成功。 redis :6379lindex mykey 1 e #索引值6超過(guò)了鏈表中元素的數(shù)量,該命令返回nil。 redis :6379lindex mykey 6 (nil) #設(shè)置的索引值6超過(guò)了鏈表中元素的數(shù)量,設(shè)置失敗,該命令返回錯(cuò)誤信息。 redis :6379lset mykey 6 hh (error) ERR index out of range #僅保留索引值0到2之間的3個(gè)元素,注意第0個(gè)和第2個(gè)元素均被保留。 redis :6379ltrim mykey 0 2 OK #查看trim后的結(jié)果。 redis 127.0

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論