深入理解分布式緩存——使用Spring Boot+Redis實(shí)現(xiàn)分布式緩存解決方案
在微服務(wù)飛速發(fā)展的今天,在高并發(fā)的分布式的系統(tǒng)中,緩存是提升系統(tǒng)性能的重要手段。沒有緩存對(duì)后端請(qǐng)求的攔截,大量的請(qǐng)求將直接落到系統(tǒng)的底層數(shù)據(jù)庫。系統(tǒng)是很難撐住高并發(fā)的沖擊,下面就以Redis為例來聊聊分布式系統(tǒng)中關(guān)于緩存的設(shè)計(jì)以及過程中遇到的一些問題。
一、分布式緩存簡介
1. 什么是分布式緩存
分布式緩存:指將應(yīng)用系統(tǒng)和緩存組件進(jìn)行分離的緩存機(jī)制,這樣多個(gè)應(yīng)用系統(tǒng)就可以共享一套緩存數(shù)據(jù)了,它的特點(diǎn)是共享緩存服務(wù)和可集群部署,為緩存系統(tǒng)提供了高可用的運(yùn)行環(huán)境,以及緩存共享的程序運(yùn)行機(jī)制。
2、本地緩存VS分布式緩存
本地緩存:是應(yīng)用系統(tǒng)中的緩存組件,其最大的優(yōu)點(diǎn)是應(yīng)用和cache是在同一個(gè)進(jìn)程內(nèi)部,請(qǐng)求緩存非常快速,沒有過多的網(wǎng)絡(luò)開銷等,在單應(yīng)用不需要集群支持的場景下使用本地緩存較合適;但是,它的缺點(diǎn)也是緩存跟應(yīng)用程序耦合,多個(gè)應(yīng)用程序無法共享緩存數(shù)據(jù),各應(yīng)用或集群的各節(jié)點(diǎn)都需要維護(hù)自己的單獨(dú)緩存。很顯然,這對(duì)內(nèi)存是一種浪費(fèi)。
分布式緩存:與應(yīng)用分離的緩存組件或服務(wù),分布式緩存系統(tǒng)是一個(gè)獨(dú)立的緩存服務(wù),與本地應(yīng)用隔離,這使得多個(gè)應(yīng)用系統(tǒng)之間可直接的共享緩存數(shù)據(jù)。目前分布式緩存系統(tǒng)已經(jīng)成為微服務(wù)架構(gòu)的重要組成部分,活躍在成千上萬的應(yīng)用服務(wù)中。但是,目前還沒有一種緩存方案可以解決一切的業(yè)務(wù)場景或數(shù)據(jù)類型,我們需要根據(jù)自身的特殊場景和背景,選擇最適合的緩存方案。
3、分布式緩存的特性
相對(duì)于本地應(yīng)用緩存,分布式緩存具有如下特性:
1) 高性能:當(dāng)傳統(tǒng)數(shù)據(jù)庫面臨大規(guī)模數(shù)據(jù)訪問時(shí),磁盤I/O 往往成為性能瓶頸,從而導(dǎo)致過高的響應(yīng)延遲。分布式緩存將高速內(nèi)存作為數(shù)據(jù)對(duì)象的存儲(chǔ)介質(zhì),數(shù)據(jù)以key/value 形式存儲(chǔ)。
2) 動(dòng)態(tài)擴(kuò)展性:支持彈性擴(kuò)展,通過動(dòng)態(tài)增加或減少節(jié)點(diǎn)應(yīng)對(duì)變化的數(shù)據(jù)訪問負(fù)載,提供可預(yù)測的性能與擴(kuò)展性;同時(shí),最大限度地提高資源利用率;
3) 高可用性:高可用性包含數(shù)據(jù)可用性與服務(wù)可用性兩方面,故障的自動(dòng)發(fā)現(xiàn),自動(dòng)轉(zhuǎn)義。確保不會(huì)因服務(wù)器故障而導(dǎo)致緩存服務(wù)中斷或數(shù)據(jù)丟失。
4) 易用性:提供單一的數(shù)據(jù)與管理視圖;API 接口簡單,且與拓?fù)浣Y(jié)構(gòu)無關(guān);動(dòng)態(tài)擴(kuò)展或失效恢復(fù)時(shí)無需人工配置;自動(dòng)選取備份節(jié)點(diǎn);多數(shù)緩存系統(tǒng)提供了圖形化的管理控制臺(tái),便于統(tǒng)一維護(hù);
4、分布式緩存的應(yīng)用場景
分布式緩存的典型應(yīng)用場景可分為以下幾類:
1) 頁面緩存:用來緩存Web 頁面的內(nèi)容片段,包括HTML、CSS 和圖片等,多應(yīng)用于社交網(wǎng)站等;
2) 應(yīng)用對(duì)象緩存:緩存系統(tǒng)作為ORM 框架的二級(jí)緩存對(duì)外提供服務(wù),目的是減輕數(shù)據(jù)庫的負(fù)載壓力,加速應(yīng)用訪問;
3) 狀態(tài)緩存:緩存包括Session 會(huì)話狀態(tài)及應(yīng)用橫向擴(kuò)展時(shí)的狀態(tài)數(shù)據(jù)等,這類數(shù)據(jù)一般是難以恢復(fù)的,對(duì)可用性要求較高,多應(yīng)用于高可用集群;
4) 并行處理:通常涉及大量中間計(jì)算結(jié)果需要共享;
5) 事件處理:分布式緩存提供了針對(duì)事件流的連續(xù)查詢(continuous query)處理技術(shù),滿足實(shí)時(shí)性需求;
6) 極限事務(wù)處理:分布式緩存為事務(wù)型應(yīng)用提供高吞吐率、低延時(shí)的解決方案,支持高并發(fā)事務(wù)請(qǐng)求處理,多應(yīng)用于鐵路、金融服務(wù)和電信等領(lǐng)域;
二、 為什么要用分布式緩存?
在傳統(tǒng)的后端架構(gòu)中,由于請(qǐng)求量以及響應(yīng)時(shí)間要求不高,我們經(jīng)常采用單一的數(shù)據(jù)庫結(jié)構(gòu)。這種架構(gòu)雖然簡單,但隨著請(qǐng)求量的增加,這種架構(gòu)存在性能瓶頸導(dǎo)致無法繼續(xù)穩(wěn)定提供服務(wù)。

