1. 程式人生 > 實用技巧 >vue.js+vuetify學習開發排坑:一個古怪的程式碼 v-slot:activator="{ on, attrs }"

vue.js+vuetify學習開發排坑:一個古怪的程式碼 v-slot:activator="{ on, attrs }"

1.Redis是什麼

Redis是C語言開發的一個開源的(遵從BSD協議)高效能鍵值對(key-value)的記憶體資料庫,可以用作資料庫、快取、訊息中介軟體等。它是一種NoSQL(not-only sql,泛指非關係型資料庫)的資料庫。Redis作為一個記憶體資料庫。

1、效能優秀,資料在記憶體中,讀寫速度非常快,支援併發10W QPS;

2、單程序單執行緒,是執行緒安全的,採用IO多路複用機制;

3、豐富的資料型別,支援字串(strings)、雜湊(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等;

4、支援資料持久化。可以將記憶體中資料儲存在磁碟中,重啟時載入;

5、主從複製,哨兵,高可用;

6、可以用作分散式鎖;

7、可以作為訊息中介軟體使用,支援釋出訂閱

2.五種資料型別

首先redis內部使用一個redisObject物件來表示所有的key和value,redisObject最主要的資訊如上圖所示:type表示一個value物件具體是何種資料型別,encoding是不同資料型別在redis內部的儲存方式。

比如:type=string表示value儲存的是一個普通字串,那麼encoding可以是raw或者int。

1、string是redis最基本的型別,可以理解成與memcached一模一樣的型別,一個key對應一個value。value不僅是string,也可以是數字。string型別是二進位制安全的,意思是redis的string型別可以包含任何資料,比如jpg圖片或者序列化的物件。string型別的值最大能儲存512M。

2、Hash是一個鍵值(key-value)的集合。redis的hash是一個string的key和value的對映表,Hash特別適合儲存物件。常用命令:hget,hset,hgetall等。

3、list列表是簡單的字串列表,按照插入順序排序。可以新增一個元素到列表的頭部(左邊)或者尾部(右邊) 常用命令:lpush、rpush、lpop、rpop、lrange(獲取列表片段)等。應用場景:list應用場景非常多,也是Redis最重要的資料結構之一,比如關注列表,粉絲列表都可以用list結構來實現。資料結構:list就是連結串列,可以用來當訊息佇列用。redis提供了List的push和pop操作,還提供了操作某一段的api,可以直接查詢或者刪除某一段的元素。實現方式:redis list的是實現是一個雙向連結串列,既可以支援反向查詢和遍歷,更方便操作,不過帶來了額外的記憶體開銷。

4、set是string型別的無序集合。集合是通過hashtable實現的。set中的元素是沒有順序的,而且是沒有重複的。常用命令:sdd、spop、smembers、sunion等。應用場景:redis set對外提供的功能和list一樣是一個列表,特殊之處在於set是自動去重的,而且set提供了判斷某個成員是否在一個set集合中。

5、zset和set一樣是string型別元素的集合,且不允許重複的元素。常用命令:zadd、zrange、zrem、zcard等。使用場景:sorted set可以通過使用者額外提供一個優先順序(score)的引數來為成員排序,並且是插入有序的,即自動排序。當你需要一個有序的並且不重複的集合列表,那麼可以選擇sorted set結構。和set相比,sorted set關聯了一個double型別權重的引數score,使得集合中的元素能夠按照score進行有序排列,redis正是通過分數來為集合中的成員進行從小到大的排序。實現方式:Redis sorted set的內部使用HashMap和跳躍表(skipList)來保證資料的儲存和有序,HashMap裡放的是成員到score的對映,而跳躍表裡存放的是所有的成員,排序依據是HashMap裡存的score,使用跳躍表的結構可以獲得比較高的查詢效率,並且在實現上比較簡單。

3.資料型別應用場景總結

型別簡介特性場景
string(字串) 二進位制安全 可以包含任何資料,比如jpg圖片或者序列化物件
Hash(字典) 鍵值對集合,即程式語言中的map型別 適合儲存物件,並且可以像資料庫中的update一個屬性一樣只修改某一項屬性值 儲存、讀取、修改使用者屬性
List(列表) 連結串列(雙向連結串列) 增刪快,提供了操作某一元素的api 最新訊息排行;訊息佇列
set(集合) hash表實現,元素不重複 新增、刪除、查詢的複雜度都是O(1),提供了求交集、並集、差集的操作 共同好友;利用唯一性,統計訪問網站的所有Ip
sorted set(有序集合zset) 將set中的元素增加一個權重引數score,元素按score有序排列 資料插入集合時,已經進行了天然排序 排行榜;帶權重的訊息佇列

結合spring boot使用的。一般有兩種方式,一種是直接通過RedisTemplate來使用,另一種是使用spring cache整合Redis

4.快取問題

快取和資料庫資料一致性問題

分散式環境下非常容易出現快取和資料庫間資料一致性問題,針對這一點,如果專案對快取的要求是強一致性的,那麼就不要使用快取。我們只能採取合適的策略來降低快取和資料庫間資料不一致的概率,而無法保證兩者間的強一致性。

合適的策略包括合適的快取更新策略,更新資料庫後及時更新快取、快取失敗時增加重試機制。

Redis雪崩

一般快取都是定時任務去重新整理,或者查不到之後去更新快取的,定時任務重新整理就有一個問題。舉個栗子:如果首頁所有Key的失效時間都是12小時,中午12點重新整理的,我零點有個大促活動大量使用者湧入,假設每秒6000個請求,本來快取可以抗住每秒5000個請求,但是快取中所有Key都失效了。此時6000個/秒的請求全部落在了資料庫上,資料庫必然扛不住,真實情況可能DBA都沒反應過來直接掛了,此時,如果沒什麼特別的方案來處理,DBA很著急,重啟資料庫,但是資料庫立馬又被新流量給打死了。這就是我理解的快取雪崩。

解決方案

在批量往Redis存資料的時候,把每個Key的失效時間都加個隨機值就好了,這樣可以保證資料不會再同一時間大面積失效。

setRedis(key, value, time+Math.random()*10000);

如果Redis是叢集部署,將熱點資料均勻分佈在不同的Redis庫中也能避免全部失效。或者設定熱點資料永不過期,有更新操作就更新快取就好了(比如運維更新了首頁商品,那你刷下快取就好了,不要設定過期時間)。

快取穿透和擊穿和雪崩的區別

快取穿透

快取穿透是指快取和資料庫中都沒有的資料,而使用者不斷髮起請求,舉個栗子:我們資料庫的id都是從1自增的,如果發起id=-1的資料或者id特別大不存在的資料,這樣的不斷攻擊導致資料庫壓力很大,嚴重會擊垮資料庫。

解決方案

  1. 在介面層增加校驗,比如使用者鑑權,引數做校驗,不合法的校驗直接return,比如id做基礎校驗,id小於1直接攔截。
  2. 高階用法**布隆過濾器(Bloom Filter)**這個也能很好的預防快取穿透的發生,他的原理也很簡單,就是利用高效的資料結構和演算法快速判斷出你這個Key是否在資料庫中存在,不存在你return就好了,存在你就去查DB重新整理KV再return。

快取擊穿

跟快取雪崩有點像,但是又有一點不一樣,快取雪崩是因為大面積的快取失效,打崩了DB,而快取擊穿不同的是快取擊穿是指一個Key非常熱點,在不停地扛著大量的請求,大併發集中對這一個點進行訪問,當這個Key在失效的瞬間,持續的大併發直接落到了資料庫上,就在這個Key的點上擊穿了快取。

解決方案

設定熱點資料永不過期,或者加上互斥鎖就搞定了。Demo:

  

public static String getData(String key) throws InterruptedException {
     //從Redis查詢資料
     String result = getDataByKV(key);
     //引數校驗
     if (StringUtils.isBlank(result)) {
         try {
             //獲得鎖
             if (reenLock.tryLock()) {
                 //去資料庫查詢
                 result = getDataByDB(key);
                 //校驗
                 if (StringUtils.isNotBlank(result)) {
                     //插進快取
                     setDataToKV(key, result);
                 }
             } else {
                 //睡一會再拿
                 Thread.sleep(100L);
                 result = getData(key);
             }
         } finally {
             //釋放鎖
             reenLock.unlock();
         }
     }
     return result;
 }

    

5.Redis為什麼這麼快

Redis是單程序單執行緒的模型,因為Redis完全是基於記憶體的操作,CPU不是Redis的瓶頸,Redis的瓶頸最有可能是機器記憶體的大小或者網路頻寬。 第一:Redis完全基於記憶體,絕大部分請求是純粹的記憶體操作,非常迅速,資料存在記憶體中,類似於HashMap,HashMap的優勢就是查詢和操作的時間複雜度是O(1)。第二:資料結構簡單,對資料操作也簡單。第三:採用單執行緒,避免了不必要的上下文切換和競爭條件,不存在多執行緒導致的CPU切換,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有死鎖問題導致的效能消耗。第四:使用多路複用IO模型,非阻塞IO。

6.Redis淘汰策略

策略描述
volatile-lru 從已設定過期時間的KV集中優先對最近最少使用(less recently used)的資料淘汰
volitile-ttl 從已設定過期時間的KV集中優先對剩餘時間短(time to live)的資料淘汰
volitile-random 從已設定過期時間的KV集中隨機選擇資料淘汰
allkeys-lru 從所有KV集中優先對最近最少使用(less recently used)的資料淘汰
allKeys-random 從所有KV集中隨機選擇資料淘汰
noeviction 不淘汰策略,若超過最大記憶體,返回錯誤資訊

補充一下:Redis4.0加入了LFU(least frequency use)淘汰策略,包括volatile-lfu和allkeys-lfu,通過統計訪問頻率,將訪問頻率最少,即最不經常使用的KV淘汰。