中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

老(lao)弟(di)第一(yi)次學(xue) Redis,被(bei)坑慘了(le)!小白可(ke)懂的(de)保姆級 Redis 教程

你(ni)是小阿巴,剛入職的程序員(yuan)。

這天,產品經理找到你(ni):阿(a)巴(ba)阿(a)巴(ba),用戶吐槽咱們網站首頁(ye)加載太慢,快優(you)化!

 

你打開監控一看(kan),好(hao)家伙!每秒有(you)上萬個(ge)用戶在訪問(wen)首頁,每次(ci)都要查詢(xun) MySQL 數據庫(ku)來獲取熱門文章。

雖然你運用畢生所學優化了數(shu)據(ju)庫查(cha)詢(xun),但它還(huan)是扛不住這(zhe)么高(gao)的并發。

你急得滿頭大(da)汗:數據庫快撐不住了,怎么辦啊?

這(zhe)時,你的(de)導師 —— 號稱 “后端之狗(gou)” 的(de)魚(yu)皮(pi)路過(guo),淡定地說了 3 個字:Redis(瑞迪斯)。

你一臉懵:Redis?那是啥?

 

?? 推薦觀看本文對應視頻:

 

第(di)一階段:認(ren)識 Redis

魚皮:Redis 的全稱是 Remote Dictionary Server(遠程字典服務器),是一個 基于內存的 K/V 存儲系統

你:遠程(cheng)?字典?K/V?這些都是什么啊?

 

魚皮:你可(ke)以把 Redis 當成一個數據(ju)庫,服務器(qi)可(ke)以通(tong)過網絡遠程操作它(ta)寫入(ru)和(he)讀取(qu)數據(ju)。K/V 就(jiu)是 Key-Value 鍵值(zhi)對(dui),數據(ju)就(jiu)像字典一樣保存。

 

你(ni)可以通過 Key 快速查詢到對應的(de) Value。而且因(yin)為(wei)數據存(cun)(cun)在內存(cun)(cun)中(zhong),Redis 的(de)讀寫速度有時比 MySQL 快 100 倍!

 

你眼前一(yi)亮:那我趕(gan)緊裝一(yi)個試試!

機智如你,直接打開 下載(zai)了 Redis 服務器(qi),并且成功安裝(zhuang)運行。

 

但是怎么操作 Redis 呢?

魚皮:可以使用官方(fang)提供的命(ming)令行工(gong)具 Redis CLI 連接并操作 Redis。

打(da)開終(zhong)端(duan)輸入(ru)下列(lie)命令(ling):

redis-cli -h 127.0.0.1 -p 6379

 

連上(shang)之后(hou),咱們試(shi)試(shi)最(zui)基礎(chu)的(de)操作,利用 SET 命令保存一個鍵值對:

SET name "xiaoaba"

 

然后通過鍵(jian)讀取到值:

GET name

 

你剛敲完命令,屏幕立(li)刻(ke)返回 "小阿巴"。

 

你大為(wei)震驚:秒回!這也太快了!

 

魚皮:你剛剛保存的值是 Redis 的 String 字符串 類(lei)型,只是(shi)最簡單的(de)一種。

你:還有(you)其他類型?

魚(yu)皮:當然,Redis 能存的(de)東(dong)西可多著呢~ 它有(you) 5 種基(ji)本(ben)數據(ju)結構,適(shi)用(yong)于不(bu)同場景:

1)String 字符串:存簡單的值,比如用戶名、計數器

SET username:1 "魚皮"
GET username:1

 

2)Hash 哈希表:存對象,比如用戶信息 {name: "小阿巴", age: 18}

HSET user:1001 name "小阿巴" age 18
HGET user:1001 name

 

3)List 列(lie)表:存有序數據,比如最新的(de) 10 條(tiao)評(ping)論

LPUSH comments "太棒了!" "學到了"
LRANGE comments -1

 