通過在應(yīng)用服務(wù)與DB中間引入緩存層,我們可以得到如下三個(gè)好處:
(1)讀取速度得到提升。
(2)系統(tǒng)擴(kuò)展能力得到大幅增強(qiáng)。我們可以通過加緩存,來讓系統(tǒng)的承載能力提升。
(3)總成本下降,單臺(tái)緩存即可承擔(dān)原來的多臺(tái)DB的請(qǐng)求量,大大節(jié)省了機(jī)器成本。
三、常用的緩存技術(shù)
目前最流行的分布式緩存技術(shù)有redis和memcached兩種,
1. Memcache
Memcached 是一個(gè)高性能,分布式內(nèi)存對(duì)象緩存系統(tǒng),通過在內(nèi)存里維護(hù)一個(gè)統(tǒng)一的巨大的 Hash 表,它能夠用來存儲(chǔ)各種格式的數(shù)據(jù),包括圖像、視頻、文件以及數(shù)據(jù)庫檢索的結(jié)果等。簡單來說就是:將數(shù)據(jù)緩存到內(nèi)存中,然后從內(nèi)存中讀取,從而大大提高讀取速度。
Memcached 特性:
使用物理內(nèi)存作為緩存區(qū),可獨(dú)立運(yùn)行在服務(wù)器上。每個(gè)進(jìn)程最大 2G,如果想緩存更多的數(shù)據(jù),可以開辟更多的 Memcached 進(jìn)程(不同端口)或者使用分布式 Memcached 進(jìn)行緩存,將數(shù)據(jù)緩存到不同的物理機(jī)或者虛擬機(jī)上。
使用 key-value 的方式來存儲(chǔ)數(shù)據(jù)。這是一種單索引的結(jié)構(gòu)化數(shù)據(jù)組織形式,可使數(shù)據(jù)項(xiàng)查詢時(shí)間復(fù)雜度為 O(1)。
協(xié)議簡單,基于文本行的協(xié)議。直接通過 telnet 在 Memcached 服務(wù)器上可進(jìn)行存取數(shù)據(jù)操作,簡單,方便多種緩存參考此協(xié)議;
基于 libevent 高性能通信。Libevent 是一套利用 C 開發(fā)的程序庫,它將 BSD 系統(tǒng)的 kqueue,Linux 系統(tǒng)的 epoll 等事件處理功能封裝成一個(gè)接口,與傳統(tǒng)的 select 相比,提高了性能。
分布式能力取決于 Memcached 客戶端,服務(wù)器之間互不通信。各個(gè) Memcached 服務(wù)器之間互不通信,各自獨(dú)立存取數(shù)據(jù),不共享任何信息。服務(wù)器并不具有分布式功能,分布式部署取決于 Memcached 客戶端。
采用 LRU 緩存淘汰策略。在 Memcached 內(nèi)存儲(chǔ)數(shù)據(jù)項(xiàng)時(shí),可以指定它在緩存的失效時(shí)間,默認(rèn)為永久。當(dāng) Memcached 服務(wù)器用完分配的內(nèi)存時(shí),失效的數(shù)據(jù)被首先替換,然后也是最近未使用的數(shù)據(jù)。在 LRU 中,Memcached 使用的是一種 Lazy Expiration 策略,自己不會(huì)監(jiān)控存入的 key/vlue 對(duì)是否過期,而是在獲取 key 值時(shí)查看記錄的時(shí)間戳,檢查 key/value 對(duì)空間是否過期,這樣可減輕服務(wù)器的負(fù)載。
內(nèi)置了一套高效的內(nèi)存管理算法。這套內(nèi)存管理效率很高,而且不會(huì)造成內(nèi)存碎片,但是它最大的缺點(diǎn)就是會(huì)導(dǎo)致空間浪費(fèi)。當(dāng)內(nèi)存滿后,通過 LRU 算法自動(dòng)刪除不使用的緩存。
不支持持久化。Memcached 沒有考慮數(shù)據(jù)的容災(zāi)問題,重啟服務(wù),所有數(shù)據(jù)會(huì)丟失。
2. Redis
Redis 是一個(gè)開源(BSD 許可),基于內(nèi)存的,支持網(wǎng)絡(luò)、可基于內(nèi)存、分布式、可選持久性的鍵值對(duì)(Key-Value)存儲(chǔ)數(shù)據(jù)庫,并提供多種語言的 API。可以用作數(shù)據(jù)庫、緩存和消息中間件。
Redis 支持多種數(shù)據(jù)類型 - string、Hash、list、set、sorted set。提供兩種持久化方式 - RDB 和 AOF。通過 Redis cluster 提供集群模式。
Redis的優(yōu)勢:
性能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s 。
豐富的數(shù)據(jù)類型 – Redis支持二進(jìn)制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數(shù)據(jù)類型操作。
原子 – Redis的所有操作都是原子性的,同時(shí)Redis還支持對(duì)幾個(gè)操作合并后的原子性執(zhí)行。(事務(wù))
豐富的特性 – Redis還支持 publish/subscribe, 通知, key 過期等等特性。
3. 分布式緩存技術(shù)對(duì)比
不同的分布式緩存功能特性和實(shí)現(xiàn)原理方面有很大的差異,因此他們所適應(yīng)的場景也有所不同。

