亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

[譯]Redis大冒險

2024-07-21 02:51:44
字體:
來源:轉載
供稿:網友

一篇對使用Redis在NoSQL的世界中冒險之旅的總結。

The legs of our journey

像每次出發一樣,先對我們這次的旅程路線做個介紹:

Redis? What is it?Available datatypesWhere are my tables?A simple use caseBack home

探索之一:Redis? What is it?

簡而言之,Redis是一種強大的key-value數據庫,之所以強大有兩點:響應速度快(所以數據內存存儲,只在必要時寫入磁盤),特性豐富(支持多種數據類型,以及各類型上的復雜操作)。

事實上,Redis的一個重要特性就是它并非通常意義上的數據庫,雖然稱之為數據庫是因為它可以為你存儲和維護數據,但它并不像關系數據庫那樣提供任何的SQL方言。不過不用擔心,Redis并不是吞噬數據的黑洞,它只是不支持SQL及相關功能,但卻提供了穩健的協議用于與之交互。

在Redis中,沒有數據表的概念,也無須關心select,join,view等操作或功能,同時也不提供類似于int或varchar的數據字段。你面對的將是相對原始的數據集合及數據類型。

探索之二:Available datatypes

下面我們深入看下這個奇怪的數據庫是如何工作的。如上所見,Redis是基于key-value范式存儲數據,所以先來重點看下"key"的概念。

key本質上就是簡單的字符串,諸如"username"、"passWord"等。在定義key時,除了不能使用空格,你可以隨意的使用普通的字符、數字等,像".",":","_"等在定義key時都能正常使用,所以像"user_name", "user:123:age", "user:123:username"都是不錯的key的定義方式。

不像RDBMS中的字段名稱,這里的key是Redis中的重要組成部分,所以我們必須在處理key時多加小心。在下面的講述中,Redis并沒有table的概念,所以像"SELECT username from users WHERE user_id=123;"這種簡單任務都只能換種方式實現,為了達到這種目的,在Redis上,一種方式是通過key "user:123:username"來獲取結果value。如你所見,key的定義中攜帶了神秘信息(像user ids)。在Redis中,key的重要性可見一斑。(其他key-value數據庫中key的地位也是如此。)

現在你應該對key有了清楚的了解,下面帶你進入可用的數據類型的神奇世界。

Strings

String是Redis中最基本的數據類型,它就是普通的二進制安全的字符串,支持最大數據長度為1Gb??梢酝ㄟ^SET命令給一個key設置String類型的數據,并可通過GET命令根據key取得結果。如果你想存儲數字信息,像計數器,你也可以把它存儲到String數據中,并可使用INCR和DECR對之做自增和自減操作。

Lists

List是string數據的集合,其中各數據項按插入順序排列。你可以把list當作一個鎖鏈(chain),所以可以在鎖鏈最左邊(鏈頭)或最右邊(鏈尾)添加一個新的鏈結(link);當然也可以加在鎖鏈中間,但卻要打斷某個鏈結。

可能通過LPUSH和RPUSH命令給list添加數據(L:left, R:right),通過LPOP或RPOP命令彈出元素(同時刪除該元素),也可以通過LRANGE獲取指定范圍的元素(僅返回數據,不會刪除任何元素)。另外也可通過LSET在指定位置添加元素,但通常這種操作比簡單的LPUSH或RPUSH要慢很多。

Hashes

Hashes以簡潔的方式存儲關系更為緊密的數據。Hashes為每個存儲的key實現一個內置的key-value對來存儲數據,例如對于"user"這個key,它的值可以是多個字段以及與每個字符相應的值對組成數據集。如果你熟悉像ruby或javascript等編程語言,這里的hashes與那些語言中的hash概念大同小異。

Sets

Sets和它在數學上的同名概念"集合"意義相同,是包含不重復元素的集合。在Redis中,這些對象變成了Redis里的String類型。正如你想,sets與lists不同的地方在于:sets中的元素是無序的,并且不能重復,你不能在sets中放進兩個相同的數據。  

可以通過SADD往set中添加數據,SREM刪除數據,或者通過SPOP返回并刪除此數據。此外還可以通過SUNION, SINTER, SDIFF命令分別實現集合上的"并集", "交集", "差集"操作。

Ordered sets

Ordered sets與sets類似,不同地方在于Ordered set中的每個元素都有一個權重,用于與其他元素比較并排序。

當然ordered set與普通sets具有類似的操作,ZADD和ZREM分別是添加和刪除元素。Ordered set也有自己獨有的操作:ZINCR和ZSCORE,前則用于為元素的權重+1,后則則返回元素的權重值。

探索之三:Where are my tables?

