天天看點

Java面試題-redis2

作者:Java農夫

又是一年招聘季,整理一些面試題,為自己也為大家整理點資料,希望大家成功上岸。這些整理的是針對面試。因平台單日有釋出數量限制,超出限制的隻能粉絲檢視,需要的請關注後自行擷取,謝謝。

1、Redis官方為什麼不提供 Windows版本?

一個字懶,多一事不如少一事,Redis是開源軟體。

Redis的Windows版本是3.0,之前微軟維護,後續是tporadowski維護

https://github.com/tporadowski/redis

目前Linux版本已經相當穩定,而且使用者量很大,無需開發windows版本,反而會帶來相容性等問題。

2、Redis 持久化方式有哪些?以及有什麼差別?

Redis 提供兩種持久化機制 RDB 和 AOF 機制:

RDB

RDB持久化是把目前程序資料生成快照儲存到硬碟的過程。所謂記憶體快照,就是指記憶體中的資料在某一個時刻的狀态記錄。這就類似于照片,當你給朋友拍照時,一張照片就能把朋友一瞬間的形象完全記下來。RDB 就是Redis DataBase 的縮寫。

優點:

  • 隻有一個檔案 dump.rdb ,友善持久化。
  • 容災性好,一個檔案可以儲存到安全的磁盤。
  • 性能最大化,fork 子程序來完成寫操作,讓主程序繼續處理指令,是以是 IO 最大化。
  • 相對于資料集大時,比AOF的啟動效率更高。

缺點:

資料安全性低。 RDB是間隔一段時間進行持久化,如果持久化之間Redis發生故障,會發生資料丢失。是以這種方式更适合資料要求不嚴謹的時候。

AOF

AOF(append only file)持久化:以獨立日志的方式記錄每次寫指令,重新開機時再重新執行AOF檔案中的指令達到恢複資料的目的。AOF的主要作用是解決了資料持久化的實時性,目前已經是Redis持久化的主流方式。

缺點:

  • AOF 檔案比 RDB 檔案大,且恢複速度慢。
  • 資料集大的時候,比 RDB 啟動效率低

3、什麼是Redis事務?原理是什麼?

Redis 中的事務是一組指令的集合,是 Redis 的最小執行機關。它可以保證一次執行多個指令,每個事務是一個單獨的隔離操作,事務中的所有指令都會序列化、按順序地執行。服務端在執行事務的過程中,不會被其他用戶端發送來的指令請求打斷。

它的原理是先将屬于一個事務的指令發送給 Redis,然後依次執行這些指令。

Redis 事務的注意點有哪些?

需要注意的點有:

Redis 事務是不支援復原的,不像 MySQL 的事務一樣,要麼都執行要麼都不執行;

Redis 服務端在執行事務的過程中,不會被其他用戶端發送來的指令請求打斷。直到事務指令全部執行完畢才會執行其他用戶端的指令。

Redis 事務為什麼不支援復原?

Redis 的事務不支援復原,但是執行的指令有文法錯誤,Redis 會執行失敗,這些問題可以從程式層面捕獲并解決。但是如果出現其他問題,則依然會繼續執行餘下的指令。這樣做的原因是因為復原需要增加很多工作,而不支援復原則可以保持簡單、快速的特性。

事務

大家應該對事務比較了解,簡單地說,事務表示一組動作,要麼全部執行,要麼全部不執行。

例如在社交網站上使用者A關注了使用者B,那麼需要在使用者A的關注表中加入使用者B,并且在使用者B的粉絲表中添加使用者A,這兩個行為要麼全部執行,要麼全部不執行,否則會出現資料不一緻的情況。

Redis提供了簡單的事務功能,将一組需要一起執行的指令放到multi和exec兩個指令之間。multi 指令代表事務開始,exec指令代表事務結束。另外discard指令是復原。

一個用戶端

Java面試題-redis2

另外一個用戶端

在事務沒有送出的時查詢(查不到資料)

Java面試題-redis2

在事務送出後查詢(可以查到資料)

