Redis 1級(入門基礎)
1、Redis有哪些數據類型?
string,list,set,sorted set(Zset),hash
高級數據結構分別是bitmap、GEO、Stream、HyperLogLog 其中,最重要的就是bitmap。GEO數據結構可以在Redis中存儲地理坐標。
Stream是Redis 5.0版本引入的一個新的數據類型,它以更抽象的方式模擬日志數據結構,但日志仍然是完整的:就像一個日志文件,通常實現為以只附加模式打開的文件,Redis流主要是一個僅附加數據結構。至少從概念上來講,因為Redis流是一種在內存表示的抽象數據類型,他們實現了更加強大的操作,以此來克服日志文件本身的限制。
Stream是Redis的數據類型中最復雜的,盡管數據類型本身非常簡單,它實現了額外的非強制性的特性:提供了一組允許消費者以阻塞的方式等待生產者向Stream中發送的新消息,此外還有一個名為消費者組的概念。
消費者組最早是由名為Kafka(TM)的流行消息系統引入的。Redis用完全不同的術語重新實現了一個相似的概念,但目標是相同的:允許一組客戶端相互配合來消費同一個Stream的不同部分的消息。
Redis HyperLogLog 是用來做基數統計的算法,HyperLogLog 的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的空間總是固定 的、並且是很小的。
在 Redis 里面,每個 HyperLogLog 鍵只需要花費 12 KB 內存,就可以計算接近 2^64 個不同元素的基 數。這和計算基數時,元素越多耗費內存就越多的集合形成鮮明對比。
但是,因為 HyperLogLog 只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以 HyperLogLog 不能像集合那樣,返回輸入的各個元素。
2、集合和列表有什么區別?
列表list是可以從兩端推入、推出數據的隊列;列表可以存儲相同字符;
集合set是無序列表(只能用SADD來添加元素);使用散列(hash)保證存儲的字符不相同;集合支持交、並、差等計算(SINTER、SUNION、SDIFF);
3、有序集合zset和散列hash有什么區別?
散列存儲鍵值對;
有序集合使用成員member來存儲鍵,用分值(浮點數)來存儲值;可根據分值的順序來訪問元素;
4、在散列中可以用HGETALL命令來獲取所有的鍵值,但在值較大的情況下,我們如何更加穩妥的(避免服務器阻塞)獲取全部 or 部分的鍵值?
獲取全部的鍵值:使用HKEYS獲取所有的鍵,然后使用HGET一個個的獲取全部值,從而避免因為一次獲取多個大體積的值而導致服務器阻塞。
獲取部分的鍵值:也是使用HKEYS獲取所有的鍵,然后根據條件篩選需要的鍵,使用HEXISTS檢查鍵是否存在,然后再用HGET獲取必要的鍵
5、講一講Redis的常用場景
簡單kv字符存儲、Session會話記錄、Token保持、熱點數據存儲、網頁緩存、數據行緩存、排名、高速隊列、分布式鎖、計數器、發布訂閱……
6、Redis如何設置密碼及驗證密碼?
設置密碼:config set requirepass 123456
授權密碼:auth 123456
Redis 2級(中級)
1、 Redis集群方案應該怎么做?都有哪些方案?
- 1.twemproxy,大概概念是,它類似於一個代理方式,使用方法和普通redis無任何區別,設置好它下屬的多個redis實例后,使用時在本需要連接redis的地方改為連接twemproxy,它會以一個代理的身份接收請求並使用一致性hash算法,將請求轉接到具體redis,將結果再返回twemproxy。使用方式簡便(相對redis只需修改連接端口),對舊項目擴展的首選。 問題:twemproxy自身單端口實例的壓力,使用一致性hash后,對redis節點數量改變時候的計算值的改變,數據無法自動移動到新的節點。
- 2.codis,目前用的最多的集群方案,基本和twemproxy一致的效果,但它支持在 節點數量改變情況下,舊節點數據可恢復到新hash節點。
- 3.redis cluster3.0自帶的集群,特點在於他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持節點設置從節點。具體看官方文檔介紹。
- 4.在業務代碼層實現,起幾個毫無關聯的redis實例,在代碼層,對key 進行hash計算,然后去對應的redis實例操作數據。 這種方式對hash層代碼要求比較高,考慮部分包括,節點失效后的替代算法方案,數據震盪后的自動腳本恢復,實例的監控,等等。
2、MySQL里有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據?
redis內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略。
相關知識:redis 內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略。redis 提供 6種數據淘汰策略:
voltile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰
volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰
volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰
allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
no-enviction(驅逐):禁止驅逐數據
3、Redis和Redisson有什么關系?
Redisson是一個高級的分布式協調Redis客戶端,能幫助用戶在分布式環境中輕松實現一些Java的數據結構對象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)
4、Jedis 和Redisson同步異步IO的區別?
Jedis使用阻塞的I/O,且其方法調用都是同步的,程序流需要等到sockets處理完I/O才能執行,不支持異步。Jedis客戶端實例不是線程安全的,所以需要通過連接池來使用Jedis。
Redisson使用非阻塞的I/O和基於Netty框架的事件驅動的通信層,其方法調用是異步的。Redisson的API是線程安全的,所以可以操作單個Redisson連接來完成各種操作。
5、Redis集群的主從復制模型是怎樣的?
為了使在部分節點失敗或者大部分節點無法通信的情況下集群仍然可用,所以集群使用了主從復制模型,每個節點都會有N-1個復制品.
6、Redis集群會有寫操作丟失嗎?為什么?
Redis並不能保證數據的強一致性,這意味這在實際中集群在特定的條件下可能會丟失寫操作。
7、Redis集群之間是如何復制的?
異步復制
8、Redis集群最大節點個數是多少?
16384,即哈希槽的數量
9、Redis哈希槽的概念?
Redis集群沒有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384個哈希槽,每個key通過CRC16校驗后對16384取模來決定放置哪個槽,集群的每個節點負責一部分hash槽。
10、談談AOF中appendfsync各個選項的區別?
appendfsync always:每次操作都寫入一次aof文件,並完成磁盤同步,強烈不建議使用,會嚴重降低Redis的寫效率,甚至寫入放大問題;
appendfsync everysec:默認的選項,每一秒寫入aof文件,並顯式完成磁盤同步
appendfsync no:寫入aof文件,不等待磁盤同步,即由系統來決定寫AOF文件,可能會帶來數據丟失問題。
11、談談如何解決AOF文件越來越膨脹的問題?
使用AOF 自動重寫。即當AOF文件增長到一定大小的時候Redis能夠調用 BGREWRITEAOF 對日志文件進行重寫。它是這樣工作的:Redis會記住上次進行寫日志后文件的大小(如果從開機以來還沒進行過重寫,那日志大小在開機的時候確定)
基礎大小會同現在的大小進行比較。如果現在的大小比基礎大小大制定的百分比(auto-aof-rewrite-percentage),重寫功能將啟動。同時需要指定一個最小大小(auto-aof-rewrite-min-size)用於AOF重寫,這個用於阻止即使文件很小但是增長幅度很大也去重寫AOF文件的情況。
如:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
12、如何檢查和修復AOF文件
檢查:redis-check-aof appendonly.aof
修復:redis-check-aof appendonly.aof --fix
13、如何進行性能測試
redis-benchmark -c 1 –q
14、如何選擇合適的持久化方式?
一般來說, 如果想達到足以媲美PostgreSQL的數據安全性, 你應該同時使用兩種持久化功能。如果你非常關心你的數據, 但仍然可以承受數分鍾以內的數據丟失,那么你可以只使用RDB持久化。
有很多用戶都只使用AOF持久化,但並不推薦這種方式:因為定時生成RDB快照(snapshot)非常便於進行數據庫備份, 並且 RDB 恢復數據集的速度也要比AOF恢復的速度要快。
15、Redis常見性能問題和解決方案?
(1) Master最好不要做任何持久化工作,如RDB內存快照和AOF日志文件
(2) 如果數據比較重要,某個Slave開啟AOF備份數據,策略設置為每秒同步一次
(3) 為了主從復制的速度和連接的穩定性,Master和Slave最好在同一個局域網內
(4) 盡量避免在壓力很大的主庫上增加從庫
(5) 主從復制不要用圖狀結構,用單向鏈表結構更為穩定,即:Master <- Slave1 <- Slave2 <- Slave3...這樣的結構方便解決單點故障問題,實現Slave對Master的替換。如果Master掛了,可以立刻啟用Slave1做Master,其他不變。
(6) 如果是讀壓力比較大的應用,可以用樹型結構,比如1主帶2-3從,從再帶2-3的二級從...
16、基數估計算法(HyperLogLog)有什么特點和用途?
HyperLogLog 的優點是,即使輸入元素的數量或者體積非常非常大,計算基數所需的空間總是固定的、並且是很小的。在 Redis 里面,每個 HyperLogLog 鍵只需要花費 12 KB 內存,就可以計算接近 2^64 個不同元素的基數。這和計算基數時,元素越多耗費內存就越多的集合形成鮮明對比。但是,因為 HyperLogLog 只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以HyperLogLog 不能像集合那樣,返回輸入的各個元素。
用途:用於僅僅需要計數(不要求完全精准)的場景。
比如網易音樂歌曲評論的999+之類的場景。還比如統計上億計的IP、點擊等數據,如果用傳統的集合需要500GB內存,而用HyperLogLog只需要12kb
17、Redis 的事務中途的命令錯誤和運行時錯誤會造成事務回滾嗎?
命令錯誤會,但運行時錯誤不會。因為Redis的事務沒有關系數據庫事務提供的回滾(rollback)功能。為此開發者必須在事務執行出錯后自己寫代碼(如事務日志)來處理。
18、寫一段Watch實現的線程安全的整形數值自增(加1)的代碼
WATCH Somekey
val = GET Somekey
val = val + 1
MULTI
SET Somekey $val
EXEC
19、介紹一下你所知道的分區方式或算法。
1、范圍分區
最簡單的分區方式是按范圍分區,就是映射一定范圍的對象到特定的Redis實例。
比如key為:object_ID,ID從0到10000的用戶會保存到實例R0,ID從10001到 20000的用戶會保存到R1,以此類推。這種方式是可行的,並且在實際中使用,不足就是要有一個區間范圍到實例的映射表。這個表要被管理,同時還需要各 種對象的映射表,通常對Redis來說並非是好的方法。
2、哈希分區
另外一種分區方法是hash分區。這對任何key都適用,也無需是object_name:這種形式,像下面描述的一樣簡單:用一個hash函數將key轉換為一個數字,比如使用crc32 hash函數。對key foobar執行crc32(foobar)會輸出類似93024922的整數。
對這個整數取模,將其轉化為0-3之間的數字,就可以將這個整數映射到4個Redis實例中的一個了。93024922 % 4 = 2,就是說key foobar應該被存到R2實例中。注意:取模操作是取除的余數,通常在多種編程語言中用%操作符實現。
20、如何實現分布式鎖?
1、 可以參考這里:https://www.cnblogs.com/linjiqin/p/8003838.html
講通原則和算法即可。
2、 還可以基於redisson快速實現,見:https://github.com/redisson/redisson/wiki/8.-distributed-locks-and-synchronizers