使用Redis與我們之前使用的SQL數據表完全不同,沒有語言支持你在服務器上查詢數據,這里僅有一些命令幫你操作數據庫中的keys值。Redis中的命令是數據類型敏感型的,也就是說你不能在list上執行set命令,否則你將得到一個執行錯誤的提示??梢酝ㄟ^redis-cli或其他你使用的編程語言中的接口給Redis server發送命令。在下面的示例中,我們只強調命令本身,而不關注你通過哪種方式提交給Redis server。

想像一下,一個簡單的SQL數據庫表,像一些應用中會用到的保存用戶數據的表:

id username password name surname1  user1  pass1   Bob  Smith2  user2  pass2   Mario Rossi

存儲數據

假如我們想把上面的數據存儲到Redis中,你會如何在Redis中設計數據庫方案呢?也許以應用的視覺來看會更直觀一些。使用SQL,我們在SELECT中通過指定用戶id來獲得一個用戶信息,換句話說就是需要有用于區分不同數據實體的方式,所以我們可以通過一個唯一的標識來標識和獲取用戶信息。所以如果在redis的key中加入用戶的id信息,那么我們的查詢需求就解決了,在redis中,數據被存儲成如下形式:

Key        Valueuser:1:username  user1user:1:password  pass1user:1:name    Bobuser:1:surname   Smithuser:2:username  user2user:2:password  pass2user:2:name      Mariouser:2:surname   Rossi

那么,給出任一個用戶id,我們就可以通過key user:id:username,user:id:password,user:id:name,user:id:surname的形式讀出用戶信息。

用戶登錄

上面的存儲形式也能用于用戶登錄,但需要一種方式能根據username來查詢用戶的id。也就是說我們還需要在username和id之間建立聯系。這可以通過添加另外一個redis key"user:username:id"來實現。

key      valueuser:user1:id  1user:user2:id  2

現在如果Mario Rossi想要登錄進來,我們可以通過key"user:user2:id"先查出username,進而獲得用戶的所有信息。

主鍵

在Redis中如何保證id值的唯一性呢。在SQL中,可以通過"id int PRimary key auto_increment"定義自增主鍵來實現,現在我們也需要一種類似的方式為每個用戶生成一個不同的id。根據前面可用的數據類型中提到的數字數據,Redis中的方案是這樣的:創建一個key"user:next_id",并把它作為計數器,每當要添加新用戶時,就對key"user:next_id"執行INCR命令。

SELECT * FROM users;

下一個面臨的問題是查詢用戶列表。也許你認為我們上面的數據存儲已經足以查詢出用戶列表:可以先獲得"user:next_id"的當前值counter,然后通過一步或多步遍歷0到counter獲得用戶數據。但如果某個用戶從系統中刪除(下面會講到刪除操作),而我們會遍歷0到counter中的所有id,這時就會有些id查詢不到任何數據。

盡管這通常不是問題,但我們不想在不存在的用戶數據上浪費時間,所以需要創建另外一個key"user:list",其value為list或set類型,用于存儲每一個新增的用戶id,并在必要的時候從"user:list"中刪除該id。我更傾向于使用list,因為它可能通過LRANGE命令實現分頁功能。

刪除用戶

還有一個要面臨的問題是"數據完整性",看看我們在刪除用戶時會發生什么吧。我們需要刪除每一個對此用戶的引用,也就是說,需要刪除下面所有的key"user:id:*","user:username:id",以及"user:list"中的用戶id。

探索之四:A Simple use case

為了學習致用,我們嘗試設計一個虛擬圖書館,并能根據主題對圖書分組。下面的例子比上面的用戶表會稍微復雜些,但你將學會如何在Redis中處理關聯關系。

在應用中,我們需要收集圖書,并存儲他們的title,author(s), topic(s), pages, price, ISBN和description。顯然有些圖書的作者不止一個,并且它也許會涵蓋不同的主題(例如一本書可以是編程主題,也可以是描述的ruby編程)。另外一個作者可能寫了很多本書,而一個主題必然會包含很多本書。可以看出,這里出現了作者和圖書、主題和圖書的多對多關系。

SQL場景

首先,我們嘗試使用SQL數據表為此種場景建數據模型,以便于我們更直觀的在Redis領域中模擬:

Books

id title         pages price   isbn     description1 Programming Ruby   829   $26  0974514055 ruby programming language2 Erlang Programming 496   $42   0596518188 an introduction to erlang

Authors

id name    surname1  Dave    Thomas2  Chad    Fowler3  Andy    Hunt4  Francesco  Cesarini5  Simon    Thompson

Topics

id  name      description1   programming Books about programming2   ruby      Books about ruby3   erlang      Books about erlang