4)Set 集(ji)合:存(cun)不重復的數據,比如點贊用戶(hu)列(lie)表

SADD post:1:likes user1 user2 user3
SMEMBERS post:1:likes

 

5)SortedSet 有序(xu)(xu)集(ji)合:存需要排(pai)序(xu)(xu)且不重復的數據(ju),比如游戲排(pai)行(xing)榜

ZADD leaderboard 100 "玩家A" 95 "玩家B" 90 "玩家C"
ZRANGE leaderboard -1 WITHSCORES

 

 

你感嘆道:這用法(fa)也太(tai)多了,我(wo)要背這些命令嗎(ma)?

魚皮:千萬別背!用的時候去查 就行。

而且想偷懶的話,推薦你裝個 Redis 官方的可視化工具 ,能像操作(zuo) Excel 一(yi)樣(yang)操作(zuo) Redis,數據一(yi)目了然。

 

你:哇,確實方便多了!但(dan)是我怎么(me)用 Java 代碼(ma)操作 Redis 呢(ni)?

魚皮:主流編程語(yu)言都有操(cao)作(zuo) Redis 的客(ke)戶端 SDK。

 

對于 Java 開發者,可(ke)以(yi)選擇 Jedis、Lettuce、Spring Data Redis 和(he) Redisson,它們封裝(zhuang)了很(hen)多操作 Redis 的方法(fa),幾行(xing)代碼就能搞定。

 

時間充足的話,建議(yi)你(ni)看(kan)看(kan)某馬的 Redis 教程(cheng)來系統學習,我(wo)當年也看(kan)過,講(jiang)的很(hen)好,先把基礎(chu)篇和實戰(zhan)篇看(kan)完就夠了。

你:得咧,我這就看!

 

第(di)二階(jie)段:實戰應用

半個(ge)月后,你已(yi)經看了不(bu)少教程,準備解決熱門(men)文(wen)章查詢(xun)太慢的問題。

 

你實現了經典的緩(huan)存(cun)邏輯:第一次查詢時(shi),先從(cong)(cong) Redis 中查找(zhao),如(ru)果沒有找(zhao)到(dao),再從(cong)(cong) MySQL 數據庫中查詢,然(ran)后將結(jie)果存(cun)入(ru) Redis 中,并設置(zhi)過期時(shi)間。后續相同的查詢就能直接從(cong)(cong) Redis 返回(hui)結(jie)果。

 

示(shi)例(li)代(dai)碼:

public List<ArticlegetHotArticles() {
   // 1. 先從 Redis 查詢
   String cacheKey "hot_articles";
   String cachedData redisTemplate.opsForValue().get(cacheKey);
   if (cachedData != null) {
       // 緩存命中,直接返回
       return JSON.parseArray(cachedData, Article.class);
  }
   // 2. 緩存未命中,查詢數據庫
   List<Articlearticles articleMapper.selectHotArticles();
   // 3. 將結果存入 Redis,設置 10 分鐘過期
   redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(articles), 10, TimeUnit.MINUTES);
   return articles;
}

 

使用 Redis 后,查詢速度從 3 秒縮短(duan)到了 0.3 秒,產品(pin)經理看你的眼神都變(bian)了,你很是得意。

 

魚皮:不(bu)錯,不(bu)過 Redis 的作(zuo)用(yong)可不(bu)僅僅是緩存,你還(huan)能用(yong)它繼續(xu)優化項目么?比(bi)如(ru)之(zhi)前(qian)用(yong)戶反饋的登(deng)錄(lu)態失效(xiao)問題。