四、分布式緩存實(shí)現(xiàn)方案
緩存的目的是為了在高并發(fā)系統(tǒng)中有效降低DB的壓力,高效的數(shù)據(jù)緩存可以極大地提高系統(tǒng)的訪問速度和并發(fā)性能。分布式緩存有很多實(shí)現(xiàn)方案,下面將講一講分布式緩存實(shí)現(xiàn)方案。
1、緩存實(shí)現(xiàn)方案
如上圖所示,系統(tǒng)會(huì)自動(dòng)根據(jù)調(diào)用的方法緩存請(qǐng)求的數(shù)據(jù)。當(dāng)再次調(diào)用該方法時(shí),系統(tǒng)會(huì)首先從緩存中查找是否有相應(yīng)的數(shù)據(jù),如果命中緩存,則從緩存中讀取數(shù)據(jù)并返回;如果沒有命中,則請(qǐng)求數(shù)據(jù)庫查詢相應(yīng)的數(shù)據(jù)并再次緩存。

如上圖所示,每一個(gè)用戶請(qǐng)求都會(huì)先查詢緩存中的數(shù)據(jù),如果緩存命中,則會(huì)返回緩存中的數(shù)據(jù)。這樣能減少數(shù)據(jù)庫查詢,提高系統(tǒng)的響應(yīng)速度。
2、使用Spring Boot+Redis實(shí)現(xiàn)分布式緩存解決方案
接下來,以用戶信息管理模塊為例演示使用Redis實(shí)現(xiàn)數(shù)據(jù)緩存框架。
1.添加Redis Cache的配置類
RedisConfig類為Redis設(shè)置了一些全局配置,比如配置主鍵的生產(chǎn)策略KeyGenerator()方法,此類繼承CachingConfigurerSupport類,并重寫方法keyGenerator(),如果不配置,就默認(rèn)使用參數(shù)名作為主鍵。
@Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport { / ** * 采用RedisCacheManager作為緩存管理器 * 為了處理高可用Redis,可以使用RedisSentinelConfiguration來支持Redis Sentinel */ @Bean public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory).build(); return redisCacheManager; } / ** * 自定義生成key的規(guī)則 */ @Override public KeyGenerator keyGenerator() { return new KeyGenerator() { @Override public Object generate(Object o, Method method, Object...objects) { // 格式化緩存key字符串 StringBuilder stringBuilder = new StringBuilder(); // 追加類名 stringBuilder.append(o.getClass().getName()); // 追加方法名 stringBuilder.append(method.getName()); // 遍歷參數(shù)并且追加 for (Object obj :objects) { stringBuilder.append(obj.toString()); } System.out.println("調(diào)用Redis緩存Key: " + stringBuilder.toString()); return stringBuilder.toString(); } }; }}
在上面的示例中,主要是自定義配置RedisKey的生成規(guī)則,使用@EnableCaching注解和@Configuration注解。
@EnableCaching:開啟基于注解的緩存,也可以寫在啟動(dòng)類上。
@Configuration:標(biāo)識(shí)它是配置類的注解。
2.添加@Cacheable注解
在讀取數(shù)據(jù)的方法上添加@Cacheable注解,這樣就會(huì)自動(dòng)將該方法獲取的數(shù)據(jù)結(jié)果放入緩存。
@Repositorypublic class UserRepository { / ** * @Cacheable應(yīng)用到讀取數(shù)據(jù)的方法上,先從緩存中讀取,如果沒有,再從DB獲取數(shù)據(jù),然后把數(shù)據(jù)添加到緩存中 * unless表示條件表達(dá)式成立的話不放入緩存 * @param username * @return */ @Cacheable(value = "user") public User getUserByName(String username) { User user = new User(); user.setName(username); user.setAge(30); user.setPassword("123456"); System.out.println("user info from database"); return user; }}
在上面的實(shí)例中,使用@Cacheable注解標(biāo)注該方法要使用緩存。@Cacheable注解主要針對(duì)方法進(jìn)行配置,能夠根據(jù)方法的請(qǐng)求對(duì)參數(shù)及其結(jié)果進(jìn)行緩存。
1)這里緩存key的規(guī)則為簡單的字符串組合,如果不指定key參數(shù),則自動(dòng)通過keyGenerator生成對(duì)應(yīng)的key。
2)Spring Cache提供了一些可以使用的SpEL上下文數(shù)據(jù),通過#進(jìn)行引用。
3.測試數(shù)據(jù)緩存
創(chuàng)建單元測試方法調(diào)用getUserByName()方法,測試代碼如下:
@Testpublic void testGetUserByName() { User user = userRepository.getUserByName("weiz"); System.out.println("name: "+ user.getName()+",age:"+user.getAge()); user = userRepository.getUserByName("weiz"); System.out.println("name: "+ user.getName()+",age:"+user.getAge());}
上面的實(shí)例分別調(diào)用了兩次getUserByName()方法,輸出獲取到的User信息。
最后,單擊Run Test或在方法上右擊,選擇Run 'testGetUserByName',運(yùn)行單元測試方法,結(jié)果如下圖所示。

通過上面的日志輸出可以看到,首次調(diào)用getPersonByName()方法請(qǐng)求User數(shù)據(jù)時(shí),由于緩存中未保存該數(shù)據(jù),因此從數(shù)據(jù)庫中獲取User信息并存入Redis緩存,再次調(diào)用會(huì)命中此緩存并直接返回。
五、常見問題及解決方案
1.緩存預(yù)熱
緩存預(yù)熱指在用戶請(qǐng)求數(shù)據(jù)前先將數(shù)據(jù)加載到緩存系統(tǒng)中,用戶查詢 事先被預(yù)熱的緩存數(shù)據(jù),以提高系統(tǒng)查詢效率。緩存預(yù)熱一般有系統(tǒng)啟動(dòng) 加載、定時(shí)加載等方式。
5.熱key問題
所謂熱key問題就是,突然有大量的請(qǐng)求去訪問redis上的某個(gè)特定key,導(dǎo)致請(qǐng)求過于集中,達(dá)到網(wǎng)絡(luò)IO的上限,從而導(dǎo)致這臺(tái)redis的服務(wù)器宕機(jī)引發(fā)雪崩。

針對(duì)熱key的解決方案:
1. 提前把熱key打散到不同的服務(wù)器,降低壓力
2. 加二級(jí)緩存,提前加載熱key數(shù)據(jù)到內(nèi)存中,如果redis宕機(jī),則內(nèi)存查詢
2.緩存擊穿
緩存擊穿是指大量請(qǐng)求緩存中過期的key,由于并發(fā)用戶特別多,同時(shí)新的緩存還沒讀到數(shù)據(jù),導(dǎo)致大量的請(qǐng)求數(shù)據(jù)庫,引起數(shù)據(jù)庫壓力瞬間增大,造成過大壓力。緩存擊穿和熱key的問題比較類似,只是說的點(diǎn)在于過期導(dǎo)致請(qǐng)求全部打到DB上而已。
解決方案:
1. 加鎖更新,假設(shè)請(qǐng)求查詢數(shù)據(jù)A,若發(fā)現(xiàn)緩存中沒有,對(duì)A這個(gè)key加鎖,同時(shí)去數(shù)據(jù)庫查詢數(shù)據(jù),然后寫入緩存,再返回給用戶,這樣后面的請(qǐng)求就可以從緩存中拿到數(shù)據(jù)了。
2. 將過期時(shí)間組合寫在value中,通過異步的方式不斷地刷新過期時(shí)間,防止此類現(xiàn)象發(fā)生。

3.緩存穿透
緩存穿透是指查詢不存在緩存中的數(shù)據(jù),每次請(qǐng)求都會(huì)打到DB,就像緩存不存在一樣。

解決方案:
接口層增加參數(shù)校驗(yàn),如用戶鑒權(quán)校驗(yàn),請(qǐng)求參數(shù)校驗(yàn)等,對(duì) id<=0的請(qǐng)求直接攔截,一定不存在請(qǐng)求數(shù)據(jù)的不去查詢數(shù)據(jù)庫。
布隆過濾器:指將所有可能存在的Key通過Hash散列函數(shù)將它映射為一個(gè)位數(shù)組,在用戶發(fā)起請(qǐng)求時(shí)首先經(jīng)過布隆過濾器的攔截,一個(gè)一定不存在的數(shù)據(jù)會(huì)被這個(gè)布隆過濾器攔截,從而避免對(duì)底層存儲(chǔ)系統(tǒng)帶來查詢上 的壓力。
cache null策略:指如果一個(gè)查詢返回的結(jié)果為null(可能是數(shù)據(jù)不存在,也可能是系統(tǒng)故障),我們?nèi)匀痪彺孢@個(gè)null結(jié)果,但它的過期 時(shí)間會(huì)很短,通常不超過 5 分鐘;在用戶再次請(qǐng)求該數(shù)據(jù)時(shí)直接返回 null,而不會(huì)繼續(xù)訪問數(shù)據(jù)庫,從而有效保障數(shù)據(jù)庫的安全。其實(shí)cache null策略的核心原理是:在緩存中記錄一個(gè)短暫的(數(shù)據(jù)過期時(shí)間內(nèi))數(shù)據(jù)在系統(tǒng)中是否存在的狀態(tài),如果不存在,則直接返回null,不再查詢數(shù)據(jù)庫,從而避免緩存穿透到數(shù)據(jù)庫上。
布隆過濾器
布隆過濾器的原理是在保存數(shù)據(jù)的時(shí)候,會(huì)通過Hash散列函數(shù)將它映射為一個(gè)位數(shù)組中的K個(gè)點(diǎn),同時(shí)把他的值置為1。這樣當(dāng)用戶再次來查詢A時(shí),而A在布隆過濾器值為0,直接返回,就不會(huì)產(chǎn)生擊穿請(qǐng)求打到DB了。

