日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

2W字!详解20道Redis经典面试题!(珍藏版)

發(fā)布時間:2023/12/14 数据库 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2W字!详解20道Redis经典面试题!(珍藏版) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

金九銀十即將到來,整理了20道經典Redis面試題,希望對大家有幫助。

1. 什么是Redis?它主要用來什么的?

Redis,英文全稱是Remote Dictionary Server(遠程字典服務),是一個開源的使用ANSI C語言編寫、支持網絡、可基于內存亦可持久化的日志型、Key-Value數(shù)據(jù)庫,并提供多種語言的API。

與MySQL數(shù)據(jù)庫不同的是,Redis的數(shù)據(jù)是存在內存中的。它的讀寫速度非常快,每秒可以處理超過10萬次讀寫操作。因此redis被廣泛應用于緩存,另外,Redis也經常用來做分布式鎖。除此之外,Redis支持事務、持久化、LUA 腳本、LRU 驅動事件、多種集群方案。

2.說說Redis的基本數(shù)據(jù)結構類型

大多數(shù)小伙伴都知道,Redis有以下這五種基本類型:

  • String(字符串)

  • Hash(哈希)

  • List(列表)

  • Set(集合)

  • zset(有序集合)

它還有三種特殊的數(shù)據(jù)結構類型

  • Geospatial

  • Hyperloglog

  • Bitmap

2.1 Redis 的五種基本數(shù)據(jù)類型

String(字符串)

  • 簡介:String是Redis最基礎的數(shù)據(jù)結構類型,它是二進制安全的,可以存儲圖片或者序列化的對象,值最大存儲為512M

  • 簡單使用舉例: set key value、get key等

  • 應用場景:共享session、分布式鎖,計數(shù)器、限流。

  • 內部編碼有3種,int(8字節(jié)長整型)/embstr(小于等于39字節(jié)字符串)/raw(大于39個字節(jié)字符串)

C語言的字符串是char[]實現(xiàn)的,而Redis使用SDS(simple dynamic string) 封裝,sds源碼如下:

struct?sdshdr{unsigned?int?len;?//?標記buf的長度unsigned?int?free;?//標記buf中未使用的元素個數(shù)char?buf[];?//?存放元素的坑 }

SDS 結構圖如下:

Redis為什么選擇SDS結構,而C語言原生的char[]不香嗎?

舉例其中一點,SDS中,O(1)時間復雜度,就可以獲取字符串長度;而C 字符串,需要遍歷整個字符串,時間復雜度為O(n)

Hash(哈希)

  • 簡介:在Redis中,哈希類型是指v(值)本身又是一個鍵值對(k-v)結構

  • 簡單使用舉例:hset key field value 、hget key field

  • 內部編碼:ziplist(壓縮列表) 、hashtable(哈希表)

  • 應用場景:緩存用戶信息等。

  • 注意點:如果開發(fā)使用hgetall,哈希元素比較多的話,可能導致Redis阻塞,可以使用hscan。而如果只是獲取部分field,建議使用hmget。

字符串和哈希類型對比如下圖:

List(列表)

  • 簡介:列表(list)類型是用來存儲多個有序的字符串,一個列表最多可以存儲2^32-1個元素。

  • 簡單實用舉例:lpush key value [value ...] 、lrange key start end

  • 內部編碼:ziplist(壓縮列表)、linkedlist(鏈表)

  • 應用場景:消息隊列,文章列表,

一圖看懂list類型的插入與彈出:

list應用場景參考以下:

  • lpush+lpop=Stack(棧)

  • lpush+rpop=Queue(隊列)

  • lpsh+ltrim=Capped Collection(有限集合)

  • lpush+brpop=Message Queue(消息隊列)

Set(集合)

  • 簡介:集合(set)類型也是用來保存多個的字符串元素,但是不允許重復元素

  • 簡單使用舉例:sadd key element [element ...]、smembers key

  • 內部編碼:intset(整數(shù)集合)、hashtable(哈希表)

  • 注意點:smembers和lrange、hgetall都屬于比較重的命令,如果元素過多存在阻塞Redis的可能性,可以使用sscan來完成。

  • 應用場景:用戶標簽,生成隨機數(shù)抽獎、社交需求。

有序集合(zset)

  • 簡介:已排序的字符串集合,同時元素不能重復

  • 簡單格式舉例:zadd key score member [score member ...],zrank key member

  • 底層內部編碼:ziplist(壓縮列表)、skiplist(跳躍表)

  • 應用場景:排行榜,社交需求(如用戶點贊)。

2.2 Redis 的三種特殊數(shù)據(jù)類型

  • Geo:Redis3.2推出的,地理位置定位,用于存儲地理位置信息,并對存儲的信息進行操作。

  • HyperLogLog:用來做基數(shù)統(tǒng)計算法的數(shù)據(jù)結構,如統(tǒng)計網站的UV。

  • Bitmaps :用一個比特位來映射某個元素的狀態(tài),在Redis中,它的底層是基于字符串類型實現(xiàn)的,可以把bitmaps成作一個以比特位為單位的數(shù)組

3. Redis為什么這么快?

Redis為什么這么快

3.1 基于內存存儲實現(xiàn)

我們都知道內存讀寫是比在磁盤快很多的,Redis基于內存存儲實現(xiàn)的數(shù)據(jù)庫,相對于數(shù)據(jù)存在磁盤的MySQL數(shù)據(jù)庫,省去磁盤I/O的消耗。

3.2 高效的數(shù)據(jù)結構

我們知道,Mysql索引為了提高效率,選擇了B+樹的數(shù)據(jù)結構。其實合理的數(shù)據(jù)結構,就是可以讓你的應用/程序更快。先看下Redis的數(shù)據(jù)結構&內部編碼圖:

SDS簡單動態(tài)字符串

  • 字符串長度處理:Redis獲取字符串長度,時間復雜度為O(1),而C語言中,需要從頭開始遍歷,復雜度為O(n);

  • 空間預分配:字符串修改越頻繁的話,內存分配越頻繁,就會消耗性能,而SDS修改和空間擴充,會額外分配未使用的空間,減少性能損耗。

  • 惰性空間釋放:SDS 縮短時,不是回收多余的內存空間,而是free記錄下多余的空間,后續(xù)有變更,直接使用free中記錄的空間,減少分配。

  • 二進制安全:Redis可以存儲一些二進制數(shù)據(jù),在C語言中字符串遇到'\0'會結束,而 SDS中標志字符串結束的是len屬性。

字典

Redis 作為 K-V 型內存數(shù)據(jù)庫,所有的鍵值就是用字典來存儲。字典就是哈希表,比如HashMap,通過key就可以直接獲取到對應的value。而哈希表的特性,在O(1)時間復雜度就可以獲得對應的值。

跳躍表

  • 跳躍表是Redis特有的數(shù)據(jù)結構,就是在鏈表的基礎上,增加多級索引提升查找效率。

  • 跳躍表支持平均 O(logN),最壞 O(N)復雜度的節(jié)點查找,還可以通過順序性操作批量處理節(jié)點。

3.3 合理的數(shù)據(jù)編碼

Redis 支持多種數(shù)據(jù)數(shù)據(jù)類型,每種基本類型,可能對多種數(shù)據(jù)結構。什么時候,使用什么樣數(shù)據(jù)結構,使用什么樣編碼,是redis設計者總結優(yōu)化的結果。

  • String:如果存儲數(shù)字的話,是用int類型的編碼;如果存儲非數(shù)字,小于等于39字節(jié)的字符串,是embstr;大于39個字節(jié),則是raw編碼。

  • List:如果列表的元素個數(shù)小于512個,列表每個元素的值都小于64字節(jié)(默認),使用ziplist編碼,否則使用linkedlist編碼

  • Hash:哈希類型元素個數(shù)小于512個,所有值小于64字節(jié)的話,使用ziplist編碼,否則使用hashtable編碼。

  • Set:如果集合中的元素都是整數(shù)且元素個數(shù)小于512個,使用intset編碼,否則使用hashtable編碼。

  • Zset:當有序集合的元素個數(shù)小于128個,每個元素的值小于64字節(jié)時,使用ziplist編碼,否則使用skiplist(跳躍表)編碼

3.4 合理的線程模型

I/O 多路復用

I/O 多路復用

多路I/O復用技術可以讓單個線程高效的處理多個連接請求,而Redis使用用epoll作為I/O多路復用技術的實現(xiàn)。并且,Redis自身的事件處理模型將epoll中的連接、讀寫、關閉都轉換為事件,不在網絡I/O上浪費過多的時間。

什么是I/O多路復用?

  • I/O :網絡 I/O

  • 多路 :多個網絡連接

  • 復用:復用同一個線程。

  • IO多路復用其實就是一種同步IO模型,它實現(xiàn)了一個線程可以監(jiān)視多個文件句柄;一旦某個文件句柄就緒,就能夠通知應用程序進行相應的讀寫操作;而沒有文件句柄就緒時,就會阻塞應用程序,交出cpu。

單線程模型

  • Redis是單線程模型的,而單線程避免了CPU不必要的上下文切換和競爭鎖的消耗。也正因為是單線程,如果某個命令執(zhí)行過長(如hgetall命令),會造成阻塞。Redis是面向快速執(zhí)行場景的數(shù)據(jù)庫。,所以要慎用如smembers和lrange、hgetall等命令。

  • Redis 6.0 引入了多線程提速,它的執(zhí)行命令操作內存的仍然是個單線程。

3.5 虛擬內存機制

Redis直接自己構建了VM機制 ,不會像一般的系統(tǒng)會調用系統(tǒng)函數(shù)處理,會浪費一定的時間去移動和請求。

Redis的虛擬內存機制是啥呢?

虛擬內存機制就是暫時把不經常訪問的數(shù)據(jù)(冷數(shù)據(jù))從內存交換到磁盤中,從而騰出寶貴的內存空間用于其它需要訪問的數(shù)據(jù)(熱數(shù)據(jù))。通過VM功能可以實現(xiàn)冷熱數(shù)據(jù)分離,使熱數(shù)據(jù)仍在內存中、冷數(shù)據(jù)保存到磁盤。這樣就可以避免因為內存不足而造成訪問速度下降的問題。

4. 什么是緩存擊穿、緩存穿透、緩存雪崩?

4.1 緩存穿透問題

先來看一個常見的緩存使用方式:讀請求來了,先查下緩存,緩存有值命中,就直接返回;緩存沒命中,就去查數(shù)據(jù)庫,然后把數(shù)據(jù)庫的值更新到緩存,再返回。

讀取緩存

緩存穿透:指查詢一個一定不存在的數(shù)據(jù),由于緩存是不命中時需要從數(shù)據(jù)庫查詢,查不到數(shù)據(jù)則不寫入緩存,這將導致這個不存在的數(shù)據(jù)每次請求都要到數(shù)據(jù)庫去查詢,進而給數(shù)據(jù)庫帶來壓力。

通俗點說,讀請求訪問時,緩存和數(shù)據(jù)庫都沒有某個值,這樣就會導致每次對這個值的查詢請求都會穿透到數(shù)據(jù)庫,這就是緩存穿透。

緩存穿透一般都是這幾種情況產生的:

