摘要:原理與架構(gòu)使用了單線程架構(gòu)和多路復(fù)用模型來實現(xiàn)高性能的內(nèi)存數(shù)據(jù)庫服務(wù)。為什么單線程還能這么快純內(nèi)存訪問,將所有數(shù)據(jù)放在內(nèi)存中,內(nèi)存的響應(yīng)時長大約為納秒,這是達到每秒萬級別訪問的重要基礎(chǔ)。
歡迎關(guān)注公眾號:【愛編碼】簡介
如果有需要后臺回復(fù)2019贈送1T的學(xué)習(xí)資料哦!!
Redis是一個開源(BSD許可)的內(nèi)存數(shù)據(jù)結(jié)構(gòu)存儲,用作數(shù)據(jù)庫、緩存和消息代理。它支持諸如字符串、散列、列表、集、帶范圍查詢的排序集、位圖、hyperloglog、帶半徑查詢和流的地理空間索引等數(shù)據(jù)結(jié)構(gòu)。
Redis具有內(nèi)置的復(fù)制、Lua腳本、LRU清除、事務(wù)和不同級別的磁盤持久性,并通過Redis Sentinel和Redis集群的自動分區(qū)提供高可用性。
原理與架構(gòu)Redis使用了單線程架構(gòu)和I/O多路復(fù)用模型來實現(xiàn)高性能的內(nèi)存數(shù)據(jù)庫服務(wù)。
單線程模型因為Redis是單線程來處理命令的,所以一條命令從客戶端達到服務(wù)端不會立刻被執(zhí)行。所有命令都會進入一個隊列中,然后逐個被執(zhí)行,因此不會產(chǎn)生并發(fā)問題。
為什么單線程還能這么快1.純內(nèi)存訪問,Redis將所有數(shù)據(jù)放在內(nèi)存中,內(nèi)存的響應(yīng)時長大
約為100納秒,這是Redis達到每秒萬級別訪問的重要基礎(chǔ)。
2.非阻塞I/O,Redis使用epoll作為I/O多路復(fù)用技術(shù)的實現(xiàn),再加上Redis自身的事件處理模型將epoll中的連接、讀寫、關(guān)閉都轉(zhuǎn)換為事件,不在網(wǎng)絡(luò)I/O上浪費過多的時間,如下圖所示
單線程避免了線程切換和競態(tài)產(chǎn)生的消耗。
注:阻塞的操作是會非常影響Redis性能,這個下次再總結(jié)
API使用場景命令語法可以到下面地址查,本節(jié)僅僅說使用場景。
https://www.runoob.com/redis/...
1.緩存功能
Redis作為緩存層,MySQL作為存儲層,絕大部分請求的數(shù)據(jù)都是從Redis中獲取。由于Redis具有支撐高并發(fā)的特性,所以緩存通常能起到加速讀寫和降低后端壓力的作用。
類似下面這樣子的偽代碼
// 從MySQL獲取用戶信息 userInfo = mysql.get(id); // 將userInfo序列化,并存入Redis redis.setex(userRedisKey, 3600, serialize(userInfo)); // 返回結(jié)果 return userInfo
2.計數(shù)
例如使用Redis作為文章點贊數(shù)計數(shù)的基礎(chǔ)組件,用戶每一次點贊,相應(yīng)的點贊數(shù)就會自增1
long incrLikeCounter(long id) { key = "article:like:" + id; return redis.incr(key); }
3.共享Session
使用Redis將用戶的Session進行集中管理,每次用戶更新或者查詢登錄信息都直接從Redis中集中獲取。
4.限速
很多應(yīng)用出于安全的考慮,會在每次進行登錄時,讓用戶輸入手機驗證碼,從而確定是否是用戶本人。但是為了短信接口不被頻繁訪問,會限制用戶每分鐘獲取驗證碼的頻率。
類似如下偽代碼
phoneNum = "138xxxxxxxx"; key = "shortMsg:limit:" + phoneNum; // SET key value EX 60 NX isExists = redis.set(key,1,"EX 60","NX"); if(isExists != null || redis.incr(key) <=5){ // 通過 }else{ // 限速 }哈希
關(guān)系型數(shù)據(jù)表記錄的兩條用戶信息,用戶的屬性作為表的列,每條用戶信息作為行。
相比于使用字符串序列化緩存用戶信息,哈希類型變得更加直觀,并且在更新操作上會更加便捷。可以將每個用戶的id定義為鍵后綴,多對fieldvalue對應(yīng)每個用戶的屬性。
類似如下偽代碼:
UserInfo getUserInfo(long id){ // 用戶id作為key后綴 userRedisKey = "user:info:" + id; // 使用hgetall獲取所有用戶信息映射關(guān)系 userInfoMap = redis.hgetAll(userRedisKey); UserInfo userInfo; if (userInfoMap != null) { // 將映射關(guān)系轉(zhuǎn)換為UserInfo userInfo = transferMapToUserInfo(userInfoMap); } else { // 從MySQL中獲取用戶信息 userInfo = mysql.get(id); // 將userInfo變?yōu)橛成潢P(guān)系使用hmset保存到Redis中 redis.hmset(userRedisKey, transferUserInfoToMap(userInfo)); // 添加過期時間 redis.expire(userRedisKey, 3600); } return userInfo; }列表
列表是一種比較靈活的數(shù)據(jù)結(jié)構(gòu),它可以充當(dāng)棧和隊列。
相關(guān)命令時間復(fù)雜度表:
消息隊列
Redis的lpush+brpop命令組合即可實現(xiàn)阻塞隊列,生產(chǎn)者客戶端使用lrpush從列表左側(cè)插入元素,多個消費者客戶端使用brpop命令阻塞式的“搶”列表尾部的元素,多個客戶端保證了消費的負(fù)載均衡和高可用性。如圖所示:
口訣:
集合lpush+lpop=Stack(棧)
lpush+rpop=Queue(隊列)
lpsh+ltrim=Capped Collection(有限集合)
lpush+brpop=Message Queue(消息隊列)
集合類型比較典型的使用場景是標(biāo)簽(tag)。例如一個用戶可能對娛樂、體育比較感興趣,另一個用戶可能對歷史、新聞比較感興趣,這些興趣點就是標(biāo)簽。
有了這些數(shù)據(jù)就可以得到喜歡同一個標(biāo)簽的人,以及用戶的共同喜好的標(biāo)簽,這些數(shù)據(jù)對于用戶體驗以及增強用戶黏度比較重要。
例如一個電子商務(wù)的網(wǎng)站會對不同標(biāo)簽的用戶做不同類型的推薦,比如對數(shù)碼產(chǎn)品比較感興趣的人,在各個頁面或者通過郵件的形式給他們推薦最新的數(shù)碼產(chǎn)品,通常會為網(wǎng)站帶來更多的利益。
相關(guān)命令時間復(fù)雜度表:
標(biāo)簽實現(xiàn)基本思路
1.給用戶添加標(biāo)簽
sadd user:1:tags tag1 tag2 tag5 sadd user:2:tags tag2 tag3 tag5 ... sadd user:k:tags tag1 tag2 tag4 ...
2.給標(biāo)簽添加用戶
sadd tag1:users user:1 user:3 sadd tag2:users user:1 user:2 user:3 ... sadd tagk:users user:1 user:2 ...
3.使用sinter命令,來計算用戶共同感興趣的標(biāo)簽
sinter user:1:tags user:2:tags
注:1,2步應(yīng)該在同一個事務(wù)(下一篇文章再講)中執(zhí)行,否則會導(dǎo)致數(shù)據(jù)不正確。
更多組合應(yīng)用:
有序集合sadd=Tagging(標(biāo)簽)
spop/srandmember=Random item(生成隨機數(shù),比如抽獎)
sadd+sinter=Social Graph(社交需求)
它保留了集合不能有重復(fù)成員的特性,給每個元素設(shè)置一個分?jǐn)?shù)(score)作為排序的依據(jù)。
場景
排行榜系統(tǒng)
例如視頻網(wǎng)站需要對用戶上傳的視頻做排行榜,榜單的維度可能是多個方面的:按照時間、按照播放數(shù)量、按照獲得的贊數(shù)。
本節(jié)使用贊數(shù)這個維度,記錄每天用戶上傳視頻的排行榜。
主要需要實現(xiàn)以下4個功能
1.添加用戶贊數(shù)
//獲得一個贊。 zadd user:ranking:2016_03_15 mike 3 //第一個贊之后自增。 zincrby user:ranking:2016_03_15 mike 1
2.取消用戶贊數(shù)
zrem user:ranking:2016_03_15 mike
3.展示獲取贊數(shù)最多的十個用戶
zrevrangebyrank user:ranking:2016_03_15 0 9
4.展示用戶信息以及用戶分?jǐn)?shù)
hgetall user:info:tom zscore user:ranking:2016_03_15 mike zrank user:ranking:2016_03_15 mike總結(jié)
Redis還有什么場景,歡迎各位大神指教。
本文所有知識點來自于【Redis開發(fā)與運維(付磊)】,這本書非常值得一讀。
關(guān)注公眾號【愛編碼】回復(fù)付磊即可獲取。
最后如果對 Java、大數(shù)據(jù)感興趣請長按二維碼關(guān)注一波,我會努力帶給你們價值。覺得對你哪怕有一丁點幫助的請幫忙點個贊或者轉(zhuǎn)發(fā)哦。
關(guān)注公眾號【愛編碼】,回復(fù)2019有相關(guān)資料哦。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/18002.html
摘要:原理與架構(gòu)使用了單線程架構(gòu)和多路復(fù)用模型來實現(xiàn)高性能的內(nèi)存數(shù)據(jù)庫服務(wù)。為什么單線程還能這么快純內(nèi)存訪問,將所有數(shù)據(jù)放在內(nèi)存中,內(nèi)存的響應(yīng)時長大約為納秒,這是達到每秒萬級別訪問的重要基礎(chǔ)。 歡迎關(guān)注公眾號:【愛編碼】如果有需要后臺回復(fù)2019贈送1T的學(xué)習(xí)資料哦!! showImg(https://segmentfault.com/img/remote/1460000019020175)...
摘要:前段時間,有個人吐槽自己的同事是上古程序猿,一直堅持反對使用。上古程序猿堅決反對用,我該怎么說服他分布式鎖如果你是一位后端工程師,面試時八成會被問到,特別是大廠,不僅要求能簡單使用,還要深入理解底層原理,具備解決常見問題的能力。 前段時間,有個人吐槽自己的同事是上古程序猿,一直堅持反對使用Redis。那位上古程序猿設(shè)計公司...
摘要:前段時間,有個人吐槽自己的同事是上古程序猿,一直堅持反對使用。那位上古程序猿設(shè)計公司的業(yè)務(wù)系統(tǒng)時候,始終堅持永遠(yuǎn)不要用緩存其他人想用,例如做個接口防重復(fù),一定要用數(shù)據(jù)庫來實現(xiàn),包括定期失效之類的功能。項目中使用,主要考慮性能和并發(fā)。 前段時間,有個人吐槽自己的同事是上古程序猿,一直堅持反對使...
閱讀 2255·2021-11-25 09:43
閱讀 3122·2021-10-14 09:42
閱讀 3484·2021-10-12 10:12
閱讀 1526·2021-09-07 10:17
閱讀 1900·2019-08-30 15:54
閱讀 3181·2019-08-30 15:54
閱讀 1550·2019-08-30 15:53
閱讀 1907·2019-08-29 11:21