Books-Authors

book_id author_id1     11     21     32     42     5

Books-Topics

book_id topic_id1     11     22     12     3

Redis場景

前面已經介紹了如何在Redis中存儲數據,所以這里理解Books,Authors和Topics這三張表應該不成問題。但當面對Books-Authors和Book-Topics這種表之間的多對多關聯時,問題變得復雜起來。下面以Topic為例來看如何解決Book與Topic之間的關聯,一旦對這個關系清楚了,Book與Author之間的關系也就迎刃而解了。

對于每本book,我們需要知道它屬于哪些topics;同樣對于每個topic,也要處理它包含的每本book。換句話說,對每本book,需要一個存儲它所關聯的topic的id列表,對于每個topic,同樣需要一個存儲它關聯的book的id列表。這正是set大展身手的地方。我們將創建兩個sets:"book:id:topic"和"topic:id:books",前者保存book的topics'id列表,后者存儲topic的books'id列表。以前面SQL場景中的數據為例,圖書"Programming Erlang"(books表中的id為2),將有一個key為"book:2:topics",value為set類型且數據為(1,3)的數據信息;而主題"programming"則會有一個key為"topic:1:books",值為(1,2)的數據集。

經過分析,就得出了Redis場景下的數據模型:

Authors

Strings- author:id- author:id:name- author:id:surname

Sets- author:id:books

Lists- authorlist

Books

Strings- book:id- book:id:title- book:id:pages- book:id:price- book:id:isbn- book:id:description

Sets- books:id:authors - books:id:topics

Lists- book:list

Topics

String- topic:id- topic:id:name- topic:id:description

Sets- topic:id:books

Lists- topic:list

可以看出,在SQL中的多對多關聯,在Redis中可以通過兩個set來實現。你會發現這種實現相當有用,它給我們提供了一種可以自由獲得其他信息的能力:可以通過對所有感興趣的"topic:id:books"集合中交集操作,從而獲得隸屬于多個主題的圖書。例如對集合"topic:1:books"(programming主題)和"topic:2:books"(ruby主題)做交集,會得到只有一個元素(1)的集合,從而獲得id=1的圖書:programming Ruby。

對于這種實現,你必須特別關注對數據的刪除操作。因為topics里有對books的引用,同樣books里有對topics的引用,那刪除如何操作?以刪除books中的數據為例,首先想到的是要刪除每個key為"book:id:*"的數據,但執行此操作前需要先遍歷topics中的所有key為"topic:id:books"的集合,并從中刪除待刪除圖書的id,當然也要從books中key為"book:list"的列表中刪除此id。如果想刪除一個topic,操作也很類似:從topics中刪除所有key為"topic:id:*"信息之前,需要先遍歷books中的key為"books:id:topics"的topic id集,并從中刪除待刪除topic的id,同時從"topic:list"列表中也刪除此id。同樣的操作對于authors一樣適用。

探索之五:Back home

對于Redis的探索到一段落,現在回頭看看我們的旅行包里收獲了哪些精彩。我們學習了Redis中的數據類型及操作命令,還有一些其他有趣的東西。 是不是還有幾段記憶深刻的故事呢:

通過對String數據執行INCR命令解決唯一自增主鍵問題通過含義豐富的key:"user:username:id"處理用戶登錄場景通過set實現數據間的多對多關聯

到此為止,Redis之旅已經結束,希望未給你帶來不快。最后送上一副良濟:having fun coding free software! 

 

譯者注:本文是翻譯而來,個人感覺是通過與SQL做對比,來強調Redis的不同,進而讓讀者能跳出SQL的枷鎖,以實現對Redis的理解。