  • 業(yè)務不合理的設計,比如大多數(shù)用戶都沒開守護,但是你的每個請求都去緩存,查詢某個userid查詢有沒有守護。

  • 業(yè)務/運維/開發(fā)失誤的操作,比如緩存和數(shù)據(jù)庫的數(shù)據(jù)都被誤刪除了。

  • 黑客非法請求攻擊,比如黑客故意捏造大量非法請求,以讀取不存在的業(yè)務數(shù)據(jù)。

如何避免緩存穿透呢? 一般有三種方法。

  • 1.如果是非法請求,我們在API入口,對參數(shù)進行校驗,過濾非法值。

  • 2.如果查詢數(shù)據(jù)庫為空,我們可以給緩存設置個空值,或者默認值。但是如有有寫請求進來的話,需要更新緩存哈,以保證緩存一致性,同時,最后給緩存設置適當?shù)倪^期時間。(業(yè)務上比較常用,簡單有效)

  • 3.使用布隆過濾器快速判斷數(shù)據(jù)是否存在。即一個查詢請求過來時,先通過布隆過濾器判斷值是否存在,存在才繼續(xù)往下查。

布隆過濾器原理:它由初始值為0的位圖數(shù)組和N個哈希函數(shù)組成。一個對一個key進行N個hash算法獲取N個值,在比特數(shù)組中將這N個值散列后設定為1,然后查的時候如果特定的這幾個位置都為1,那么布隆過濾器判斷該key存在。

4.2 緩存雪奔問題

緩存雪奔: 指緩存中數(shù)據(jù)大批量到過期時間,而查詢數(shù)據(jù)量巨大,請求都直接訪問數(shù)據(jù)庫,引起數(shù)據(jù)庫壓力過大甚至down機。

  • 緩存雪奔一般是由于大量數(shù)據(jù)同時過期造成的,對于這個原因,可通過均勻設置過期時間解決,即讓過期時間相對離散一點。如采用一個較大固定值+一個較小的隨機值,5小時+0到1800秒醬紫。

  • Redis 故障宕機也可能引起緩存雪奔。這就需要構造Redis高可用集群啦。

4.3 緩存擊穿問題

緩存擊穿: 指熱點key在某個時間點過期的時候,而恰好在這個時間點對這個Key有大量的并發(fā)請求過來,從而大量的請求打到db。

緩存擊穿看著有點像,其實它兩區(qū)別是,緩存雪奔是指數(shù)據(jù)庫壓力過大甚至down機,緩存擊穿只是大量并發(fā)請求到了DB數(shù)據(jù)庫層面。可以認為擊穿是緩存雪奔的一個子集吧。有些文章認為它倆區(qū)別,是區(qū)別在于擊穿針對某一熱點key緩存,雪奔則是很多key。

解決方案就有兩種:

  • 1.使用互斥鎖方案。緩存失效時,不是立即去加載db數(shù)據(jù),而是先使用某些帶成功返回的原子操作命令,如(Redis的setnx)去操作,成功的時候,再去加載db數(shù)據(jù)庫數(shù)據(jù)和設置緩存。否則就去重試獲取緩存。

  • 2. “永不過期”,是指沒有設置過期時間,但是熱點數(shù)據(jù)快要過期時,異步線程去更新和設置過期時間。

5. 什么是熱Key問題,如何解決熱key問題

什么是熱Key呢?在Redis中,我們把訪問頻率高的key,稱為熱點key。

如果某一熱點key的請求到服務器主機時,由于請求量特別大,可能會導致主機資源不足,甚至宕機,從而影響正常的服務。

而熱點Key是怎么產生的呢?主要原因有兩個:

  • 用戶消費的數(shù)據(jù)遠大于生產的數(shù)據(jù),如秒殺、熱點新聞等讀多寫少的場景。

  • 請求分片集中,超過單Redi服務器的性能,比如固定名稱key,Hash落入同一臺服務器,瞬間訪問量極大,超過機器瓶頸,產生熱點Key問題。

那么在日常開發(fā)中,如何識別到熱點key呢?

  • 憑經驗判斷哪些是熱Key;

  • 客戶端統(tǒng)計上報;

  • 服務代理層上報

如何解決熱key問題?

  • Redis集群擴容:增加分片副本,均衡讀流量;

  • 將熱key分散到不同的服務器中;

  • 使用二級緩存,即JVM本地緩存,減少Redis的讀請求。

6. Redis 過期策略和內存淘汰策略

6.1 Redis的過期策略

我們在set key的時候,可以給它設置一個過期時間,比如expire key 60。指定這key60s后過期,60s后,redis是如何處理的嘛?我們先來介紹幾種過期策略:

定時過期

每個設置過期時間的key都需要創(chuàng)建一個定時器,到過期時間就會立即對key進行清除。該策略可以立即清除過期的數(shù)據(jù),對內存很友好;但是會占用大量的CPU資源去處理過期的數(shù)據(jù),從而影響緩存的響應時間和吞吐量。

惰性過期

只有當訪問一個key時,才會判斷該key是否已過期,過期則清除。該策略可以最大化地節(jié)省CPU資源,卻對內存非常不友好。極端情況可能出現(xiàn)大量的過期key沒有再次被訪問,從而不會被清除,占用大量內存。

定期過期

每隔一定的時間,會掃描一定數(shù)量的數(shù)據(jù)庫的expires字典中一定數(shù)量的key,并清除其中已過期的key。該策略是前兩者的一個折中方案。通過調整定時掃描的時間間隔和每次掃描的限定耗時,可以在不同情況下使得CPU和內存資源達到最優(yōu)的平衡效果。

expires字典會保存所有設置了過期時間的key的過期時間數(shù)據(jù),其中,key是指向鍵空間中的某個鍵的指針,value是該鍵的毫秒精度的UNIX時間戳表示的過期時間。鍵空間是指該Redis集群中保存的所有鍵。

Redis中同時使用了惰性過期和定期過期兩種過期策略。

  • 假設Redis當前存放30萬個key,并且都設置了過期時間,如果你每隔100ms就去檢查這全部的key,CPU負載會特別高,最后可能會掛掉。

  • 因此,redis采取的是定期過期,每隔100ms就隨機抽取一定數(shù)量的key來檢查和刪除的。

  • 但是呢,最后可能會有很多已經過期的key沒被刪除。這時候,redis采用惰性刪除。在你獲取某個key的時候,redis會檢查一下,這個key如果設置了過期時間并且已經過期了,此時就會刪除。

但是呀,如果定期刪除漏掉了很多過期的key,然后也沒走惰性刪除。就會有很多過期key積在內存內存,直接會導致內存爆的?;蛘哂行r候,業(yè)務量大起來了,redis的key被大量使用,內存直接不夠了,運維小哥哥也忘記加大內存了。難道redis直接這樣掛掉?不會的!Redis用8種內存淘汰策略保護自己~

6.2 Redis 內存淘汰策略

  • volatile-lru:當內存不足以容納新寫入數(shù)據(jù)時,從設置了過期時間的key中使用LRU(最近最少使用)算法進行淘汰;

  • allkeys-lru:當內存不足以容納新寫入數(shù)據(jù)時,從所有key中使用LRU(最近最少使用)算法進行淘汰。

  • volatile-lfu:4.0版本新增,當內存不足以容納新寫入數(shù)據(jù)時,在過期的key中,使用LFU算法進行刪除key。

  • allkeys-lfu:4.0版本新增,當內存不足以容納新寫入數(shù)據(jù)時,從所有key中使用LFU算法進行淘汰;

  • volatile-random:當內存不足以容納新寫入數(shù)據(jù)時,從設置了過期時間的key中,隨機淘汰數(shù)據(jù);。

  • allkeys-random:當內存不足以容納新寫入數(shù)據(jù)時,從所有key中隨機淘汰數(shù)據(jù)。

  • volatile-ttl:當內存不足以容納新寫入數(shù)據(jù)時,在設置了過期時間的key中,根據(jù)過期時間進行淘汰,越早過期的優(yōu)先被淘汰;

  • noeviction:默認策略,當內存不足以容納新寫入數(shù)據(jù)時,新寫入操作會報錯。

7.說說Redis的常用應用場景

  • 緩存

  • 排行榜

  • 計數(shù)器應用

  • 共享Session

  • 分布式鎖

  • 社交網絡

  • 消息隊列

  • 位操作

7.1 緩存

我們一提到redis,自然而然就想到緩存,國內外中大型的網站都離不開緩存。合理的利用緩存,比如緩存熱點數(shù)據(jù),不僅可以提升網站的訪問速度,還可以降低數(shù)據(jù)庫DB的壓力。并且,Redis相比于memcached,還提供了豐富的數(shù)據(jù)結構,并且提供RDB和AOF等持久化機制,強的一批。

7.2 排行榜

當今互聯(lián)網應用,有各種各樣的排行榜,如電商網站的月度銷量排行榜、社交APP的禮物排行榜、小程序的投票排行榜等等。Redis提供的zset數(shù)據(jù)類型能夠實現(xiàn)這些復雜的排行榜。

比如,用戶每天上傳視頻,獲得點贊的排行榜可以這樣設計:

  • 1.用戶Jay上傳一個視頻,獲得6個贊,可以醬紫:

zadd?user:ranking:2021-03-03?Jay?3
  • 2.過了一段時間,再獲得一個贊,可以這樣:

zincrby?user:ranking:2021-03-03?Jay?1
  • 3.如果某個用戶John作弊,需要刪除該用戶:

zrem?user:ranking:2021-03-03?John
  • 4.展示獲取贊數(shù)最多的3個用戶

zrevrangebyrank?user:ranking:2021-03-03?0?2

7.3 計數(shù)器應用

各大網站、APP應用經常需要計數(shù)器的功能,如短視頻的播放數(shù)、電商網站的瀏覽數(shù)。這些播放數(shù)、瀏覽數(shù)一般要求實時的,每一次播放和瀏覽都要做加1的操作,如果并發(fā)量很大對于傳統(tǒng)關系型數(shù)據(jù)的性能是一種挑戰(zhàn)。Redis天然支持計數(shù)功能而且計數(shù)的性能也非常好,可以說是計數(shù)器系統(tǒng)的重要選擇。

7.4 共享Session

如果一個分布式Web服務將用戶的Session信息保存在各自服務器,用戶刷新一次可能就需要重新登錄了,這樣顯然有問題。實際上,可以使用Redis將用戶的Session進行集中管理,每次用戶更新或者查詢登錄信息都直接從Redis中集中獲取。

7.5 分布式鎖

幾乎每個互聯(lián)網公司中都使用了分布式部署,分布式服務下,就會遇到對同一個資源的并發(fā)訪問的技術難題,如秒殺、下單減庫存等場景。

  • 用synchronize或者reentrantlock本地鎖肯定是不行的。

  • 如果是并發(fā)量不大話,使用數(shù)據(jù)庫的悲觀鎖、樂觀鎖來實現(xiàn)沒啥問題。

  • 但是在并發(fā)量高的場合中,利用數(shù)據(jù)庫鎖來控制資源的并發(fā)訪問,會影響數(shù)據(jù)庫的性能。

  • 實際上,可以用Redis的setnx來實現(xiàn)分布式的鎖。