你想了想:Redis 的本質是 存儲系統,也就(jiu)是(shi)說,可以(yi)利(li)用 Redis 來(lai)存(cun)儲多個服(fu)務(wu)器(qi)間(jian)需要(yao)共享的數據。公司有 2 臺服(fu)務(wu)器(qi),用戶第一次登錄時,Session 存(cun)在(zai)服(fu)務(wu)器(qi) A 本地;刷新頁面后(hou),請求被分(fen)(fen)配(pei)到(dao)服(fu)務(wu)器(qi) B,就(jiu)找(zhao)不到(dao) Session 了,導致(zhi)丟失登錄態(tai)。那我就(jiu)把需要(yao)共享的 Session 數據存(cun)到(dao) Redis 中(zhong),這樣無論(lun)請求分(fen)(fen)配(pei)到(dao)哪(na)臺服(fu)務(wu)器(qi),都能從(cong) Redis 里拿到(dao) Session。

 

魚皮欣慰地點了點頭:不錯,這就是典型的 分布式 Session 問題。

類似的,分布式(shi)鎖也可(ke)以利用 Redis 實(shi)現(xian),讓多個(ge)服務器都(dou)從 Redis 去(qu)獲取鎖資源,誰(shui)先拿(na)到鎖,誰(shui)就能(neng)操作,其他人排(pai)隊(dui)等待(dai)。

 

你:確實,那(nei) Redis 還(huan)有其他應用場景么?

魚皮:那可太多了,Redis 除了 5 種基本數據結構外,還提供了很多 “高級” 數據結構,專門解決特(te)定場景的問(wen)題。

  • GEO:存地(di)理位置坐標,實現(xian)附近(jin)的(de)人(ren)、附近(jin)的(de)餐廳(ting)功能

  • Bitmap:用(yong) 1 個(ge) bit 表示一個(ge)狀態(tai)(tai),節約(yue)內(nei)存,實現用(yong)戶簽到、在(zai)線狀態(tai)(tai)統計(ji)

  • HyperLogLog:適(shi)用(yong)于大(da)規(gui)模統計(ji) UV(獨立訪(fang)客數),雖然存在誤差,但內存占用(yong)只有 12 KB

  • 布隆(long)過濾器(qi):快速(su)判斷數(shu)(shu)據是(shi)否存在,可(ke)用(yong)來防止無效查詢打到數(shu)(shu)據庫

  • Stream:消(xiao)息(xi)隊列功能,可以實(shi)現異步(bu)(bu)任務,比如用戶下單(dan)后異步(bu)(bu)發送短信通知(zhi)(但更推薦用專(zhuan)業的消(xiao)息(xi)隊列)

 

魚皮:對了,還有更高級的玩法,Redis 支持編寫 Lua 腳本 保證(zheng)多個操作的(de)原子性,確(que)保要么全部成功,要么全部失敗,避免(mian)數據(ju)不(bu)一致(zhi)的(de)問題。

 

你:這些聽(ting)起來好高級,感覺學不完了……

魚皮:想什么(me)呢,肯(ken)定(ding)學不完啊!

Redis 是在持續更新的,去看看 ,你會發現更多數據結構,比如適用于 AI 應用開發的 。不過別(bie)擔心,可以等(deng)實際開發中(zhong)遇到對應場景再學(xue)。

 

Redis 是實戰型技術,光看不練等于白學,一定要多(duo)動手實踐(jian)。

你:好,那我就先給 的更(geng)多查(cha)詢也加(jia)上緩存吧~

 

第三(san)階段:常見問題和解決方案

一(yi)個月(yue)后的(de)某天,凌晨 3 點,你被電(dian)話吵(chao)醒(xing)了。

運維小哥急切地說:阿(a)巴阿(a)巴,網站(zhan)掛了!數據庫查(cha)詢一直超時,你快(kuai)看看!

你很(hen)是疑惑:都用 Redis 緩存了,還能超(chao)時?

 

你趕緊去公司(si)看了下日志,發現原(yuan)來有惡意(yi)用戶在(zai)瘋(feng)狂(kuang)查詢一個不存(cun)在(zai)的文章 ID,每次 Redis 緩存(cun)中都查不到,請求就直接打(da)到了 MySQL 數據庫上!

 