在真實場景中,Redis未必如文中描述的方式使用,我自己對Redis的使用場景也在學習中,歡迎指導。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
伊人久久综合97精品| 亚洲精品按摩视频| 国产日韩中文字幕| 色悠悠国产精品| 欧美国产日韩视频| 九色精品免费永久在线| 日本免费一区二区三区视频观看| 日韩在线欧美在线| 久久不射热爱视频精品| 亚洲自拍高清视频网站| 国产精品扒开腿做爽爽爽视频| 欧美日韩国产成人在线| 清纯唯美亚洲综合| 91久久久在线| 最近2019中文免费高清视频观看www99| 国产专区欧美专区| 色一区av在线| 欧美激情一区二区三区高清视频| 九九九热精品免费视频观看网站| 在线观看国产精品日韩av| 日韩久久精品成人| 欧美亚洲国产成人精品| 不卡av电影在线观看| 欧美资源在线观看| 色妞色视频一区二区三区四区| 国产精品欧美日韩| 伊人久久大香线蕉av一区二区| 日韩在线欧美在线国产在线| 亚洲人精品午夜在线观看| 中文字幕亚洲综合| 26uuu另类亚洲欧美日本老年| 日本欧美黄网站| 欧美日韩裸体免费视频| 国产97在线亚洲| 国产97免费视| 久久人人爽人人爽人人片av高请| 国产在线观看精品一区二区三区| 欧美大全免费观看电视剧大泉洋| 国产一区二区香蕉| 成人综合网网址| 国产精品久久久久久久久久免费| 亚洲第一视频在线观看| 亚洲已满18点击进入在线看片| 91极品女神在线| 欧美中文在线免费| 国产亚洲人成网站在线观看| 日韩av在线影视| 久久在精品线影院精品国产| 国产精品一区二区三区久久久| 91夜夜未满十八勿入爽爽影院| 久久精品电影网站| 欧美精品videofree1080p| 精品国产成人av| 成人免费淫片视频软件| 国产精品女主播视频| 久久久久久久久久国产| 欧美日韩高清在线观看| 亚洲第一偷拍网| 欧美孕妇毛茸茸xxxx| 欧美在线免费视频| 亚洲第一免费播放区| 欧美激情视频在线免费观看 欧美视频免费一| 久久久国产精品亚洲一区| 亚洲精品98久久久久久中文字幕| 国产欧美精品va在线观看| 国产一区二区三区精品久久久| 国产一区二区三区在线视频| 国产亚洲美女精品久久久| 欧美亚洲国产视频小说| 日韩中文字幕不卡视频| 成人女保姆的销魂服务| 秋霞成人午夜鲁丝一区二区三区| 俺去了亚洲欧美日韩| 成人黄色免费片| 亚洲毛片在线免费观看| 成人午夜激情免费视频| 久久久亚洲天堂| 国产91精品视频在线观看| 亚洲美女性生活视频| 在线视频国产日韩| 国产精品网红福利| 日韩经典一区二区三区| 中文字幕亚洲一区二区三区五十路| 国产精品自拍视频| 久久天天躁狠狠躁夜夜av| 欧美一级片免费在线| 日本久久精品视频| 日韩美女在线观看| 欧美制服第一页| 久久久久久有精品国产| 欧美成年人网站| 国产精品久久久久久久久久久久久| 国产精品美女www| 992tv成人免费视频| 精品久久久久久国产| 精品视频在线导航| 日韩中文字幕亚洲| 久久久久国产精品一区| www.国产精品一二区| 91精品视频免费看| 91免费高清视频| 欧美日韩另类在线| 成人午夜激情网| 国产精品福利观看| 国产精品96久久久久久又黄又硬| 日韩小视频网址| 日本久久精品视频| 国产精品第8页| 亚洲精品久久久久久久久久久久久| 欧美理论电影在线播放| 成人综合网网址| 国产精品久久久久久久午夜| www国产亚洲精品久久网站| 高潮白浆女日韩av免费看| 91中文精品字幕在线视频| 亚洲www视频| 91精品在线影院| 精品视频一区在线视频| 欧美成人精品不卡视频在线观看| 国产视频综合在线| 综合久久五月天| 91在线视频一区| 日韩精品免费综合视频在线播放| 亚洲精品福利在线| 欧美在线精品免播放器视频| 久久综合国产精品台湾中文娱乐网| 日韩高清不卡av| 精品中文字幕在线观看| 亚洲少妇中文在线| 欧美壮男野外gaytube| 懂色av中文一区二区三区天美| 亚洲free性xxxx护士白浆| 国产欧美日韩精品在线观看| 欧美视频不卡中文| 欧美日韩国产精品| 国产成人精品综合久久久| 欧美综合在线观看| 欧美一区二区色| 国模极品一区二区三区| 久久久久成人精品| 亚洲一区精品电影| 欧美另类在线观看| 亚洲欧美日韩直播| 国产亚洲精品久久久| 亚洲自拍偷拍一区| 国产精品久久久久国产a级| 亚洲天堂第一页| 俺去了亚洲欧美日韩| 日韩电影大片中文字幕| 成人免费大片黄在线播放| 欧美大片在线看| 精品国产欧美一区二区五十路| 中文字幕日韩视频| 久久精品视频中文字幕| 国产不卡视频在线| 亚洲午夜精品久久久久久久久久久久| 狠狠色噜噜狠狠狠狠97| 国产成人av在线播放| 欧美老女人xx| 亚洲精品97久久| 亚洲在线观看视频网站| 日韩中文字幕av| 午夜精品国产精品大乳美女| 日韩欧美精品在线观看|