7.6 社交網絡

贊/踩、粉絲、共同好友/喜好、推送、下拉刷新等是社交網站的必備功能,由于社交網站訪問量通常比較大,而且傳統(tǒng)的關系型數(shù)據(jù)不太適保存 這種類型的數(shù)據(jù),Redis提供的數(shù)據(jù)結構可以相對比較容易地實現(xiàn)這些功能。

7.7 消息隊列

消息隊列是大型網站必用中間件,如ActiveMQ、RabbitMQ、Kafka等流行的消息隊列中間件,主要用于業(yè)務解耦、流量削峰及異步處理實時性低的業(yè)務。Redis提供了發(fā)布/訂閱及阻塞隊列功能,能實現(xiàn)一個簡單的消息隊列系統(tǒng)。另外,這個不能和專業(yè)的消息中間件相比。

7.8 位操作

用于數(shù)據(jù)量上億的場景下,例如幾億用戶系統(tǒng)的簽到,去重登錄次數(shù)統(tǒng)計,某用戶是否在線狀態(tài)等等。騰訊10億用戶,要幾個毫秒內查詢到某個用戶是否在線,能怎么做?千萬別說給每個用戶建立一個key,然后挨個記(你可以算一下需要的內存會很恐怖,而且這種類似的需求很多。這里要用到位操作——使用setbit、getbit、bitcount命令。原理是:redis內構建一個足夠長的數(shù)組,每個數(shù)組元素只能是0和1兩個值,然后這個數(shù)組的下標index用來表示用戶id(必須是數(shù)字哈),那么很顯然,這個幾億長的大數(shù)組就能通過下標和元素值(0和1)來構建一個記憶系統(tǒng)。

8. Redis 的持久化機制有哪些?優(yōu)缺點說說

Redis是基于內存的非關系型K-V數(shù)據(jù)庫,既然它是基于內存的,如果Redis服務器掛了,數(shù)據(jù)就會丟失。為了避免數(shù)據(jù)丟失了,Redis提供了持久化,即把數(shù)據(jù)保存到磁盤。

Redis提供了RDB和AOF兩種持久化機制,它持久化文件加載流程如下:

8.1 RDB

RDB,就是把內存數(shù)據(jù)以快照的形式保存到磁盤上。

什么是快照?可以這樣理解,給當前時刻的數(shù)據(jù),拍一張照片,然后保存下來。

RDB持久化,是指在指定的時間間隔內,執(zhí)行指定次數(shù)的寫操作,將內存中的數(shù)據(jù)集快照寫入磁盤中,它是Redis默認的持久化方式。執(zhí)行完操作后,在指定目錄下會生成一個dump.rdb文件,Redis 重啟的時候,通過加載dump.rdb文件來恢復數(shù)據(jù)。RDB觸發(fā)機制主要有以下幾種:

RDB 的優(yōu)點

  • 適合大規(guī)模的數(shù)據(jù)恢復場景,如備份,全量復制等

RDB缺點

  • 沒辦法做到實時持久化/秒級持久化。

  • 新老版本存在RDB格式兼容問題

AOF

AOF(append only file) 持久化,采用日志的形式來記錄每個寫操作,追加到文件中,重啟時再重新執(zhí)行AOF文件中的命令來恢復數(shù)據(jù)。它主要解決數(shù)據(jù)持久化的實時性問題。默認是不開啟的。

AOF的工作流程如下:

AOF的優(yōu)點

  • 數(shù)據(jù)的一致性和完整性更高

AOF的缺點

  • AOF記錄的內容越多,文件越大,數(shù)據(jù)恢復變慢。

9.怎么實現(xiàn)Redis的高可用?

我們在項目中使用Redis,肯定不會是單點部署Redis服務的。因為,單點部署一旦宕機,就不可用了。為了實現(xiàn)高可用,通常的做法是,將數(shù)據(jù)庫復制多個副本以部署在不同的服務器上,其中一臺掛了也可以繼續(xù)提供服務。Redis 實現(xiàn)高可用有三種部署模式:主從模式,哨兵模式,集群模式

9.1 主從模式

主從模式中,Redis部署了多臺機器,有主節(jié)點,負責讀寫操作,有從節(jié)點,只負責讀操作。從節(jié)點的數(shù)據(jù)來自主節(jié)點,實現(xiàn)原理就是主從復制機制

主從復制包括全量復制,增量復制兩種。一般當slave第一次啟動連接master,或者認為是第一次連接,就采用全量復制,全量復制流程如下:

  • 1.slave發(fā)送sync命令到master。

  • 2.master接收到SYNC命令后,執(zhí)行bgsave命令,生成RDB全量文件。

  • 3.master使用緩沖區(qū),記錄RDB快照生成期間的所有寫命令。

  • 4.master執(zhí)行完bgsave后,向所有slave發(fā)送RDB快照文件。

  • 5.slave收到RDB快照文件后,載入、解析收到的快照。

  • 6.master使用緩沖區(qū),記錄RDB同步期間生成的所有寫的命令。

  • 7.master快照發(fā)送完畢后,開始向slave發(fā)送緩沖區(qū)中的寫命令;

  • 8.salve接受命令請求,并執(zhí)行來自master緩沖區(qū)的寫命令

redis2.8版本之后,已經使用psync來替代sync,因為sync命令非常消耗系統(tǒng)資源,psync的效率更高。

slave與master全量同步之后,master上的數(shù)據(jù),如果再次發(fā)生更新,就會觸發(fā)增量復制

當master節(jié)點發(fā)生數(shù)據(jù)增減時,就會觸發(fā)replicationFeedSalves()函數(shù),接下來在 Master節(jié)點上調用的每一個命令會使用replicationFeedSlaves()來同步到Slave節(jié)點。執(zhí)行此函數(shù)之前呢,master節(jié)點會判斷用戶執(zhí)行的命令是否有數(shù)據(jù)更新,如果有數(shù)據(jù)更新的話,并且slave節(jié)點不為空,就會執(zhí)行此函數(shù)。這個函數(shù)作用就是:把用戶執(zhí)行的命令發(fā)送到所有的slave節(jié)點,讓slave節(jié)點執(zhí)行。流程如下:

9.2 哨兵模式

主從模式中,一旦主節(jié)點由于故障不能提供服務,需要人工將從節(jié)點晉升為主節(jié)點,同時還要通知應用方更新主節(jié)點地址。顯然,多數(shù)業(yè)務場景都不能接受這種故障處理方式。Redis從2.8開始正式提供了Redis Sentinel(哨兵)架構來解決這個問題。

哨兵模式,由一個或多個Sentinel實例組成的Sentinel系統(tǒng),它可以監(jiān)視所有的Redis主節(jié)點和從節(jié)點,并在被監(jiān)視的主節(jié)點進入下線狀態(tài)時,自動將下線主服務器屬下的某個從節(jié)點升級為新的主節(jié)點。但是呢,一個哨兵進程對Redis節(jié)點進行監(jiān)控,就可能會出現(xiàn)問題(單點問題),因此,可以使用多個哨兵來進行監(jiān)控Redis節(jié)點,并且各個哨兵之間還會進行監(jiān)控。

Sentinel哨兵模式

簡單來說,哨兵模式就三個作用:

  • 發(fā)送命令,等待Redis服務器(包括主服務器和從服務器)返回監(jiān)控其運行狀態(tài);

  • 哨兵監(jiān)測到主節(jié)點宕機,會自動將從節(jié)點切換成主節(jié)點,然后通過發(fā)布訂閱模式通知其他的從節(jié)點,修改配置文件,讓它們切換主機;

  • 哨兵之間還會相互監(jiān)控,從而達到高可用。

故障切換的過程是怎樣的呢

假設主服務器宕機,哨兵1先檢測到這個結果,系統(tǒng)并不會馬上進行 failover 過程,僅僅是哨兵1主觀的認為主服務器不可用,這個現(xiàn)象成為主觀下線。當后面的哨兵也檢測到主服務器不可用,并且數(shù)量達到一定值時,那么哨兵之間就會進行一次投票,投票的結果由一個哨兵發(fā)起,進行 failover 操作。切換成功后,就會通過發(fā)布訂閱模式,讓各個哨兵把自己監(jiān)控的從服務器實現(xiàn)切換主機,這個過程稱為客觀下線。這樣對于客戶端而言,一切都是透明的。

哨兵的工作模式如下:

  • 每個Sentinel以每秒鐘一次的頻率向它所知的Master,Slave以及其他Sentinel實例發(fā)送一個 PING命令。

  • 如果一個實例(instance)距離最后一次有效回復 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個實例會被 Sentinel標記為主觀下線。

  • 如果一個Master被標記為主觀下線,則正在監(jiān)視這個Master的所有 Sentinel 要以每秒一次的頻率確認Master的確進入了主觀下線狀態(tài)。

  • 當有足夠數(shù)量的 Sentinel(大于等于配置文件指定的值)在指定的時間范圍內確認Master的確進入了主觀下線狀態(tài), 則Master會被標記為客觀下線。

  • 在一般情況下, 每個 Sentinel 會以每10秒一次的頻率向它已知的所有Master,Slave發(fā)送 INFO 命令。

  • 當Master被 Sentinel 標記為客觀下線時,Sentinel 向下線的 Master 的所有 Slave 發(fā)送 INFO 命令的頻率會從 10 秒一次改為每秒一次

  • 若沒有足夠數(shù)量的 Sentinel同意Master已經下線, Master的客觀下線狀態(tài)就會被移除;若Master 重新向 Sentinel 的 PING 命令返回有效回復, Master 的主觀下線狀態(tài)就會被移除。

  • 9.3 Cluster集群模式

    哨兵模式基于主從模式,實現(xiàn)讀寫分離,它還可以自動切換,系統(tǒng)可用性更高。但是它每個節(jié)點存儲的數(shù)據(jù)是一樣的,浪費內存,并且不好在線擴容。因此,Cluster集群應運而生,它在Redis3.0加入的,實現(xiàn)了Redis的分布式存儲。對數(shù)據(jù)進行分片,也就是說每臺Redis節(jié)點上存儲不同的內容,來解決在線擴容的問題。并且,它也提供復制和故障轉移的功能。

    Cluster集群節(jié)點的通訊

    一個Redis集群由多個節(jié)點組成,各個節(jié)點之間是怎么通信的呢?通過Gossip協(xié)議

    Redis Cluster集群通過Gossip協(xié)議進行通信,節(jié)點之前不斷交換信息,交換的信息內容包括節(jié)點出現(xiàn)故障、新節(jié)點加入、主從節(jié)點變更信息、slot信息等等。常用的Gossip消息分為4種,分別是:ping、pong、meet、fail。

    • meet消息:通知新節(jié)點加入。消息發(fā)送者通知接收者加入到當前集群,meet消息通信正常完成后,接收節(jié)點會加入到集群中并進行周期性的ping、pong消息交換。

    • ping消息:集群內交換最頻繁的消息,集群內每個節(jié)點每秒向多個其他節(jié)點發(fā)送ping消息,用于檢測節(jié)點是否在線和交換彼此狀態(tài)信息。

    • pong消息:當接收到ping、meet消息時,作為響應消息回復給發(fā)送方確認消息正常通信。pong消息內部封裝了自身狀態(tài)數(shù)據(jù)。節(jié)點也可以向集群內廣播自身的pong消息來通知整個集群對自身狀態(tài)進行更新。

    • fail消息:當節(jié)點判定集群內另一個節(jié)點下線時,會向集群內廣播一個fail消息,其他節(jié)點接收到fail消息之后把對應節(jié)點更新為下線狀態(tài)。

    特別的,每個節(jié)點是通過集群總線(cluster bus) 與其他的節(jié)點進行通信的。通訊時,使用特殊的端口號,即對外服務端口號加10000。例如如果某個node的端口號是6379,那么它與其它nodes通信的端口號是 16379。nodes 之間的通信采用特殊的二進制協(xié)議。

    Hash Slot插槽算法

    既然是分布式存儲,Cluster集群使用的分布式算法是一致性Hash嘛?并不是,而是Hash Slot插槽算法

    插槽算法把整個數(shù)據(jù)庫被分為16384個slot(槽),每個進入Redis的鍵值對,根據(jù)key進行散列,分配到這16384插槽中的一個。使用的哈希映射也比較簡單,用CRC16算法計算出一個16 位的值,再對16384取模。數(shù)據(jù)庫中的每個鍵都屬于這16384個槽的其中一個,集群中的每個節(jié)點都可以處理這16384個槽。

    集群中的每個節(jié)點負責一部分的hash槽,比如當前集群有A、B、C個節(jié)點,每個節(jié)點上的哈希槽數(shù) =16384/3,那么就有:

    • 節(jié)點A負責0~5460號哈希槽

    • 節(jié)點B負責5461~10922號哈希槽

    • 節(jié)點C負責10923~16383號哈希槽

    Redis Cluster集群

    Redis Cluster集群中,需要確保16384個槽對應的node都正常工作,如果某個node出現(xiàn)故障,它負責的slot也會失效,整個集群將不能工作。

    因此為了保證高可用,Cluster集群引入了主從復制,一個主節(jié)點對應一個或者多個從節(jié)點。當其它主節(jié)點 ping 一個主節(jié)點 A 時,如果半數(shù)以上的主節(jié)點與 A 通信超時,那么認為主節(jié)點 A 宕機了。如果主節(jié)點宕機時,就會啟用從節(jié)點。

    在Redis的每一個節(jié)點上,都有兩個玩意,一個是插槽(slot),它的取值范圍是0~16383。另外一個是cluster,可以理解為一個集群管理的插件。當我們存取的key到達時,Redis 會根據(jù)CRC16算法得出一個16 bit的值,然后把結果對16384取模。醬紫每個key都會對應一個編號在 0~16383 之間的哈希槽,通過這個值,去找到對應的插槽所對應的節(jié)點,然后直接自動跳轉到這個對應的節(jié)點上進行存取操作。

    雖然數(shù)據(jù)是分開存儲在不同節(jié)點上的,但是對客戶端來說,整個集群Cluster,被看做一個整體??蛻舳硕诉B接任意一個node,看起來跟操作單實例的Redis一樣。當客戶端操作的key沒有被分配到正確的node節(jié)點時,Redis會返回轉向指令,最后指向正確的node,這就有點像瀏覽器頁面的302 重定向跳轉。

    故障轉移

    Redis集群實現(xiàn)了高可用,當集群內節(jié)點出現(xiàn)故障時,通過故障轉移,以保證集群正常對外提供服務。

    redis集群通過ping/pong消息,實現(xiàn)故障發(fā)現(xiàn)。這個環(huán)境包括主觀下線和客觀下線。

    主觀下線: 某個節(jié)點認為另一個節(jié)點不可用,即下線狀態(tài),這個狀態(tài)并不是最終的故障判定,只能代表一個節(jié)點的意見,可能存在誤判情況。

    主觀下線

    客觀下線: 指標記一個節(jié)點真正的下線,集群內多個節(jié)點都認為該節(jié)點不可用,從而達成共識的結果。如果是持有槽的主節(jié)點故障,需要為該節(jié)點進行故障轉移。

    • 假如節(jié)點A標記節(jié)點B為主觀下線,一段時間后,節(jié)點A通過消息把節(jié)點B的狀態(tài)發(fā)到其它節(jié)點,當節(jié)點C接受到消息并解析出消息體時,如果發(fā)現(xiàn)節(jié)點B的pfail狀態(tài)時,會觸發(fā)客觀下線流程;

    • 當下線為主節(jié)點時,此時Redis Cluster集群為統(tǒng)計持有槽的主節(jié)點投票,看投票數(shù)是否達到一半,當下線報告統(tǒng)計數(shù)大于一半時,被標記為客觀下線狀態(tài)。

    流程如下:

    客觀下線

    故障恢復:故障發(fā)現(xiàn)后,如果下線節(jié)點的是主節(jié)點,則需要在它的從節(jié)點中選一個替換它,以保證集群的高可用。流程如下:

    • 資格檢查:檢查從節(jié)點是否具備替換故障主節(jié)點的條件。

    • 準備選舉時間:資格檢查通過后,更新觸發(fā)故障選舉時間。

    • 發(fā)起選舉:到了故障選舉時間,進行選舉。

    • 選舉投票:只有持有槽的主節(jié)點才有票,從節(jié)點收集到足夠的選票(大于一半),觸發(fā)替換主節(jié)點操作

    10. 使用過Redis分布式鎖嘛?有哪些注意點呢?

    分布式鎖,是控制分布式系統(tǒng)不同進程共同訪問共享資源的一種鎖的實現(xiàn)。秒殺下單、搶紅包等等業(yè)務場景,都需要用到分布式鎖,我們項目中經常使用Redis作為分布式鎖。

    選了Redis分布式鎖的幾種實現(xiàn)方法,大家來討論下,看有沒有啥問題哈。

    • 命令setnx + expire分開寫

    • setnx + value值是過期時間

    • set的擴展命令(set ex px nx)

    • set ex px nx + 校驗唯一隨機值,再刪除

    10.1 命令setnx + expire分開寫

    if(jedis.setnx(key,lock_value)?==?1){?//加鎖expire(key,100);?//設置過期時間try?{do?something??//業(yè)務請求}catch(){}finally?{jedis.del(key);?//釋放鎖} }

    如果執(zhí)行完setnx加鎖,正要執(zhí)行expire設置過期時間時,進程crash掉或者要重啟維護了,那這個鎖就“長生不老”了,別的線程永遠獲取不到鎖啦,所以分布式鎖不能這么實現(xiàn)。

    10.2 setnx + value值是過期時間

    long?expires?=?System.currentTimeMillis()?+?expireTime;?//系統(tǒng)時間+設置的過期時間 String?expiresStr?=?String.valueOf(expires);//?如果當前鎖不存在,返回加鎖成功 if?(jedis.setnx(key,?expiresStr)?==?1)?{return?true; }? //?如果鎖已經存在,獲取鎖的過期時間 String?currentValueStr?=?jedis.get(key);//?如果獲取到的過期時間,小于系統(tǒng)當前時間,表示已經過期 if?(currentValueStr?!=?null?&&?Long.parseLong(currentValueStr)?<?System.currentTimeMillis())?{//?鎖已過期,獲取上一個鎖的過期時間,并設置現(xiàn)在鎖的過期時間(不了解redis的getSet命令的小伙伴,可以去官網看下哈)String?oldValueStr?=?jedis.getSet(key_resource_id,?expiresStr);if?(oldValueStr?!=?null?&&?oldValueStr.equals(currentValueStr))?{//?考慮多線程并發(fā)的情況,只有一個線程的設置值和當前值相同,它才可以加鎖return?true;} }//其他情況,均返回加鎖失敗 return?false; }

    筆者看過有開發(fā)小伙伴是這么實現(xiàn)分布式鎖的,但是這種方案也有這些缺點

    • 過期時間是客戶端自己生成的,分布式環(huán)境下,每個客戶端的時間必須同步。

    • 沒有保存持有者的唯一標識,可能被別的客戶端釋放/解鎖。

    • 鎖過期的時候,并發(fā)多個客戶端同時請求過來,都執(zhí)行了jedis.getSet(),最終只能有一個客戶端加鎖成功,但是該客戶端鎖的過期時間,可能被別的客戶端覆蓋。

    10.3:set的擴展命令(set ex px nx)(注意可能存在的問題)

    if(jedis.set(key,?lock_value,?"NX",?"EX",?100s)?==?1){?//加鎖try?{do?something??//業(yè)務處理}catch(){}finally?{jedis.del(key);?//釋放鎖} }

    這個方案可能存在這樣的問題:

    • 鎖過期釋放了,業(yè)務還沒執(zhí)行完。

    • 鎖被別的線程誤刪。

    10.4 set ex px nx + 校驗唯一隨機值,再刪除

    if(jedis.set(key,?uni_request_id,?"NX",?"EX",?100s)?==?1){?//加鎖try?{do?something??//業(yè)務處理}catch(){}finally?{//判斷是不是當前線程加的鎖,是才釋放if?(uni_request_id.equals(jedis.get(key)))?{jedis.del(key);?//釋放鎖}} }

    在這里,判斷當前線程加的鎖和釋放鎖是不是一個原子操作。如果調用jedis.del()釋放鎖的時候,可能這把鎖已經不屬于當前客戶端,會解除他人加的鎖。

    一般也是用lua腳本代替。lua腳本如下:

    if?redis.call('get',KEYS[1])?==?ARGV[1]?then?return?redis.call('del',KEYS[1])? elsereturn?0 end;

    這種方式比較不錯了,一般情況下,已經可以使用這種實現(xiàn)方式。但是存在鎖過期釋放了,業(yè)務還沒執(zhí)行完的問題(實際上,估算個業(yè)務處理的時間,一般沒啥問題了)。

    11. 使用過Redisson嘛?說說它的原理

    分布式鎖可能存在鎖過期釋放,業(yè)務沒執(zhí)行完的問題。有些小伙伴認為,稍微把鎖過期時間設置長一些就可以啦。其實我們設想一下,是否可以給獲得鎖的線程,開啟一個定時守護線程,每隔一段時間檢查鎖是否還存在,存在則對鎖的過期時間延長,防止鎖過期提前釋放。

    當前開源框架Redisson就解決了這個分布式鎖問題。我們一起來看下Redisson底層原理是怎樣的吧:

    只要線程一加鎖成功,就會啟動一個watch dog看門狗,它是一個后臺線程,會每隔10秒檢查一下,如果線程1還持有鎖,那么就會不斷的延長鎖key的生存時間。因此,Redisson就是使用Redisson解決了鎖過期釋放,業(yè)務沒執(zhí)行完問題。

    12. 什么是Redlock算法

    Redis一般都是集群部署的,假設數(shù)據(jù)在主從同步過程,主節(jié)點掛了,Redis分布式鎖可能會有哪些問題呢?一起來看些這個流程圖:

    如果線程一在Redis的master節(jié)點上拿到了鎖,但是加鎖的key還沒同步到slave節(jié)點。恰好這時,master節(jié)點發(fā)生故障,一個slave節(jié)點就會升級為master節(jié)點。線程二就可以獲取同個key的鎖啦,但線程一也已經拿到鎖了,鎖的安全性就沒了。

    為了解決這個問題,Redis作者 antirez提出一種高級的分布式鎖算法:Redlock。Redlock核心思想是這樣的:

    搞多個Redis master部署,以保證它們不會同時宕掉。并且這些master節(jié)點是完全相互獨立的,相互之間不存在數(shù)據(jù)同步。同時,需要確保在這多個master實例上,是與在Redis單實例,使用相同方法來獲取和釋放鎖。

    我們假設當前有5個Redis master節(jié)點,在5臺服務器上面運行這些Redis實例。

    RedLock的實現(xiàn)步驟:如下

    • 1.獲取當前時間,以毫秒為單位。

    • 2.按順序向5個master節(jié)點請求加鎖??蛻舳嗽O置網絡連接和響應超時時間,并且超時時間要小于鎖的失效時間。(假設鎖自動失效時間為10秒,則超時時間一般在5-50毫秒之間,我們就假設超時時間是50ms吧)。如果超時,跳過該master節(jié)點,盡快去嘗試下一個master節(jié)點。

    • 3.客戶端使用當前時間減去開始獲取鎖時間(即步驟1記錄的時間),得到獲取鎖使用的時間。當且僅當超過一半(N/2+1,這里是5/2+1=3個節(jié)點)的Redis master節(jié)點都獲得鎖,并且使用的時間小于鎖失效時間時,鎖才算獲取成功。(如上圖,10s> 30ms+40ms+50ms+4m0s+50ms)

    • 如果取到了鎖,key的真正有效時間就變啦,需要減去獲取鎖所使用的時間。

    • 如果獲取鎖失敗(沒有在至少N/2+1個master實例取到鎖,有或者獲取鎖時間已經超過了有效時間),客戶端要在所有的master節(jié)點上解鎖(即便有些master節(jié)點根本就沒有加鎖成功,也需要解鎖,以防止有些漏網之魚)。

    簡化下步驟就是:

    • 按順序向5個master節(jié)點請求加鎖

    • 根據(jù)設置的超時時間來判斷,是不是要跳過該master節(jié)點。

    • 如果大于等于三個節(jié)點加鎖成功,并且使用的時間小于鎖的有效期,即可認定加鎖成功啦。

    • 如果獲取鎖失敗,解鎖!

    13. Redis的跳躍表

    跳躍表
    • 跳躍表是有序集合zset的底層實現(xiàn)之一

    • 跳躍表支持平均O(logN),最壞 O(N)復雜度的節(jié)點查找,還可以通過順序性操作批量處理節(jié)點。

    • 跳躍表實現(xiàn)由zskiplist和zskiplistNode兩個結構組成,其中zskiplist用于保存跳躍表信息(如表頭節(jié)點、表尾節(jié)點、長度),而zskiplistNode則用于表示跳躍表節(jié)點。

    • 跳躍表就是在鏈表的基礎上,增加多級索引提升查找效率。

    14. MySQL與Redis 如何保證雙寫一致性

    • 緩存延時雙刪

    • 刪除緩存重試機制

    • 讀取biglog異步刪除緩存

    14.1 延時雙刪?

    什么是延時雙刪呢?流程圖如下:

    延時雙刪流程
  • 先刪除緩存

  • 再更新數(shù)據(jù)庫

  • 休眠一會(比如1秒),再次刪除緩存。

  • 這個休眠一會,一般多久呢?都是1秒?

    這個休眠時間 = ?讀業(yè)務邏輯數(shù)據(jù)的耗時 + 幾百毫秒。為了確保讀請求結束,寫請求可以刪除讀請求可能帶來的緩存臟數(shù)據(jù)。

    這種方案還算可以,只有休眠那一會(比如就那1秒),可能有臟數(shù)據(jù),一般業(yè)務也會接受的。但是如果第二次刪除緩存失敗呢?緩存和數(shù)據(jù)庫的數(shù)據(jù)還是可能不一致,對吧?給Key設置一個自然的expire過期時間,讓它自動過期怎樣?那業(yè)務要接受過期時間內,數(shù)據(jù)的不一致咯?還是有其他更佳方案呢?

    14.2 刪除緩存重試機制

    因為延時雙刪可能會存在第二步的刪除緩存失敗,導致的數(shù)據(jù)不一致問題。可以使用這個方案優(yōu)化:刪除失敗就多刪除幾次呀,保證刪除緩存成功就可以了呀~ 所以可以引入刪除緩存重試機制

    刪除緩存重試流程
  • 寫請求更新數(shù)據(jù)庫

  • 緩存因為某些原因,刪除失敗

  • 把刪除失敗的key放到消息隊列

  • 消費消息隊列的消息,獲取要刪除的key

  • 重試刪除緩存操作

  • 14.3 讀取biglog異步刪除緩存

    重試刪除緩存機制還可以吧,就是會造成好多業(yè)務代碼入侵。其實,還可以這樣優(yōu)化:通過數(shù)據(jù)庫的binlog來異步淘汰key。

    以mysql為例吧

    • 可以使用阿里的canal將binlog日志采集發(fā)送到MQ隊列里面

    • 然后通過ACK機制確認處理這條更新消息,刪除緩存,保證數(shù)據(jù)緩存一致性

    15. 為什么Redis 6.0 之后改多線程呢?

    • Redis6.0之前,Redis在處理客戶端的請求時,包括讀socket、解析、執(zhí)行、寫socket等都由一個順序串行的主線程處理,這就是所謂的“單線程”。

    • Redis6.0之前為什么一直不使用多線程?使用Redis時,幾乎不存在CPU成為瓶頸的情況, Redis主要受限于內存和網絡。例如在一個普通的Linux系統(tǒng)上,Redis通過使用pipelining每秒可以處理100萬個請求,所以如果應用程序主要使用O(N)或O(log(N))的命令,它幾乎不會占用太多CPU。

    redis使用多線程并非是完全摒棄單線程,redis還是使用單線程模型來處理客戶端的請求,只是使用多線程來處理數(shù)據(jù)的讀寫和協(xié)議解析,執(zhí)行命令還是使用單線程。

    這樣做的目的是因為redis的性能瓶頸在于網絡IO而非CPU,使用多線程能提升IO讀寫的效率,從而整體提高redis的性能。

    16. 聊聊Redis 事務機制

    Redis通過MULTI、EXEC、WATCH等一組命令集合,來實現(xiàn)事務機制。事務支持一次執(zhí)行多個命令,一個事務中所有命令都會被序列化。在事務執(zhí)行過程,會按照順序串行化執(zhí)行隊列中的命令,其他客戶端提交的命令請求不會插入到事務執(zhí)行命令序列中。

    簡言之,Redis事務就是順序性、一次性、排他性的執(zhí)行一個隊列中的一系列命令。

    Redis執(zhí)行事務的流程如下:

    • 開始事務(MULTI)

    • 命令入隊

    • 執(zhí)行事務(EXEC)、撤銷事務(DISCARD )

    命令描述
    EXEC執(zhí)行所有事務塊內的命令
    DISCARD取消事務,放棄執(zhí)行事務塊內的所有命令
    MULTI標記一個事務塊的開始
    UNWATCH取消 WATCH 命令對所有 key 的監(jiān)視。
    WATCH監(jiān)視key ,如果在事務執(zhí)行之前,該key 被其他命令所改動,那么事務將被打斷。

    17. Redis的Hash 沖突怎么辦

    Redis 作為一個K-V的內存數(shù)據(jù)庫,它使用用一張全局的哈希來保存所有的鍵值對。這張哈希表,有多個哈希桶組成,哈希桶中的entry元素保存了key和value指針,其中*key指向了實際的鍵,*value指向了實際的值。

    哈希表查找速率很快的,有點類似于Java中的HashMap,它讓我們在O(1) 的時間復雜度快速找到鍵值對。首先通過key計算哈希值,找到對應的哈希桶位置,然后定位到entry,在entry找到對應的數(shù)據(jù)。

    什么是哈希沖突?

    哈希沖突:通過不同的key,計算出一樣的哈希值,導致落在同一個哈希桶中。

    Redis為了解決哈希沖突,采用了鏈式哈希。鏈式哈希是指同一個哈希桶中,多個元素用一個鏈表來保存,它們之間依次用指針連接。

    有些讀者可能還會有疑問:哈希沖突鏈上的元素只能通過指針逐一查找再操作。當往哈希表插入數(shù)據(jù)很多,沖突也會越多,沖突鏈表就會越長,那查詢效率就會降低了。

    為了保持高效,Redis 會對哈希表做rehash操作,也就是增加哈希桶,減少沖突。為了rehash更高效,Redis還默認使用了兩個全局哈希表,一個用于當前使用,稱為主哈希表,一個用于擴容,稱為備用哈希表。

    18. 在生成 RDB期間,Redis 可以同時處理寫請求么?

    可以的,Redis提供兩個指令生成RDB,分別是save和bgsave

    • 如果是save指令,會阻塞,因為是主線程執(zhí)行的。

    • 如果是bgsave指令,是fork一個子進程來寫入RDB文件的,快照持久化完全交給子進程來處理,父進程則可以繼續(xù)處理客戶端的請求。

    19. Redis底層,使用的什么協(xié)議?

    RESP,英文全稱是Redis Serialization Protocol,它是專門為redis設計的一套序列化協(xié)議. 這個協(xié)議其實在redis的1.2版本時就已經出現(xiàn)了,但是到了redis2.0才最終成為redis通訊協(xié)議的標準。

    RESP主要有實現(xiàn)簡單、解析速度快、可讀性好等優(yōu)點。

    20. 布隆過濾器

    應對緩存穿透問題,我們可以使用布隆過濾器。布隆過濾器是什么呢?

    布隆過濾器是一種占用空間很小的數(shù)據(jù)結構,它由一個很長的二進制向量和一組Hash映射函數(shù)組成,它用于檢索一個元素是否在一個集合中,空間效率和查詢時間都比一般的算法要好的多,缺點是有一定的誤識別率和刪除困難。

    布隆過濾器原理是?假設我們有個集合A,A中有n個元素。利用k個哈希散列函數(shù),將A中的每個元素映射到一個長度為a位的數(shù)組B中的不同位置上,這些位置上的二進制數(shù)均設置為1。如果待檢查的元素,經過這k個哈希散列函數(shù)的映射后,發(fā)現(xiàn)其k個位置上的二進制數(shù)全部為1,這個元素很可能屬于集合A,反之,一定不屬于集合A。

    來看個簡單例子吧,假設集合A有3個元素,分別為{d1,d2,d3}。有1個哈希函數(shù),為Hash1?,F(xiàn)在將A的每個元素映射到長度為16位數(shù)組B。

    我們現(xiàn)在把d1映射過來,假設Hash1(d1)= 2,我們就把數(shù)組B中,下標為2的格子改成1,如下:

    我們現(xiàn)在把d2也映射過來,假設Hash1(d2)= 5,我們把數(shù)組B中,下標為5的格子也改成1,如下:

    接著我們把d3也映射過來,假設Hash1(d3)也等于 2,它也是把下標為2的格子標1:

    因此,我們要確認一個元素dn是否在集合A里,我們只要算出Hash1(dn)得到的索引下標,只要是0,那就表示這個元素不在集合A,如果索引下標是1呢?那該元素可能是A中的某一個元素。因為你看,d1和d3得到的下標值,都可能是1,還可能是其他別的數(shù)映射的,布隆過濾器是存在這個缺點的:會存在hash碰撞導致的假陽性,判斷存在誤差。

    如何減少這種誤差呢?

    • 搞多幾個哈希函數(shù)映射,降低哈希碰撞的概率

    • 同時增加B數(shù)組的bit長度,可以增大hash函數(shù)生成的數(shù)據(jù)的范圍,也可以降低哈希碰撞的概率

    我們又增加一個Hash2哈希映射函數(shù),假設Hash2(d1)=6,Hash2(d3)=8,它倆不就不沖突了嘛,如下:

    即使存在誤差,我們可以發(fā)現(xiàn),布隆過濾器并沒有存放完整的數(shù)據(jù),它只是運用一系列哈希映射函數(shù)計算出位置,然后填充二進制向量。如果數(shù)量很大的話,布隆過濾器通過極少的錯誤率,換取了存儲空間的極大節(jié)省,還是挺劃算的。

    目前布隆過濾器已經有相應實現(xiàn)的開源類庫啦,如Google的Guava類庫,Twitter的 Algebird 類庫,信手拈來即可,或者基于Redis自帶的Bitmaps自行實現(xiàn)設計也是可以的。

    參考資料

    [1]

    Redis 高可用解決方案總結: https://www.jianshu.com/p/5de2ab291696

    [2]

    Redia系列九:redis集群高可用: https://www.cnblogs.com/leeSmall/p/8414687.html

    推薦好文

    主流Java進階技術(學習資料分享)

    分享一套基于SpringBoot和Vue的企業(yè)級中后臺開源項目,代碼很規(guī)范!

    能掙錢的,開源 SpringBoot 商城系統(tǒng),功能超全,超漂亮?

    總結

    以上是生活随笔為你收集整理的2W字!详解20道Redis经典面试题!(珍藏版)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    中文字幕中文字幕中文字幕 | 九九九热精品免费视频观看网站 | 国产在线 一区二区三区 | 一区二区三区免费在线 | 久久五月天综合 | 超碰国产97 | av资源免费看 | 成人免费视频视频在线观看 免费 | 91日韩精品视频 | 美女国产 | 日韩在线理论 | 亚州五月 | 又黄又爽又湿又无遮挡的在线视频 | 亚洲 中文字幕av | 中文字幕在线观看完整版 | www久久| 日韩欧美精品在线观看视频 | 日日爱av| 中文字幕在线观看免费高清电影 | 毛片激情永久免费 | 黄色www免费 | 亚洲伦理一区二区 | 在线视频日韩精品 | 中文字幕视频一区 | 天天射天天色天天干 | 欧美黑人xxxx猛性大交 | 91久久久久久国产精品 | 日韩免费视频线观看 | 日本中文字幕系列 | 日韩电影一区二区在线观看 | 久久久精品二区 | 六月丁香六月婷婷 | 亚洲精品视频在线观看网站 | 免费av观看 | av黄在线播放 | 91av小视频 | 亚洲国产成人久久综合 | 国产日产精品一区二区三区四区 | 免费av在 | 成人9ⅰ免费影视网站 | 婷婷久久网 | 国产福利精品视频 | 在线亚洲免费视频 | 成人免费在线电影 | 久久线视频 | 天堂网av 在线 | 中文区中文字幕免费看 | 欧美一级专区免费大片 | 九七在线视频 | 婷婷开心久久网 | 青青久草在线 | 日韩午夜视频在线观看 | 亚洲精品在线观看av | 久久成人午夜 | 久草资源免费 | 国产女人免费看a级丨片 | 在线中文字幕av观看 | 国产一级黄色片免费看 | 99精品视频在线观看 | 国内外成人免费在线视频 | 青青五月天 | 亚洲蜜桃在线 | 天天操天天色天天射 | 日韩欧美一区二区在线观看 | 中文字幕日韩精品有码视频 | 亚洲视频一区二区三区在线观看 | 婷婷.com| 超黄视频网站 | 久久精品九色 | 蜜臀av性久久久久av蜜臀三区 | 在线免费观看视频你懂的 | 欧美aaa级片 | 免费观看一区二区三区视频 | 天天天天天天操 | 日本三级中文字幕在线观看 | 日本精品久久久久影院 | 人人添人人澡人人澡人人人爽 | 波多野结衣在线播放一区 | 中文字幕av最新更新 | av先锋中文字幕 | 亚洲精品久久在线 | www久草 | 久久在线免费观看视频 | 国产最新91| 一区二区三区免费播放 | 91福利免费 | 超碰免费公开 | 成人一级免费视频 | 草久在线观看 | 不卡的av电影在线观看 | 亚洲精品自拍视频在线观看 | 人人干干人人 | 国产精品18久久久久白浆 | 久久久精品午夜 | 精品亚洲男同gayvideo网站 | 免费黄色在线 | 日本中文不卡 | 亚洲精品一区二区精华 | 91亚洲夫妻| 在线电影av | 黄色软件视频大全免费下载 | 中文字幕 国产视频 | 日韩有码网站 | 久久亚洲区 | 婷婷激情综合五月天 | 视频 国产区 | 精品福利国产 | 一本大道久久精品懂色aⅴ 五月婷社区 | 亚洲第一中文字幕 | 久久这里只有精品23 | 国产91精品久久久久 | 9999在线视频 | 色射色| 日韩免费一区二区在线观看 | 免费在线激情视频 | 欧美影片 | 成人av电影在线播放 | 色偷偷人人澡久久超碰69 | 中文免费在线观看 | 九九热在线视频免费观看 | 欧美男男tv网站 | 在线岛国av| 一区二区三区影院 | 天天曰天天爽 | 在线观看中文字幕一区二区 | 韩国av一区二区三区在线观看 | 久久精品欧美一区 | 久久影院午夜论 | 激情网五月 | 日本三级吹潮在线 | 草久中文字幕 | 丁香视频 | 久久久久免费精品视频 | 中文字幕在线视频网站 | 97精品免费视频 | 伊人亚洲综合网 | 一区二区三区在线观看免费 | 国产不卡精品 | 精品国产理论片 | 久久精品欧美 | 国产精品国产三级国产aⅴ无密码 | 91.麻豆视频 | 亚洲丁香日韩 | 天天艹天天操 | 在线99视频 | 婷婷丁香六月 | 狠狠干成人 | 免费无遮挡动漫网站 | 国产一区在线观看免费 | 91人人澡人人爽人人精品 | 亚洲黄色一级视频 | 在线国产一区二区三区 | 成人在线观看免费 | 亚洲欧洲国产视频 | 色婷婷www | 精品9999 | 热久久在线视频 | 欧美一区二视频在线免费观看 | 精品久久1| 成人免费观看在线视频 | av五月婷婷| 日韩电影精品一区 | 福利视频精品 | 激情综合久久 | 亚州av网站大全 | 国产精品久久久久一区二区三区 | 99久热在线精品视频成人一区 | 激情久久五月 | 精品久久久久免费极品大片 | 免费日韩 精品中文字幕视频在线 | 91 中文字幕 | 日日日天天天 | 中文字幕电影一区 | 狠狠狠色丁香婷婷综合久久88 | 91久久丝袜国产露脸动漫 | 91热精品| 免费福利在线播放 | 99re亚洲国产精品 | 美女在线观看网站 | 一区二区三区四区在线 | 亚洲精品成人av在线 | 国产丝袜在线 | 国产精品久久久久久久久久久免费看 | 字幕网在线观看 | 午夜av在线电影 | 日韩欧美视频 | 久久激情影院 | 国产激情小视频在线观看 | 欧美激情综合色综合啪啪五月 | 中文字幕一区二区三区四区久久 | 亚洲欧洲精品一区二区精品久久久 | 国产亚洲精品久久久久久电影 | 成人在线播放免费观看 | 福利视频导航网址 | 免费黄色av. | 日日操天天射 | 天天亚洲| 欧美日韩久久不卡 | 在线观看免费版高清版 | 日韩在线观看网站 | 狠狠干网 | 久在线观看 | 福利一区在线 | 99热国产在线| 国产精品精 | 日韩精品2区 | 国产专区在线播放 | 日韩视频一二三区 | 91精品啪啪 | 91人人澡人人爽人人精品 | 久久精品国产一区 | 91精品区 | 色婷婷亚洲婷婷 | 色天天天 | 久免费视频 | 欧美日韩三级 | av在线色 | 国产麻豆精品久久一二三 | 五月天天在线 | 超碰在线99 | 黄色免费在线视频 | 中文字幕 国产专区 | 最近最新最好看中文视频 | 少妇高潮流白浆在线观看 | 丰满少妇在线观看网站 | 美女免费视频一区 | 婷婷激情5月天 | 日本黄色a级大片 | 五月天婷婷免费视频 | 国产精品18久久久久久久久 | 天天弄天天干 | 亚洲欧美精品一区二区 | 婷婷播播网 | 激情网五月 | 91精品久久久久久久久 | 色国产视频 | 亚洲欧美日韩精品一区二区 | 国产97色在线 | 粉嫩一二三区 | 国产精品视频免费在线观看 | 香蕉在线观看视频 | 欧美人牲 | 久久激情五月丁香伊人 | 天天操天天爱天天干 | 激情影院在线观看 | 久久av福利 | 日b视频在线观看网址 | 91福利视频免费 | 国产不卡在线观看视频 | 日韩欧美国产免费播放 | 国产亲近乱来精品 | 九九九九精品九九九九 | 99r在线播放 | 国产一区二区在线精品 | 国内精品免费久久影院 | av看片网址 | 欧美性受极品xxxx喷水 | 欧美色图p| www视频在线免费观看 | 亚洲精品国偷拍自产在线观看 | 人人精品久久 | 成人av高清在线观看 | 久久婷婷综合激情 | 中文字幕在线播出 | 国产精品一区二区在线看 | 91人人插| 日韩欧美99 | 日日夜夜91 | 最近乱久中文字幕 | 精品久久久久久久久久国产 | 天堂av在线中文在线 | 人人爽人人爽人人片av | 免费看成人 | 国产成年人av | 中文字幕一区二区三区精华液 | 亚洲一二三久久 | 免费试看一区 | 免费视频久久久久久久 | 国产91免费在线观看 | 欧美精品久久久久a | 久久久免费在线观看 | 国产亚洲综合性久久久影院 | 久草在线视频中文 | 久久久久久久久久久综合 | 91看片一区二区三区 | 亚洲精品乱码久久久一二三 | 久久99久久99精品免视看婷婷 | 91精品国产一区二区在线观看 | 日本久久中文字幕 | 久久综合久久鬼 | 中文字幕在线人 | 又黄又爽又湿又无遮挡的在线视频 | 999久久精品 | 最近的中文字幕大全免费版 | 精品国产一区二区三区久久久蜜月 | 国产精品99久久免费观看 | 国产精品video | 国产亚洲精品v | 婷香五月 | 久久99精品久久久久久久久久久久 | 四虎影视8848dvd | 狠狠躁夜夜躁人人爽超碰91 | 国产亚洲综合在线 | 国产字幕在线播放 | 国产成人一区二 | 午夜精品久久一牛影视 | 精品国模一区二区三区 | 国产亚洲精品久久久久久久久久 | 亚洲成年人在线播放 | 天天天射 | 日本精品视频网站 | 最新日本中文字幕 | 久久久久久久久久亚洲精品 | 狠狠色狠狠色综合日日小说 | 波多野结衣在线视频一区 | 国产精品剧情在线亚洲 | 国模精品一区二区三区 | av久久久 | 国产精品第 | 在线免费观看国产视频 | 丁香视频在线观看 | 国产不卡免费视频 | 中文字幕在线播放第一页 | wwwav视频| 999久久久国产精品 高清av免费观看 | 欧美a级一区二区 | 中文字幕一区二区三区久久蜜桃 | 在线观看91视频 | 高清美女视频 | 久青草电影| 午夜精品视频免费在线观看 | 六月色婷婷 | 国产一级片播放 | 精品久久久久久久久中文字幕 | 国产黄免费 | 欧美成人精品欧美一级乱 | 国产日韩精品在线观看 | 午夜婷婷综合 | 蜜臀久久99精品久久久无需会员 | 日韩mv欧美mv国产精品 | 日韩欧美一区二区在线观看 | 日韩在线观看一区二区 | 婷婷国产视频 | 五月激情在线 | 婷婷色网视频在线播放 | 久久久久久久久久久久久9999 | 蜜臀久久99静品久久久久久 | 欧美日韩免费在线观看视频 | 亚洲专区在线 | 天天射天天操天天色 | 毛片在线网 | 久久伦理 | 国产午夜精品av一区二区 | 国产精品不卡视频 | 亚洲免费在线看 | 97日日| 国产只有精品 | 最近中文字幕mv免费高清在线 | 日本一区二区三区视频在线播放 | 午夜在线看片 | 最近日本韩国中文字幕 | 国产精品美女久久久网av | 中文字幕欧美日韩va免费视频 | 欧美另类激情 | 中文字幕91 | 99在线免费视频 | 中文字幕免费高 | 国产黄色视 | 丁香免费视频 | 国产精品日韩欧美 | 国产手机视频在线 | 久久国产精品一区二区三区四区 | 国产一级视频在线观看 | 最新中文字幕 | 黄色中文字幕 | 婷婷精品在线视频 | 国产1区2区3区精品美女 | 91在线影视 | 人人澡超碰碰97碰碰碰软件 | www最近高清中文国语在线观看 | 亚洲一区二区精品 | 超碰97人 | 91精品国产一区二区三区 | 特级片免费看 | 91麻豆精品国产 | 免费日韩精品 | 久久国产剧场电影 | 日韩精品免费在线观看 | 欧美成年网站 | 日韩av综合网站 | 在线观看av的网站 | 国产美女被啪进深处喷白浆视频 | www.伊人色.com | 九色精品免费永久在线 | 黄色精品网站 | 91污污 | 国产91学生粉嫩喷水 | 中文字幕亚洲精品日韩 | 久久乱码卡一卡2卡三卡四 五月婷婷久 | 美女视频a美女大全免费下载蜜臀 | 波多野结衣一区二区三区中文字幕 | 亚洲人成人天堂h久久 | 久久伊人热 | 99热精品久久| 久久污视频 | 蜜臀av性久久久久蜜臀aⅴ涩爱 | 婷婷丁香在线视频 | 午夜影院三级 | 亚洲成色777777在线观看影院 | 久久九九网站 | 亚洲伊人婷婷 | 欧美 日韩 国产 中文字幕 | 久久精品国产亚洲a | 草久久av| 久久久久福利视频 | 婷婷综合影院 | 久久精品免费观看 | 中文字幕黄色网 | 日韩免费一区二区在线观看 | 中文字幕韩在线第一页 | 国产精品久久久久久久久久三级 | 激情视频在线高清看 | 少妇精品久久久一区二区免费 | 成人黄色小说在线观看 | 91视频在线播放视频 | 91.精品高清在线观看 | 久草精品视频 | 久久视频在线视频 | 国内精品久久久久久久影视麻豆 | 91传媒在线观看 | 中文字幕在 | 国产一二区免费视频 | 久热久草 | 国产成人精品在线 | 亚洲最新在线 | 日韩免费观看视频 | 免费在线观看日韩视频 | 99综合久久 | 91九色porny蝌蚪视频 | 天天综合色天天综合 | 黄色一级在线视频 | 97碰碰精品嫩模在线播放 | 人人看黄色 | 99视频国产在线 | 日韩精品一区二区不卡 | 久久这里有精品 | 玖玖在线免费视频 | 国产精品久久久久影院 | 国产精品18p | 碰超在线 | 在线免费看片 | 成人在线网站观看 | 天天干亚洲 | 国产一区精品在线 | 国产精品综合在线观看 | 玖玖综合网 | 久草在线视频新 | 久久情爱 | 久草.com| 91黄色在线视频 | 国产中文在线播放 | 色综合天天 | 国产精品久久久久影院日本 | 国产亚洲精品久久久久久移动网络 | 制服丝袜在线 | 欧美国产日韩一区二区三区 | 人人澡人人爽 | 亚洲欧美成人综合 | 成人免费看黄 | 婷婷丁香激情网 | 国内外成人在线视频 | 国产自产在线视频 | 超级碰碰免费视频 | 国产精品毛片久久久久久久久久99999999 | 国产成人在线看 | 免费高清在线视频一区· | 91精品国自产在线 | 黄色免费视频在线观看 | 网站免费黄色 | 一区二区三区久久精品 | 国产精品破处视频 | 久久久久久久久久毛片 | 欧美久久久久久久久中文字幕 | 中文av网站| 国产专区免费 | 91精品麻豆 | 99在线免费视频 | 午夜视频欧美 | 日韩在线视| 国产亚洲精品v | 久久婷婷一区二区三区 | 久草爱 | 国产精品视频专区 | 久久久久综合网 | 久久久亚洲国产精品麻豆综合天堂 | 久久看片网 | 国产精品岛国久久久久久久久红粉 | 久久免费观看少妇a级毛片 久久久久成人免费 | 丁香婷婷基地 | 成人网444ppp | 午夜视频一区二区三区 | 婷婷在线色 | 91| 日韩精品视频网站 | 六月色婷 | 人人干在线 | 亚洲欧美成人综合 | 黄色小说在线观看视频 | 国产精品99久久久久久有的能看 | 国产 精品 资源 | 午夜久久 | 中文字幕久久精品亚洲乱码 | 久久香蕉一区 | 久久久亚洲网站 | 成年人免费在线观看网站 | 国产色综合 | 亚洲精品美女久久 | 亚洲国产中文在线观看 | 国产精品毛片久久久久久久久久99999999 | 国产亚洲精品bv在线观看 | 国产91精品在线播放 | 精品在线观看免费 | 日韩在线看片 | 午夜a区 | 国产精品久久久久久久久软件 | 久草免费色站 | 91九色视频国产 | 日日日日干 | 日韩女同av| 亚洲成人一二三 | 97福利视频 | 深夜免费福利 | 九月婷婷人人澡人人添人人爽 | 九九在线高清精品视频 | 国产精品video爽爽爽爽 | 久久久.com | 欧美日本在线视频 | 午夜影院先 | 激情影院在线观看 | 亚洲视频电影在线 | 国产91探花| 欧美另类z0zx| 香蕉久草| 国产一级免费播放 | 久久av一区二区三区亚洲 | 久草在线综合 | 亚洲精品色婷婷 | 超碰av在线 | 国产精品男女 | 天天草天天干天天 | 久久99久久99精品免费看小说 | 操操操人人| 玖玖在线资源 | av网址aaa| 91精品国自产在线观看欧美 | 国产精品久久久久久一区二区 | 国产精品高清一区二区三区 | 亚洲黄色软件 | 久久视频免费在线观看 | 欧美一级性| 中文字幕视频播放 | 在线一区av | 天天操天天爽天天干 | 亚洲mv大片欧洲mv大片免费 | 在线小视频国产 | 欧美日韩高清一区二区 国产亚洲免费看 | 久久看片| 国产精品久久久久久麻豆一区 | 久久久国产一区二区 | 中文字幕在线观看一区二区 | 久草视频在线免费 | 亚洲爱爱视频 | 天天操夜夜逼 | 亚洲男男gaygay无套 | 99爱精品在线 | 美女视频黄,久久 | 国产精品wwwwww | 激情av五月婷婷 | 91麻豆看国产在线紧急地址 | 五月婷亚洲 | 国产高清福利在线 | 亚洲精品国产区 | 最近中文字幕完整视频高清1 | 中国美女一级看片 | 久久久久久99精品 | 亚洲人久久久 | 色婷婷国产精品一区在线观看 | 欧美在线aaa| 国产精久久 | 国产成人精品亚洲精品 | 一级黄色片在线免费看 | 操一草 | 91黄色免费网站 | 国产精品区一区 | 成人av网站在线观看 | 国产黄色电影 | 99亚洲国产| av东方在线| 91久久国产自产拍夜夜嗨 | 久久只精品99品免费久23小说 | 99久久er热在这里只有精品66 | 国产亚洲一区二区三区 | 欧美色久 | 中文字幕第 | 国产91粉嫩白浆在线观看 | 丁香电影小说免费视频观看 | 亚洲国产免费 | 色婷婷狠狠| 亚洲免费不卡 | 亚洲精品国产区 | 中文字幕色在线视频 | 亚洲免费av在线 | 六月丁香婷婷网 | 久草在线视频精品 | 久草久 | 伊人永久在线 | 婷婷亚洲激情 | 国产高清视频在线免费观看 | www成人av| avsex| 亚洲丝袜一区二区 | 中文字幕a∨在线乱码免费看 | 久久国产精品精品国产色婷婷 | 久久精品国产免费看久久精品 | 午夜精品剧场 | av综合站 | 久久久国产99久久国产一 | 久久久久国产精品厨房 | 国产精品久久久久久久久婷婷 | 黄色小说18 | www.com黄| 在线激情网 | 国产青青青 | 日韩有码欧美 | 国产999视频| 91自拍视频在线观看 | 91精品视频网站 | 亚洲 综合 国产 精品 | 91中文字幕在线视频 | 亚洲,国产成人av | 亚洲精品久久激情国产片 | 六月丁香激情综合 | 国产午夜精品在线 | 一级黄色片网站 | 99精品国产成人一区二区 | 午夜精品av | 国产精品精品国产 | 在线观看日韩精品 | 狠狠操狠狠干天天操 | 国内精品小视频 | 99久久爱| 精品欧美一区二区三区久久久 | 成人在线视频论坛 | 亚洲国产精品一区二区久久,亚洲午夜 | 中文字幕在线免费观看 | 特级西西人体444是什么意思 | 欧美精品久久久久久久久久丰满 | 天天操天天操天天操天天操天天操 | 色国产精品 | 免费黄色av电影 | 国产成人精品久久二区二区 | 91亚洲网 | 日韩av高清在线观看 | 91精品国产综合久久婷婷香蕉 | 97国产在线 | 中文字幕视频一区 | 日韩女同av| 成人在线观看资源 | 伊人狠狠色 | 伊人五月综合 | 超碰在线最新网址 | 欧美a视频在线观看 | 在线日韩一区 | 欧美一区日韩精品 | 天天玩夜夜操 | 亚洲国产激情 | 免费久久网 | 中文字幕av日韩 | 区一区二区三区中文字幕 | 亚洲成人av在线播放 | 99久e精品热线免费 99国产精品久久久久久久久久 | 免费av大全 | 精品国产伦一区二区三区观看体验 | 亚洲视频综合在线 | 中文字幕在线观 | 一区二区三区 亚洲 | 国产午夜影院 | 黄色三级视频片 | 亚洲午夜精品一区二区三区电影院 | 永久免费视频国产 | 天天看天天干天天操 | 激情图片久久 | 国产免费看| 久久久精品免费看 | 亚洲国产电影在线观看 | 99久久综合狠狠综合久久 | 天天干天天插 | 黄色a大片 | 久久艹精品 | 成人久久久久久久久久 | 精品国产乱码久久久久久久 | 国产精品人成电影在线观看 | 狠狠色狠狠综合久久 | 成人福利在线观看 | av一级片网站 | 国产精品久久99综合免费观看尤物 | 又色又爽又黄高潮的免费视频 | 国产亚洲激情视频在线 | 久久伦理电影 | 国产裸体永久免费视频网站 | 97天堂网 | www.91国产 | 亚洲欧美视频在线观看 | 美女网站视频久久 | 亚洲精品综合久久 | 综合亚洲视频 | 久久99国产综合精品免费 | 黄色国产区 | 久久久久久久久久免费 | 波多野结衣理论片 | 精品国产免费一区二区三区五区 | 992tv在线观看网站 | 亚洲va在线va天堂va偷拍 | 日韩精品国产一区 | 国产亚洲婷婷免费 | 久久综合欧美精品亚洲一区 | 欧美电影在线观看 | 色网影音先锋 | 中文字幕在线观看完整版电影 | 国产一区二区手机在线观看 | 欧美性生活小视频 | 久久人人爽爽人人爽人人片av | 97在线精品 | 国产精品aⅴ | av电影免费观看 | 日韩国产欧美在线播放 | 99av在线视频 | 999久久久久久久久6666 | 香蕉视频在线免费 | 午夜资源站 | 国产91区| 在线看片一区 | 国产资源免费 | 国产成人精品在线播放 | 国产成人精品久久 | 欧美精品久久久久a | 五月婷在线 | www在线观看国产 | 精品999久久久 | 久久不卡视频 | 亚洲国产精品99久久久久久久久 | 五月婷婷丁香色 | 日本久久久精品视频 | 色婷婷激婷婷情综天天 | 99热精品视 | 亚洲色图 校园春色 | 性色在线视频 | 久久久精品一区二区 | 久久伊人爱 | 中文字幕乱码在线播放 | 色婷婷综合久久久中文字幕 | av电影久久 | 人人爽人人爽人人爽人人爽 | 国产精品一区久久久久 | 成人av在线亚洲 | 久草观看| 欧美性生活小视频 | 成人av一区二区在线观看 | 一区二区三区精品在线视频 | 国产成人免费网站 | 亚洲精品在线观看不卡 | 天干啦夜天干天干在线线 | 成年人在线免费视频观看 | 成人午夜免费剧场 | 午夜视频在线观看一区 | 日韩精品免费在线观看视频 | 在线免费观看黄色大片 | 五月激情姐姐 | 欧美在线观看小视频 | 亚洲视频大全 | 韩国av电影在线观看 | 天天插天天干天天操 | 激情偷乱人伦小说视频在线观看 | 六月丁香综合网 | 天天操天天舔天天干 | 欧美日韩一区二区免费在线观看 | av免费看av| 亚洲国产高清在线观看视频 | 日韩特级片 | 伊人色综合久久天天网 | 久久大香线蕉app | 日韩av一区二区在线 | 国产免费影院 | 福利网址在线观看 | 国产在线观看高清视频 | 欧美国产不卡 | 久久久久久黄 | 久久久久久久久久久国产精品 | 久久久久99精品国产片 | 午夜精品视频一区二区三区在线看 | 欧美日韩国产欧美 | 久久精品99北条麻妃 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 欧美在线视频不卡 | 中文字幕人成乱码在线观看 | 99久久成人| 久草www | 国产专区在线 | 五月天综合网 | 中文字幕a在线 | 亚洲高清精品在线 | 亚洲综合视频在线播放 | 久久中文网 | 精品成人免费 | 在线观看黄av | av色网站| 干天天| 国产成人亚洲在线电影 | 久久精品波多野结衣 | 国产亚州精品视频 | a级成人毛片 | 天天综合狠狠精品 | www.亚洲视频| 狠狠色狠狠色 | 91精品国产成人观看 | 99超碰在线观看 | 97超碰资源 | 丁香电影小说免费视频观看 | 久久久久久久久久久免费视频 | 欧美精品亚洲精品日韩精品 | 国产精品igao视频网入口 | 久草视频在 | 在线中文日韩 | 久久久久久久久久亚洲精品 | 日韩免费视频线观看 | 亚洲精品久久久久999中文字幕 | 日韩电影在线视频 | 日韩欧美成 | 91精品国产一区 | 日韩在线观看 | 91免费视频国产 | 国产一区视频导航 | 在线免费视频a | 日本最大色倩网站www | 欧美黄污视频 | 91欧美日韩国产 | 91亚洲在线观看 | 日韩在线免费视频观看 | 免费亚洲片 | 中文字幕在线免费97 | 九九在线播放 | av电影一区二区三区 | 国产免费小视频 | 香蕉网在线| 国产午夜一区 | www.人人草| 国产又粗又长又硬免费视频 | 91视频大全 | 亚洲国产精品久久 | 亚州五月 | 99精品乱码国产在线观看 | 欧美va日韩va | av手机在线播放 | 国产黄色片在线免费观看 | 美女视频久久久 | 91九色视频国产 | 热久久这里只有精品 | 亚洲乱码精品久久久久 | 久久人人爽人人爽人人片 | 国际av在线 | 国产特级毛片aaaaaaa高清 | 日韩av一区二区三区在线观看 | 久久精品久久精品久久 | 久久久国产精品一区二区中文 | 亚洲精品久久久久中文字幕m男 | 91黄色视屏 | 99资源网 | 伊香蕉大综综综合久久啪 | 99se视频在线观看 | 天天综合成人网 | 久久成人国产精品入口 | 国产精品久久视频 | 99精品免费网 | 狠狠狠狠狠狠狠狠干 | 久久毛片高清国产 | 国产成人资源 | 国产麻豆精品传媒av国产下载 | av一区二区三区在线观看 | 99热精品久久 | www.av中文字幕.com | 在线网址你懂得 | 黄色网中文字幕 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 日韩欧美xx| 成人a在线观看高清电影 | 天天视频色 | 91精品国自产拍天天拍 | 伊人狠狠操| 亚洲 欧美日韩 国产 中文 | 日韩天天操 | 亚洲在线视频播放 | 久久久91精品国产 | 亚洲高清不卡av | 成人av影院在线观看 | 亚洲欧美一区二区三区孕妇写真 | 视频一区二区国产 | 伊人激情网 | www.超碰97.com | 欧美一级激情 | 亚洲精品玖玖玖av在线看 | 亚洲砖区区免费 | 日本久久久久久 | 五月婷婷视频在线 | 夜夜爽天天爽 | 在线色亚洲 | 成人av直播 | 久久午夜电影院 | 国产精品久久久久久久久久久久 | 成人av片免费观看app下载 | 久久9视频 | 国产一区二区影院 | 国产精品久久久久影院 | 日日夜日日干 | 一区在线观看 | 久久精品久久99精品久久 | 国产精品久久久久久久久久久久午夜片 | 中文字幕 在线看 | 国产黄免费 | 亚洲 中文 欧美 日韩vr 在线 | 亚洲欧美在线观看视频 | 蜜臀av网址 | 欧美资源 | 久久99精品热在线观看 | 欧美激情第一页xxx 午夜性福利 | 国内综合精品午夜久久资源 | 成人av片免费观看app下载 | 久久久久亚洲精品成人网小说 | 在线黄频| 夜色资源站国产www在线视频 | 91精品婷婷国产综合久久蝌蚪 | 日韩剧情 | 久久久免费观看视频 | 欧美激情综合五月色丁香小说 | 中文字幕免费观看全部电影 | 日本久久片 | 国产1区2| 一区二区三区 中文字幕 | 岛国av在线不卡 | 国产精品九九热 | 国产精品久久久久久麻豆一区 | 成人在线播放免费观看 | 婷香五月 | 久久激情电影 | 久久99精品一区二区三区三区 | 日韩一区二区免费播放 | 亚洲欧洲久久久 | 夜夜操天天 | 久草在线这里只有精品 | 国产成人免费观看 | 久久精品国产免费看久久精品 | 欧美在线久久 | 国产资源网 | 亚洲婷婷免费 | 婷婷丁香激情综合 | 色婷婷亚洲综合 | 欧美xxxx性xxxxx高清 | 在线观看成人网 | 久久久99精品免费观看app | 天天射射天天 | 天海冀一区二区三区 | 国产精品 日韩精品 | 亚洲美女视频在线 | h动漫中文字幕 | 天天操天天操天天爽 | 国产精品video爽爽爽爽 | 免费色视频网址 | 天天做天天爱天天综合网 | 日本精品va在线观看 | 亚洲午夜久久久久 | 久久理论片 | 日韩伦理一区二区三区av在线 | 亚洲天堂网在线观看视频 | 免费在线观看污网站 | 久青草电影| 久久草av | 开心激情五月网 | 国产高清在线a视频大全 | 欧美成人精品在线 | 射久久| 天天天插 | 国产一区视频在线观看免费 | 高清久久久 | 97在线观视频免费观看 | 一本一本久久a久久精品综合小说 | 亚洲va在线va天堂va偷拍 | 午夜久久精品 | 久久五月激情 | 13日本xxxxxⅹxxx20 |