魚皮這時也趕到了公司:這就是經典的 緩存穿透 問題(ti),惡(e)意請求故意查詢(xun)不存(cun)在的數(shu)據,繞過緩存(cun),直接攻擊數(shu)據庫。

 

你汗流(liu)浹(jia)背了:那怎么辦(ban)?

 

魚皮:最簡(jian)單的方法(fa)是,即(ji)使數(shu)據庫查詢結(jie)果為空,仍將這個(ge)空結(jie)果緩存到 Redis 中,并設置一(yi)個(ge)較短的過期時間。后續(xu)相同請求會直接命(ming)中緩存的空值(zhi),避免(mian)訪問數(shu)據庫。

 

你恍然大悟,趕緊寫代碼(ma)補充了緩存(cun)空值的邏(luo)輯。

public Article getArticleById(Long id) {
   String cacheKey "article:" id;
   String cachedData redisTemplate.opsForValue().get(cacheKey);
   if (cachedData != null) {
       // 如果是空值標識,直接返回 null
       if ("__NULL__".equals(cachedData)) {
           return null;
      }
       return JSON.parseObject(cachedData, Article.class);
  }  
   // 查詢數據庫
   Article article articleMapper.selectById(id);
   if (article != null) {
       // 存儲正常數據,10 分鐘過期
       redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(article), 10, TimeUnit.MINUTES);
  } else {
       // 存儲空值標識,2 分鐘過期
       redisTemplate.opsForValue().set(cacheKey, "NULL", 2, TimeUnit.MINUTES);
  }  
   return article;
}

 

魚皮提醒道:緩存穿透只是其中一個問題,實際項目中還會遇到 緩存擊穿緩存雪崩

1)緩存擊穿:熱門數(shu)(shu)(shu)據突(tu)然過期,大量請求(qiu)同時(shi)涌向數(shu)(shu)(shu)據庫(ku)。可以用互斥鎖,讓請求(qiu)排隊一(yi)個一(yi)個來,第一(yi)個請求(qiu)負責查數(shu)(shu)(shu)據庫(ku)并重建緩存,其他請求(qiu)等緩存重建完成后(hou)再查詢。

 

2)緩(huan)存雪崩:大(da)量緩(huan)存同時過(guo)期,數據庫瞬間壓力巨大(da)。解決方法是給過(guo)期時間加上隨機值,避免同時失效。

 

你感慨道:Redis 的坑(keng)還真不少!

魚皮(pi):這就是為(wei)什么要學(xue)習 Redis 的最佳實踐,比(bi)如合理設計緩存(cun)鍵名、設置合適的過(guo)期(qi)時間、選擇(ze)正確的數據結(jie)構(gou)等等。

 

魚皮(pi):不(bu)過這才剛開始呢,你(ni)以(yi)后(hou)還(huan)會遇到緩存和數據(ju)庫的數據(ju)不(bu)一致、查詢 Redis 阻塞、內存爆滿等(deng)問題,都是(shi)需(xu)要學習的,以(yi)后(hou)我再給(gei)你(ni)講吧。

 

你(ni):那如果 Redis 本身也扛(kang)不住高并發怎(zen)么辦(ban)?

魚皮:那就搭建 多級緩存,比如服務器本(ben)地(di)(di)內(nei)存緩存 => Redis 分布式緩存 => 數(shu)據庫,層(ceng)層(ceng)過(guo)濾。用戶請求先(xian)查(cha)本(ben)地(di)(di)緩存,沒(mei)有再查(cha) Redis,還沒(mei)有才查(cha)數(shu)據庫。每一層(ceng)都能攔截一部分請求,大(da)(da)大(da)(da)減少 Redis 的壓(ya)力。

 

還有 緩存預熱,比(bi)如大促活動前,提前把熱門商(shang)品數據(ju)(ju)加(jia)載到(dao) Redis 中,避免活動開始時大量請求同時打到(dao)數據(ju)(ju)庫。

 