4.緩存雪崩
緩存雪崩指在同一時(shí)刻由于大量緩存失效,導(dǎo)致大量原本應(yīng)該訪問緩存的請(qǐng)求都去查詢數(shù)據(jù)庫,而對(duì)數(shù)據(jù)庫的CPU和內(nèi)存造成巨大壓力,嚴(yán)重的話會(huì)導(dǎo)致數(shù)據(jù)庫宕機(jī),從而形成一系列連鎖反應(yīng),使得整個(gè)系統(tǒng)崩潰。雪崩和擊穿、熱key的問題不太一樣的是,緩存雪崩是指大規(guī)模的緩存都過期失效了。

針對(duì)雪崩的解決方案:
1. 針對(duì)不同key設(shè)置不同的過期時(shí)間,避免同時(shí)過期
2. 限流,如果redis宕機(jī),可以限流,避免同時(shí)刻大量請(qǐng)求打崩DB
3. 二級(jí)緩存,同熱key的方案。
六、緩存與數(shù)據(jù)庫數(shù)據(jù)一致性
緩存與數(shù)據(jù)庫的一致性問題分為兩種情況,一是緩存中有數(shù)據(jù),則必須與數(shù)據(jù)庫中的數(shù)據(jù)一致;二是緩存中沒數(shù)據(jù),則數(shù)據(jù)庫中的數(shù)據(jù)必須是最新的。
3.1刪除和修改數(shù)據(jù)
第一種情況:我們先刪除緩存,在更新數(shù)據(jù)庫,潛在的問題:數(shù)據(jù)庫更新失敗了,get請(qǐng)求進(jìn)來發(fā)現(xiàn)沒緩存則請(qǐng)求數(shù)據(jù)庫,導(dǎo)致緩存又刷入了舊的值。
第二種情況:我們先更新數(shù)據(jù)庫,再刪除緩存,潛在的問題:緩存刪除失敗,get請(qǐng)求進(jìn)來緩存命中,導(dǎo)致讀到的是舊值。
3.2先刪除緩存再更新數(shù)據(jù)庫
假設(shè)有2個(gè)線程A和B,A刪除緩存之后,由于網(wǎng)絡(luò)延遲,在更新數(shù)據(jù)庫之前,B來訪問了,發(fā)現(xiàn)緩存未命中,則去請(qǐng)求數(shù)據(jù)庫然后把舊值刷入了緩存,這時(shí)候姍姍來遲的A,才把最新數(shù)據(jù)刷入數(shù)據(jù)庫,導(dǎo)致了數(shù)據(jù)的不一致性。
解決方案
針對(duì)多線程的場景,可以采用延遲雙刪的解決方案,我們可以在A更新完數(shù)據(jù)庫之后,線程A先休眠一段時(shí)間,再刪除緩存。
需要注意的是:具體休眠的時(shí)間,需要評(píng)估自己的項(xiàng)目的讀數(shù)據(jù)業(yè)務(wù)邏輯的耗時(shí)。這么做的目的,就是確保讀請(qǐng)求結(jié)束,寫請(qǐng)求可以刪除讀請(qǐng)求造成的緩存臟數(shù)據(jù)。當(dāng)然這種策略還要考慮redis和數(shù)據(jù)庫主從同步的耗時(shí)。
3.3先更新數(shù)據(jù)庫再刪除緩存
這種場景潛在的風(fēng)險(xiǎn)就是更新完數(shù)據(jù)庫,刪緩存之前,會(huì)有部分并發(fā)請(qǐng)求讀到舊值,這種情況對(duì)業(yè)務(wù)影響較小,可以通過重試機(jī)制,保證緩存能得到刪除。
最后
以上,就把分布式緩存介紹完了,并使用Spring Boot+Redis實(shí)現(xiàn)分布式緩存解決方案。緩存的使用是程序員、架構(gòu)師的必備技能,好的程序員能根據(jù)數(shù)據(jù)類型、業(yè)務(wù)場景來準(zhǔn)確判斷使用何種類型的緩存,如何使用這種緩存,以最小的成本最快的效率達(dá)到最優(yōu)的目的。
