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