第四階段:高級特(te)性和(he)生產部署

用了(le)一段時間 Redis 后,你開(kai)始有點(dian)飄(piao)了(le)。

你對著新來的實習生阿坤炫(xuan)耀:Redis 我(wo)閉著眼睛都能寫!什(shen)么緩(huan)存、分布式鎖(suo)、多級緩(huan)存,我(wo)都搞(gao)定過!

結(jie)果第二天(tian),老板黑著臉(lian)找到你:昨(zuo)晚機房斷(duan)電重啟后,很多用戶反(fan)饋自(zi)己的(de)學習進(jin)度丟失了,怎(zen)么(me)回事?!

你這才意識到問題的嚴重性:Redis 數據存(cun)儲在(zai)內(nei)存(cun),斷(duan)電不就沒了嗎?

 

魚(yu)皮及時(shi)出(chu)現:看(kan)來你對 Redis 的理解還停(ting)留在玩具階段(duan)啊,生產環境的 Redis 可不是這么(me)簡單!我來問你幾個(ge)問題。

第一問:怎么防止數據丟失?

你支(zhi)支(zhi)吾(wu)吾(wu):做…… 做備份(fen)?

沒想到(dao),旁邊的(de)阿坤突然(ran)雞叫起(qi)來:可以(yi)利(li)用 Redis 提供(gong)的(de) 2 種持久化方案(an)!

 

1)RDB 快照:定(ding)期把內存數據完(wan)整保(bao)存到硬盤,像拍照一樣,恢復快但(dan)可能丟失最新數據。

 

2)AOF 日志:把每(mei)個寫操作都記(ji)錄下來(lai),像記(ji)日記(ji),數據更安(an)全但恢復較慢(需(xu)要重(zhong)新執行所有寫操作)。

 

第二問:Redis 服務器掛了怎么辦?

你撓頭(tou):重啟?

魚(yu)皮搖頭:用戶等得起(qi)嗎?

阿坤又雞叫起來:要部署 主從集群,主(zhu)(zhu)節(jie)(jie)點(dian)負責(ze)寫數(shu)據(ju),從節(jie)(jie)點(dian)實時同步主(zhu)(zhu)節(jie)(jie)點(dian)的數(shu)據(ju)。這樣即使主(zhu)(zhu)節(jie)(jie)點(dian)掛了(le),從節(jie)(jie)點(dian)立(li)刻頂(ding)上,用戶毫無感知。

 

第三問:主節點掛了,誰來決定哪個從節點升級?

你無言以對,但是那阿坤竟從容不迫:用 哨兵機制,哨(shao)兵就像監工,可以實時監控 Redis 集群健康狀態。發現主節(jie)點(dian)掛了,自動(dong)(dong)選(xuan)擇一個(ge)從節(jie)點(dian)升(sheng)級為(wei)新(xin)主節(jie)點(dian),實現自動(dong)(dong)故障轉移。

 

第四問:數據量太大,單臺 Redis 存不下怎么辦?

你(ni)眼(yan)前一亮,終于等到(dao)自己會的問題了(le),搶答道:刪(shan)除數據!

 

阿(a)坤(kun)用(yong)看(kan)流浪狗的眼(yan)神看(kan)了你一眼(yan),回答道:首(shou)先 Redis 自身有多種淘汰(tai)策略,會自動(dong)刪除不常用(yong)的數據。

 

還可以搭建 分片集群,把數據按照某種規則分散到多臺 Redis 上,每臺只存一部分。Redis 使用 哈希槽 機制來分配數(shu)(shu)據(ju),既(ji)能存(cun)儲更(geng)多數(shu)(shu)據(ju),又能承受更(geng)高并發。

 

魚皮拍(pai)了拍(pai)阿坤的肩膀:小伙子(zi)年輕(qing)有(you)為(wei)啊!

