1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      Redis數(shù)據(jù)庫常見的鍵值設(shè)計有哪些

      這篇文章將為大家詳細講解有關(guān)redis數(shù)據(jù)庫常見的鍵值設(shè)計有哪些,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

      成都創(chuàng)新互聯(lián)公司科技有限公司專業(yè)互聯(lián)網(wǎng)基礎(chǔ)服務(wù)商,為您提供成都服務(wù)器托管高防服務(wù)器租用,成都IDC機房托管,成都主機托管等互聯(lián)網(wǎng)服務(wù)。

      用戶登錄系統(tǒng)

      記錄用戶登錄信息的一個系統(tǒng),我們簡化業(yè)務(wù)后只留下一張表。

      關(guān)系型數(shù)據(jù)庫的設(shè)計

      MySQL>select*fromlogin;

      +---------+----------------+-------------+---------------------+

      |user_id|name|login_times|last_login_time|

      +---------+----------------+-------------+---------------------+

      |1|kenthompson|5|2011-01-0100:00:00|

      |2|dennisritchie|1|2011-02-0100:00:00|

      |3|JoeArmstrong|2|2011-03-0100:00:00|

      +---------+----------------+-------------+---------------------+

      user_id表的主鍵,name表示用戶名,login_times表示該用戶的登錄次數(shù),每次用戶登錄后,login_times會自增,而last_login_time更新為當前時間。

      REDIS的設(shè)計

      關(guān)系型數(shù)據(jù)轉(zhuǎn)化為KV數(shù)據(jù)庫,我的方法如下:

      key表名:主鍵值:列名

      value列值

      一般使用冒號做分割符,這是不成文的規(guī)矩。比如在php-adminforredis系統(tǒng)里,就是默認以冒號分割,于是user:1user:2等key會分成一組。于是以上的關(guān)系數(shù)據(jù)轉(zhuǎn)化成kv數(shù)據(jù)后記錄如下:

      Setlogin:1:login_times5

      Setlogin:2:login_times1

      Setlogin:3:login_times2

      Setlogin:1:last_login_time2011-1-1

      Setlogin:2:last_login_time2011-2-1

      Setlogin:3:last_login_time2011-3-1

      setlogin:1:name”kenthompson“

      setlogin:2:name“dennisritchie”

      setlogin:3:name”JoeArmstrong“

      這樣在已知主鍵的情況下,通過get、set就可以獲得或者修改用戶的登錄次數(shù)和最后登錄時間和姓名。

      一般用戶是無法知道自己的id的,只知道自己的用戶名,所以還必須有一個從name到id的映射關(guān)系,這里的設(shè)計與上面的有所不同。

      set"login:kenthompson:id"1

      set"login:dennisritchie:id"2

      set"login:JoeArmstrong:id"3

      這樣每次用戶登錄的時候業(yè)務(wù)邏輯如下(python版),r是redis對象,name是已經(jīng)獲知的用戶名。

      #獲得用戶的id

      uid=r.get("login:%s:id"%name)

      #自增用戶的登錄次數(shù)

      ret=r.incr("login:%s:login_times"%uid)

      #更新該用戶的最后登錄時間

      ret=r.set("login:%s:last_login_time"%uid,datetime.datetime.now())

      如果需求僅僅是已知id,更新或者獲取某個用戶的最后登錄時間,登錄次數(shù),關(guān)系型和kv數(shù)據(jù)庫無啥區(qū)別。一個通過btreepk,一個通過hash,效果都很好。

      假設(shè)有如下需求,查找最近登錄的N個用戶。開發(fā)人員看看,還是比較簡單的,一個sql搞定。

      select*fromloginorderbylast_login_timedesclimitN

      DBA了解需求后,考慮到以后表如果比較大,所以在last_login_time上建個索引。執(zhí)行計劃從索引leafblock的最右邊開始訪問N條記錄,再回表N次,效果很好。

      有哪些常見Redis數(shù)據(jù)庫鍵值的設(shè)計

      過了兩天,又來一個需求,需要知道登錄次數(shù)最多的人是誰。同樣的關(guān)系型如何處理?DEV說簡單

      select*fromloginorderbylogin_timesdesclimitN

      DBA一看,又要在login_time上建立一個索引。有沒有覺得有點問題呢,表上每個字段上都有素引。

      關(guān)系型數(shù)據(jù)庫的數(shù)據(jù)存儲的的不靈活是問題的源頭,數(shù)據(jù)僅有一種儲存方法,那就是按行排列的堆表。統(tǒng)一的數(shù)據(jù)結(jié)構(gòu)意味著你必須使用索引來改變sql的訪問路徑來快速訪問某個列的,而訪問路徑的增加又意味著你必須使用統(tǒng)計信息來輔助,于是一大堆的問題就出現(xiàn)了。

      沒有索引,沒有統(tǒng)計計劃,沒有執(zhí)行計劃,這就是kv數(shù)據(jù)庫。

      redis里如何滿足以上的需求呢?對于求最新的N條數(shù)據(jù)的需求,鏈表的后進后出的特點非常適合。我們在上面的登錄代碼之后添加一段代碼,維護一個登錄的鏈表,控制他的長度,使得里面永遠保存的是最近的N個登錄用戶。

      #把當前登錄人添加到鏈表里

      ret=r.lpush("login:last_login_times",uid)

      #保持鏈表只有N位

      ret=redis.ltrim("login:last_login_times",0,N-1)

      這樣需要獲得最新登錄人的id,如下的代碼即可

      last_login_list=r.lrange("login:last_login_times",0,N-1)

      另外,求登錄次數(shù)最多的人,對于排序,積分榜這類需求,sortedset非常的適合,我們把用戶和登錄次數(shù)統(tǒng)一存儲在一個sortedset里。

      zaddlogin:login_times51

      zaddlogin:login_times12

      zaddlogin:login_times23

      這樣假如某個用戶登錄,額外維護一個sortedset,代碼如此

      #對該用戶的登錄次數(shù)自增1

      ret=r.zincrby("login:login_times",1,uid)

      那么如何獲得登錄次數(shù)最多的用戶呢,逆序排列取的排名第N的用戶即可

      ret=r.zrevrange("login:login_times",0,N-1)

      可以看出,DEV需要添加2行代碼,而DBA不需要考慮索引什么的。

      TAG系統(tǒng)

      tag在互聯(lián)網(wǎng)應(yīng)用里尤其多見,如果以傳統(tǒng)的關(guān)系型數(shù)據(jù)庫來設(shè)計有點不倫不類。我們以查找書的例子來看看redis在這方面的優(yōu)勢。

      關(guān)系型數(shù)據(jù)庫的設(shè)計

      兩張表,一張book的明細,一張tag表,表示每本的tag,一本書存在多個tag。

      mysql>select*frombook;

      +------+-------------------------------+----------------+

      |id|name|author|

      +------+-------------------------------+----------------+

      |1|TheRubyProgrammingLanguage|MarkPilgrim|

      |1|Rubyonrail|DavidFlanagan|

      |1|ProgrammingErlang|JoeArmstrong|

      +------+-------------------------------+----------------+

      mysql>select*fromtag;

      +---------+---------+

      |tagname|book_id|

      +---------+---------+

      |ruby|1|

      |ruby|2|

      |web|2|

      |erlang|3|

      +---------+---------+

      假如有如此需求,查找即是ruby又是web方面的書籍,如果以關(guān)系型數(shù)據(jù)庫會怎么處理?

      selectb.name,b.authorfromtagt1,tagt2,bookb

      wheret1.tagname='web'andt2.tagname='ruby'andt1.book_id=t2.book_idandb.id=t1.book_id

      tag表自關(guān)聯(lián)2次再與book關(guān)聯(lián),這個sql還是比較復(fù)雜的,如果要求即ruby,但不是web方面的書籍呢?

      關(guān)系型數(shù)據(jù)其實并不太適合這些集合操作。

      REDIS的設(shè)計

      首先book的數(shù)據(jù)肯定要存儲的,和上面一樣。

      setbook:1:name”TheRubyProgrammingLanguage”

      Setbook:2:name”Rubyonrail”

      Setbook:3:name”ProgrammingErlang”

      setbook:1:author”MarkPilgrim”

      Setbook:2:author”DavidFlanagan”

      Setbook:3:author”JoeArmstrong”

      tag表我們使用集合來存儲數(shù)據(jù),因為集合擅長求交集、并集

      saddtag:ruby1

      saddtag:ruby2

      saddtag:web2

      saddtag:erlang3

      那么,即屬于ruby又屬于web的書?

      inter_list=redis.sinter("tag.web","tag:ruby")

      即屬于ruby,但不屬于web的書?

      inter_list=redis.sdiff("tag.ruby","tag:web")

      屬于ruby和屬于web的書的合集?

      inter_list=redis.sunion("tag.ruby","tag:web")

      簡單到不行阿。

      從以上2個例子可以看出在某些場景里,關(guān)系型數(shù)據(jù)庫是不太適合的,你可能能夠設(shè)計出滿足需求的系統(tǒng),但總是感覺的怪怪的,有種生搬硬套的感覺。

      尤其登錄系統(tǒng)這個例子,頻繁的為業(yè)務(wù)建立索引。放在一個復(fù)雜的系統(tǒng)里,ddl(創(chuàng)建索引)有可能改變執(zhí)行計劃。導致其它的sql采用不同的執(zhí)行計劃,業(yè)務(wù)復(fù)雜的老系統(tǒng),這個問題是很難預(yù)估的,sql千奇百怪。要求DBA對這個系統(tǒng)里所有的sql都了解,這點太難了。這個問題在oracle里尤其嚴重,每個DBA估計都碰到過。對于MySQL這類系統(tǒng),ddl又不方便(雖然現(xiàn)在有onlineddl的方法)。碰到大表,DBA凌晨爬起來在業(yè)務(wù)低峰期操作,這事我沒少干過。而這種需求放到redis里就很好處理,DBA僅僅對容量進行預(yù)估即可。

      關(guān)于“Redis數(shù)據(jù)庫常見的鍵值設(shè)計有哪些”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。


      分享名稱:Redis數(shù)據(jù)庫常見的鍵值設(shè)計有哪些
      網(wǎng)頁URL:http://www.ef60e0e.cn/article/jhcpgg.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        盘锦市| 瓮安县| 张家川| 四子王旗| 扶余县| 黎川县| 浙江省| 荥经县| 马关县| 黔西| 绥化市| 长乐市| 周至县| 繁峙县| 都兰县| 隆尧县| 台南市| 文成县| 涟水县| 邵阳县| 嘉峪关市| 大洼县| 泾川县| 容城县| 元朗区| 安多县| 大英县| 巩义市| 建始县| 洞口县| 房产| 紫金县| 基隆市| 乌兰察布市| 吉安县| 剑阁县| 屏南县| 安溪县| 洪雅县| 靖远县| 泾源县|