Java面試題-redis2

可以看到sadd指令此時的傳回結果是QUEUED,代表指令并沒有真正執行,而是暫時儲存在Redis中的一個緩存隊列(是以discard也隻是丢棄這個緩存隊列中的未執行指令,并不會復原已經操作過的資料,這一點要和關系型資料庫的Rollback操作區分開)。

隻有當exec執行後,使用者A關注使用者B的行為才算完成,如下所示exec傳回的兩個結果對應sadd指令。

但是要注意Redis的事務功能很弱。在事務復原機制上,Redis隻能對基本的文法錯誤進行判斷。

如果事務中的指令出現錯誤,Redis 的處理機制也不盡相同。

  • 文法指令錯誤
Java面試題-redis2

例如下面操作錯将set寫成了sett,屬于文法錯誤,會造成整個事務無法執行,事務内的操作都沒有執行:

  • 運作時錯誤

例如:事務内第一個指令簡單的設定一個string類型,第二個對這個key進行sadd指令,這種就是運作時指令錯誤,因為文法是正确的:

Java面試題-redis2

可以看到Redis并不支援復原功能,第一個set指令已經執行成功,開發人員需要自己修複這類問題。

Redis的事務原理

事務是Redis實作在伺服器端的行為,使用者執行MULTI指令時,伺服器會将對應這個使用者的用戶端對象設定為一個特殊的狀态,在這個狀态下後續使用者執行的查詢指令不會被真的執行,而是被伺服器緩存起來,直到使用者執行EXEC指令為止,伺服器會将這個使用者對應的用戶端對象中緩存的指令按照送出的順序依次執行。

4、如何在100個億URL中快速判斷某URL是否存在?

傳統資料結構的不足

當然有人會想,我直接将網頁URL存入資料庫進行查找不就好了,或者建立一個哈希表進行查找不就OK了。

當資料量小的時候,這麼思考是對的,

确實可以将值映射到 HashMap 的 Key,然後可以在 O(1) 的時間複雜度内傳回結果,效率奇高。但是 HashMap 的實作也有缺點,例如存儲容量占比高,考慮到負載因子的存在,通常空間是不能被用滿的,舉個例子如果一個1000萬HashMap,Key=String(長度不超過16字元,且重複性極小),Value=Integer,會占據多少空間呢?1.2個G。實際上,1000萬個int型,隻需要40M左右空間,占比3%,1000萬個Integer,需要161M左右空間,占比13.3%。可見一旦你的值很多例如上億的時候,那HashMap 占據的記憶體大小就變得很可觀了。

但如果整個網頁黑名單系統包含100億個網頁URL,在資料庫查找是很費時的,并且如果每個URL空間為64B,那麼需要記憶體為640GB,一般的伺服器很難達到這個需求。

布隆過濾器

1970 年布隆提出了一種布隆過濾器的算法,用來判斷一個元素是否在一個集合中。這種算法由一個二進制數組和一個 Hash 算法組成。

本質上布隆過濾器是一種資料結構,比較巧妙的機率型資料結構(probabilistic data structure),特點是高效地插入和查詢,可以用來告訴你 “某樣東西一定不存在或者可能存在”。

相比于傳統的 List、Set、Map 等資料結構,它更高效、占用空間更少,但是缺點是其傳回的結果是機率性的,而不是确切的。

實際上,布隆過濾器廣泛應用于網頁黑名單系統、垃圾郵件過濾系統、爬蟲網址判重系統等,Google 著名的分布式資料庫 Bigtable 使用了布隆過濾器來查找不存在的行或列,以減少磁盤查找的IO次數,Google Chrome浏覽器使用了布隆過濾器加速安全浏覽服務。

Java面試題-redis2

布隆過濾器的誤判問題

  • Ø通過hash計算在數組上不一定在集合
  • Ø本質是hash沖突
  • Ø通過hash計算不在數組的一定不在集合(誤判)
Java面試題-redis2

優化方案

增大數組(預估适合值)

增加hash函數

Java面試題-redis2

繼續閱讀