你羞愧地抬不起頭:我以為自己已經(jing)掌握了 Redis,原(yuan)來(lai)只是學了個皮毛……

 

魚皮:這些都是 Redis 在生產環境必須考慮的問題,大廠的 Redis 集群動輒幾十上百個節點,就是為了保證 高可用、高性能、高可擴展性。小阿巴,你還(huan)要好好跟阿坤學(xue)習啊。

 

第五(wu)階段:深(shen)入底層原理(li)

被魚皮連環(huan)拷問后,你(ni)主動找到阿坤:我(wo)想深入學習 Redis,不(bu)能只(zhi)停留(liu)在會用的(de)層(ceng)面,請(qing)問你(ni)是怎么學習底層(ceng)原理的(de)呀?

阿坤有些驚訝:咦?你不背八股文的么?去 刷刷題就好了(le)呀(ya)!

 

你震驚了:現(xian)在的校招生,竟然(ran)恐怖如斯!

 

魚皮:阿坤你別逗他了,其實我們可以帶著問題學習。比如你知道 Redis 為什么這么快 嗎?

你想了想:因(yin)為數據存(cun)在內存(cun)里?

 

魚皮:這只是表面原因。深層次的原因有很多:

  1. 高效的(de)數據(ju)(ju)結構:Redis 底層使用了動態字(zi)符串(chuan)、跳表、壓縮列表等經過優(you)化的(de)數據(ju)(ju)結構

  2. 單線程模型:避免了多線程的上下文(wen)切換開(kai)銷

  3. IO 多路復(fu)用:一個(ge)(ge)線程就(jiu)能(neng)同時處理成(cheng)千上萬個(ge)(ge)連接

  4. 內存管理:有完(wan)善的(de)內存淘(tao)汰策略(lve),比(bi)如 LRU 算法(fa)

 

你驚(jing)訝:單線程還能這么快?

 

魚皮:對!這(zhe)就(jiu)是 Redis 設計(ji)的(de)巧妙(miao)之處(chu)。從這(zhe)些(xie)問(wen)題(ti)出(chu)發(fa),去閱讀相(xiang)關的(de)文章(zhang),或者直接像阿(a)坤說的(de)刷(shua)一刷(shua) Redis 面試題(ti),就(jiu)能快速學會很多核心知(zhi)識點(dian)。

 

如果想(xiang)系統學習(xi),可(ke)以看(kan)(kan)看(kan)(kan)《Redis 設計與實現》這本(ben)書(shu),講得很透徹;甚至可(ke)以看(kan)(kan)看(kan)(kan) Redis 的開源代碼。

 

要記住,學習(xi)底(di)層原理不是為了(le)炫(xuan)技,而是為了(le)更好地使用 Redis,遇到問題時能(neng)夠快(kuai)速定位(wei)和(he)解決。

你:好的,我這就去學!

 

結尾

若(ruo)干年后,你已經(jing)成(cheng)為(wei)了公司的(de) Redis 專家。

不僅(jin)能(neng)熟練使用(yong) Redis 解決各(ge)種業務問(wen)題,搭個(ge) Redis 集群架構(gou)也(ye)是(shi)手拿(na)把掐的。

你也像魚皮當時一(yi)樣(yang),耐心地給新人分(fen)享(xiang)學習(xi) Redis 的經驗,讓他們謹記(ji)魚皮的教誨 “Redis 是實戰型(xing)技術,一(yi)定(ding)要多(duo)動手實踐”。

 

再次遇(yu)到魚皮是(shi)在一條昏暗的(de)小巷(xiang),此(ci)時(shi)的(de)他年過(guo) 35,灰頭土臉。你什(shen)么都沒(mei)說,只是(shi)給他點(dian)了個贊(zan),投了 2 個幣,不打擾,是(shi)你的(de)溫柔。

更多編程學習資源(yuan)

posted @ 2025-10-22 11:21  程序員魚皮  閱讀(180)  評論(3)    收藏  舉報