redis面試題及答案php(關於redis的面試題以及答案)

本文目錄一覽:

redis常見的面試問題都有哪些

其實,不管是什麼樣的面試形,問的問題都差不多,萬變不離其宗,都有規律可尋。其實對所有的面試官而言,只有一個目的:在最短的時間裡了解到你最多的信息。想高效率的準備面試,先從這七個大方面着手吧!

一、基本情況

1、請用最簡潔的語言描述您從前的工作經歷和工作成果。

二、專業背景

您認為此工作崗位應當具備哪些素質?

三、工作模式

您平時習慣於單獨工作還是團隊工作?

四、價值取向

您對原來的單位和上司的看法如何?

五、資質特性

您如何描述自己的個性?

六、薪資待遇

是否方便告訴我您目前的待遇是多少?

七、背景調查

您是否介意我們通過您原來的單位迚行一些調查?

95%的面試基本上都離不開這些問題,當然還有可能問一些專業問題,我想如果你做過的話應該都不是什麼難事,一般面試官都不會過多的問專業方面的問題的。

php面試題 memcache和redis的區別

Redis與Memcached的區別

傳統MySQL+ Memcached架構遇到的問題

實際MySQL是適合進行海量數據存儲的,通過Memcached將熱點數據加載到cache,加速訪問,很多公司都曾經使用過這樣的架構,但隨着業務數據量的不斷增加,和訪問量的持續增長,我們遇到了很多問題:

1.MySQL需要不斷進行拆庫拆表,Memcached也需不斷跟着擴容,擴容和維護工作佔據大量開發時間。

2.Memcached與MySQL數據庫數據一致性問題。

3.Memcached數據命中率低或down機,大量訪問直接穿透到DB,MySQL無法支撐。

4.跨機房cache同步問題。

眾多NoSQL百花齊放,如何選擇

最近幾年,業界不斷湧現出很多各種各樣的NoSQL產品,那麼如何才能正確地使用好這些產品,最大化地發揮其長處,是我們需要深入研究和思考的

問題,實際歸根結底最重要的是了解這些產品的定位,並且了解到每款產品的tradeoffs,在實際應用中做到揚長避短,總體上這些NoSQL主要用於解

決以下幾種問題

1.少量數據存儲,高速讀寫訪問。此類產品通過數據全部in-momery 的方式來保證高速訪問,同時提供數據落地的功能,實際這正是Redis最主要的適用場景。

2.海量數據存儲,分布式系統支持,數據一致性保證,方便的集群節點添加/刪除。

3.這方面最具代表性的是dynamo和bigtable 2篇論文所闡述的思路。前者是一個完全無中心的設計,節點之間通過gossip方式傳遞集群信息,數據保證最終一致性,後者是一個中心化的方案設計,通過類似一個分布式鎖服務來保證強一致性,數據寫入先寫內存和redo log,然後定期compat歸併到磁盤上,將隨機寫優化為順序寫,提高寫入性能。

4.Schema free,auto-sharding等。比如目前常見的一些文檔數據庫都是支持schema-free的,直接存儲json格式數據,並且支持auto-sharding等功能,比如mongodb。

面對這些不同類型的NoSQL產品,我們需要根據我們的業務場景選擇最合適的產品。

Redis適用場景,如何正確的使用

前面已經分析過,Redis最適合所有數據in-momory的場景,雖然Redis也提供持久化功能,但實際更多的是一個disk-

backed的功能,跟傳統意義上的持久化有比較大的差別,那麼可能大家就會有疑問,似乎Redis更像一個加強版的Memcached,那麼何時使用

Memcached,何時使用Redis呢?

如果簡單地比較Redis與Memcached的區別,大多數都會得到以下觀點:

1 Redis不僅僅支持簡單的k/v類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。

2 Redis支持數據的備份,即master-slave模式的數據備份。

3 Redis支持數據的持久化,可以將內存中的數據保持在磁盤中,重啟的時候可以再次加載進行使用。

拋開這些,可以深入到Redis內部構造去觀察更加本質的區別,理解Redis的設計。

Redis中,並不是所有的數據都一直存儲在內存中的。這是和Memcached相比一個最大的區別。Redis只會緩存所有的

key的信息,如果Redis發現內存的使用量超過了某一個閥值,將觸發swap的操作,Redis根據“swappability =

age*log(size_in_memory)”計

算出哪些key對應的value需要swap到磁盤。然後再將這些key對應的value持久化到磁盤中,同時在內存中清除。這種特性使得Redis可以

保持超過其機器本身內存大小的數據。當然,機器本身的內存必須要能夠保持所有的key,畢竟這些數據是不會進行swap操作的。同時由於Redis將內存

中的數據swap到磁盤中的時候,提供服務的主線程和進行swap操作的子線程會共享這部分內存,所以如果更新需要swap的數據,Redis將阻塞這個

操作,直到子線程完成swap操作後才可以進行修改。

使用Redis特有內存模型前後的情況對比:

VM off: 300k keys, 4096 bytes values: 1.3G used

VM on: 300k keys, 4096 bytes values: 73M used

VM off: 1 million keys, 256 bytes values: 430.12M used

VM on: 1 million keys, 256 bytes values: 160.09M used

VM on: 1 million keys, values as large as you want, still: 160.09M used

從Redis中讀取數據的時候,如果讀取的key對應的value不在內存中,那麼Redis就需要從swap文件中加載相應數據,然後再返回給請求方。

這裡就存在一個I/O線程池的問題。在默認的情況下,Redis會出現阻塞,即完成所有的swap文件加載後才會相應。這種策略在客戶端的數量較小,進行

批量操作的時候比較合適。但是如果將Redis應用在一個大型的網站應用程序中,這顯然是無法滿足大並發的情況的。所以Redis運行我們設置I/O線程

池的大小,對需要從swap文件中加載相應數據的讀取請求進行並發操作,減少阻塞的時間。

如果希望在海量數據的環境中使用好Redis,我相信理解Redis的內存設計和阻塞的情況是不可缺少的。

補充的知識點:

memcached和redis的比較

1 網絡IO模型

Memcached是多線程,非阻塞IO復用的網絡模型,分為監聽主線程和worker子線程,監聽線程監聽網絡連接,接受請求後,將連接描述

字pipe 傳遞給worker線程,進行讀寫IO, 網絡層使用libevent封裝的事件庫,多線程模型可以發揮多核作用,但是引入了cache

coherency和鎖的問題,比如,Memcached最常用的stats

命令,實際Memcached所有操作都要對這個全局變量加鎖,進行計數等工作,帶來了性能損耗。

(Memcached網絡IO模型)

Redis使用單線程的IO復用模型,自己封裝了一個簡單的AeEvent事件處理框架,主要實現了epoll、kqueue和select,

對於單純只有IO操作來說,單線程可以將速度優勢發揮到最大,但是Redis也提供了一些簡單的計算功能,比如排序、聚合等,對於這些操作,單線程模型實

際會嚴重影響整體吞吐量,CPU計算過程中,整個IO調度都是被阻塞住的。

2.內存管理方面

Memcached使用預分配的內存池的方式,使用slab和大小不同的chunk來管理內存,Item根據大小選擇合適的chunk存儲,內

存池的方式可以省去申請/釋放內存的開銷,並且能減小內存碎片產生,但這種方式也會帶來一定程度上的空間浪費,並且在內存仍然有很大空間時,新的數據也可

能會被剔除,原因可以參考Timyang的文章:

Redis使用現場申請內存的方式來存儲數據,並且很少使用free-list等方式來優化內存分配,會在一定程度上存在內存碎片,Redis

跟據存儲命令參數,會把帶過期時間的數據單獨存放在一起,並把它們稱為臨時數據,非臨時數據是永遠不會被剔除的,即便物理內存不夠,導致swap也不會剔

除任何非臨時數據(但會嘗試剔除部分臨時數據),這點上Redis更適合作為存儲而不是cache。

3.數據一致性問題

Memcached提供了cas命令,可以保證多個並發訪問操作同一份數據的一致性問題。 Redis沒有提供cas 命令,並不能保證這點,不過Redis提供了事務的功能,可以保證一串 命令的原子性,中間不會被任何操作打斷。

4.存儲方式及其它方面

Memcached基本只支持簡單的key-value存儲,不支持枚舉,不支持持久化和複製等功能

Redis除key/value之外,還支持list,set,sorted set,hash等眾多數據結構,提供了KEYS

進行枚舉操作,但不能在線上使用,如果需要枚舉線上數據,Redis提供了工具可以直接掃描其dump文件,枚舉出所有數據,Redis還同時提供了持久化和複製等功能。

5.關於不同語言的客戶端支持

在不同語言的客戶端方面,Memcached和Redis都有豐富的第三方客戶端可供選擇,不過因為Memcached發展的時間更久一些,目

前看在客戶端支持方面,Memcached的很多客戶端更加成熟穩定,而Redis由於其協議本身就比Memcached複雜,加上作者不斷增加新的功能

等,對應第三方客戶端跟進速度可能會趕不上,有時可能需要自己在第三方客戶端基礎上做些修改才能更好的使用。

根據以上比較不難看出,當我們不希望數據被踢出,或者需要除key/value之外的更多數據類型時,或者需要落地功能時,使用Redis比使用Memcached更合適。

關於Redis的一些周邊功能

Redis除了作為存儲之外還提供了一些其它方面的功能,比如聚合計算、pubsub、scripting等,對於此類功能需要了解其實現原

理,清楚地了解到它的局限性後,才能正確的使用,比如pubsub功能,這個實際是沒有任何持久化支持的,消費方連接閃斷或重連之間過來的消息是會全部丟

失的,又比如聚合計算和scripting等功能受Redis單線程模型所限,是不可能達到很高的吞吐量的,需要謹慎使用。

總的來說Redis作者是一位非常勤奮的開發者,可以經常看到作者在嘗試着各種不同的新鮮想法和思路,針對這些方面的功能就要求我們需要深入了解後再使用。

總結:

1.Redis使用最佳方式是全部數據in-memory。

2.Redis更多場景是作為Memcached的替代者來使用。

3.當需要除key/value之外的更多數據類型支持時,使用Redis更合適。

4.當存儲的數據不能被剔除時,使用Redis更合適。

談談Memcached與Redis(一)

1. Memcached簡介

Memcached是以LiveJurnal旗下Danga Interactive公司的Bard

Fitzpatric為首開發的高性能分布式內存緩存服務器。其本質上就是一個內存key-value數據庫,但是不支持數據的持久化,服務器關閉之後數

據全部丟失。Memcached使用C語言開發,在大多數像Linux、BSD和Solaris等POSIX系統上,只要安裝了libevent即可使

用。在Windows下,它也有一個可用的非官方版本()。Memcached

的客戶端軟件實現非常多,包括C/C++, PHP, Java, Python, Ruby, Perl, Erlang,

Lua等。當前Memcached使用廣泛,除了LiveJournal以外還有Wikipedia、Flickr、Twitter、Youtube和

WordPress等。

在Window系統下,Memcached的安裝非常方便,只需從以上給出的地址下載可執行軟件然後運行memcached.exe –d

install即可完成安裝。在Linux等系統下,我們首先需要安裝libevent,然後從獲取源碼,make make

install即可。默認情況下,Memcached的服務器啟動程序會安裝到/usr/local/bin目錄下。在啟動Memcached時,我們可

以為其配置不同的啟動參數。

1.1 Memcache配置

Memcached服務器在啟動時需要對關鍵的參數進行配置,下面我們就看一看Memcached在啟動時需要設定哪些關鍵參數以及這些參數的作用。

1)-p num Memcached的TCP監聽端口,缺省配置為11211;

2)-U num Memcached的UDP監聽端口,缺省配置為11211,為0時表示關閉UDP監聽;

3)-s file Memcached監聽的UNIX套接字路徑;

4)-a mask 訪問UNIX套接字的八進制掩碼,缺省配置為0700;

5)-l addr 監聽的服務器IP地址,默認為所有網卡;

6)-d 為Memcached服務器啟動守護進程;

7)-r 最大core文件大小;

8)-u username 運行Memcached的用戶,如果當前為root的話需要使用此參數指定用戶;

9)-m num 分配給Memcached使用的內存數量,單位是MB;

10)-M 指示Memcached在內存用光的時候返回錯誤而不是使用LRU算法移除數據記錄;

11)-c num 最大並發連數,缺省配置為1024;

12)-v –vv –vvv 設定服務器端打印的消息的詳細程度,其中-v僅打印錯誤和警告信息,-vv在-v的基礎上還會打印客戶端的命令和相應,-vvv在-vv的基礎上還會打印內存狀態轉換信息;

13)-f factor 用於設置chunk大小的遞增因子;

14)-n bytes 最小的chunk大小,缺省配置為48個字節;

15)-t num Memcached服務器使用的線程數,缺省配置為4個;

16)-L 嘗試使用大內存頁;

17)-R 每個事件的最大請求數,缺省配置為20個;

18)-C 禁用CAS,CAS模式會帶來8個字節的冗餘;

2. Redis簡介

Redis是一個開源的key-value存儲系統。與Memcached類似,Redis將大部分數據存儲在內存中,支持的數據類型包括:字

符串、哈希表、鏈表、集合、有序集合以及基於這些數據類型的相關操作。Redis使用C語言開發,在大多數像Linux、BSD和Solaris等

POSIX系統上無需任何外部依賴就可以使用。Redis支持的客戶端語言也非常豐富,常用的計算機語言如C、C#、C++、Object-C、PHP、

Python、Java、Perl、Lua、Erlang等均有可用的客戶端來訪問Redis服務器。當前Redis的應用已經非常廣泛,國內像新浪、淘

寶,國外像Flickr、Github等均在使用Redis的緩存服務。

Redis的安裝非常方便,只需從獲取源碼,然後make make

install即可。默認情況下,Redis的服務器啟動程序和客戶端程序會安裝到/usr/local/bin目錄下。在啟動Redis服務器時,我們

需要為其指定一個配置文件,缺省情況下配置文件在Redis的源碼目錄下,文件名為redis.conf。

大廠面試題詳解:如何用Redis實現分布式鎖?

說一道常見面試題:

一個很簡單的答案就是去使用 Redission 客戶端。Redission 中的鎖方案就是 Redis 分布式鎖得比較完美的詳細方案。

那麼,Redission 中的鎖方案為什麼會比較完美呢?

正好,我用 Redis 做分布式鎖經驗十分豐富,在實際工作中,也 探索 過許多種使用 Redis 做分布式鎖的方案,經過了無數血淚教訓。

所以,在談及 Redission 鎖為什麼比較完美之前,先給大家看看我曾經使用 Redis 做分布式鎖是遇到過的問題。

我曾經用 Redis 做分布式鎖是想去解決一個用戶搶優惠券的問題。這個業務需求是這樣的:當用戶領完一張優惠券後,優惠券的數量必須相應減一,如果優惠券搶光了,就不允許用戶再搶了。

在實現時,先從數據庫中先讀出優惠券的數量進行判斷,當優惠券大於 0,就進行允許領取優惠券,然後,再將優惠券數量減一後,寫回數據庫。

當時由於請求數量比較多,所以,我們使用了三台服務器去做分流。

這個時候會出現一個問題:

如果其中一台服務器上的 A 應用獲取到了優惠券的數量之後,由於處理相關業務邏輯,未及時更新數據庫的優惠券數量;在 A 應用處理業務邏輯的時候,另一台服務器上的 B 應用更新了優惠券數量。那麼,等 A 應用去更新數據庫中優惠券數量時,就會把 B 應用更新的優惠券數量覆蓋掉。

看到這裡,可能有人比較奇怪,為什麼這裡不直接使用 SQL:

原因是這樣做,在沒有分布式鎖的協調下,優惠券數量可能直接會出現負數。因為當前優惠券數量為 1 的時候,如果兩個用戶通過兩台服務器同時發起搶優惠券的請求,都滿足優惠券大於 0 每個條件,然後都執行這條 SQL 說了句,結果優惠券數量直接變成 -1 了。

還有人說可以用樂觀鎖,比如使用如下 SQL:

這種方式就在一定幾率下,很可能出現數據一直更新不上,導致長時間重試的情況。

所以,經過綜合考慮,我們就採用了 Redis 分布式鎖,通過互斥的方式,以防止多個客戶端同時更新優惠券數量的方案。

當時,我們首先想到的就是使用 Redis 的 setnx 命令,setnx 命令其實就是 set if not exists 的簡寫。

當 key 設置值成功後,則返回 1,否則就返回 0。所以,這裡 setnx 設置成功可以表示成獲取到鎖,如果失敗,則說明已經有鎖,可以被視作獲取鎖失敗。

如果想要釋放鎖,執行任務 del 指令,把 key 刪除即可。

利用這個特性,我們就可以讓系統在執行優惠券邏輯之前,先去 Redis 中執行 setnx 指令。再根據指令執行結果,去判斷是否獲取到鎖。如果獲取到了,就繼續執行業務,執行完再使用 del 指令去釋放鎖。如果沒有獲取到,就等待一定時間,重新再去獲取鎖。

乍一看,這一切沒什麼問題,使用 setnx 指令確實起到了想要的互斥效果。

但是,這是建立在所有運行環境都是正常的情況下的。一旦運行環境出現了異常,問題就出現了。

想一下,持有鎖的應用突然崩潰了,或者所在的服務器宕機了,會出現什麼情況?

這會造成死鎖——持有鎖的應用無法釋放鎖,其他應用根本也沒有機會再去獲取鎖了。這會造成巨大的線上事故,我們要改進方案,解決這個問題。

怎麼解決呢?咱們可以看到,造成死鎖的根源是,一旦持有鎖的應用出現問題,就不會去釋放鎖。從這個方向思考,可以在 Redis 上給 key 一個過期時間。

這樣的話,即使出現問題,key 也會在一段時間後釋放,是不是就解決了這個問題呢?實際上,大家也確實是這麼做的。

不過,由於 setnx 這個指令本身無法設置超時時間,所以一般會採用兩種辦法來做這件事:

1、採用 lua 腳本,在使用 setnx 指令之後,再使用 expire 命令去給 key 設置過期時間。

2、直接使用 set(key,value,NX,EX,timeout) 指令,同時設置鎖和超時時間。

以上兩種方法,使用哪種方式都可以。

釋放鎖的腳本兩種方式都一樣,直接調用 Redis 的 del 指令即可。

到目前為止,我們的鎖既起到了互斥效果,又不會因為某些持有鎖的系統出現問題,導致死鎖了。這樣就完美了嗎?

假設有這樣一種情況,如果一個持有鎖的應用,其持有的時間超過了我們設定的超時時間會怎樣呢?會出現兩種情況:

出現第一種情況比較正常。因為你畢竟執行任務超時了,key 被正常清除也是符合邏輯的。

但是最可怕的是第二種情況,發現設置的 key 還存在。這說明什麼?說明當前存在的 key,是另外的應用設置的。

這時候如果持有鎖超時的應用調用 del 指令去刪除鎖時,就會把別人設置的鎖誤刪除,這會直接導致系統業務出現問題。

所以,為了解決這個問題,我們需要繼續對 Redis 腳本進行改動……毀滅吧,累了……

首先,我們要讓應用在獲取鎖的時候,去設置一個只有應用自己知道的獨一無二的值。

通過這個唯一值,系統在釋放鎖的時候,就能識別出這鎖是不是自己設置的。如果是自己設置的,就釋放鎖,也就是刪除 key;如果不是,則什麼都不做。

腳本如下:

或者

這裡,ARGV[1] 是一個可傳入的參數變量,可以傳入唯一值。比如一個只有自己知道的 UUID 的值,或者通過雪球算法,生成只有自己持有的唯一 ID。

釋放鎖的腳本改成這樣:

可以看到,從業務角度,無論如何,我們的分布式鎖已經可以滿足真正的業務需求了。能互斥,不死鎖,不會誤刪除別人的鎖,只有自己上的鎖,自己可以釋放。

一切都是那麼美好!!!

可惜,還有個隱患,我們並未排除。這個隱患就是 Redis 自身。

要知道,lua 腳本都是用在 Redis 的單例上的。一旦 Redis 本身出現了問題,我們的分布式鎖就沒法用了,分布式鎖沒法用,對業務的正常運行會造成重大影響,這是我們無法接受的。

所以,我們需要把 Redis 搞成高可用的。一般來講,解決 Redis 高可用的問題,都是使用主從集群。

但是搞主從集群,又會引入新的問題。主要問題在於,Redis 的主從數據同步有延遲。這種延遲會產生一個邊界條件:當主機上的 Redis 已經被人建好了鎖,但是鎖數據還未同步到從機時,主機宕了。隨後,從機提升為主機,此時從機上是沒有以前主機設置好的鎖數據的——鎖丟了……丟了……了……

到這裡,終於可以介紹 Redission(開源 Redis 客戶端)了,我們來看看它怎麼是實現 Redis 分布式鎖的。

Redission 實現分布式鎖的思想很簡單,無論是主從集群還是 Redis Cluster 集群,它會對集群中的每個 Redis,挨個去執行設置 Redis 鎖的腳本,也就是集群中的每個 Redis 都會包含設置好的鎖數據。

我們通過一個例子來介紹一下。

假設 Redis 集群有 5 台機器,同時根據評估,鎖的超時時間設置成 10 秒比較合適。

第 1 步,咱們先算出集群總的等待時間,集群總的等待時間是 5 秒(鎖的超時時間 10 秒 / 2)。

第 2 步,用 5 秒除以 5 台機器數量,結果是 1 秒。這個 1 秒是連接每台 Redis 可接受的等待時間。

第 3 步,依次連接 5 台 Redis,並執行 lua 腳本設置鎖,然後再做判斷:

再額外多說一句,在很多業務邏輯里,其實對鎖的超時時間是沒有需求的。

比如,凌晨批量執行處理的任務,可能需要分布式鎖保證任務不會被重複執行。此時,任務要執行多長時間是不明確的。如果設置分布式鎖的超時時間在這裡,並沒有太大意義。但是,不設置超時時間,又會引發死鎖問題。

所以,解決這種問題的通用辦法是,每個持有鎖的客戶端都啟動一個後台線程,通過執行特定的 lua 腳本,去不斷地刷新 Redis 中的 key 超時時間,使得在任務執行完成前,key 不會被清除掉。

腳本如下:

其中,ARGV[1] 是可傳入的參數變量,表示持有鎖的系統的唯一值,也就是只有持有鎖的客戶端才能刷新 key 的超時時間。

到此為止,一個完整的分布式鎖才算實現完畢。總結實現方案如下:

這個分布式鎖滿足如下四個條件:

當然,在 Redission 中的腳本,為了保證鎖的可重入,又對 lua 腳本做了一定的修改,現在把完整的 lua 腳本貼在下面。

獲取鎖的 lua 腳本:

對應的刷新鎖超時時間的腳本:

對應的釋放鎖的腳本:

到現在為止,使用 Redis 作為分布式鎖的詳細方案就寫完了。

我既寫了一步一坑的坎坷經歷,也寫明了各個問題和解決問題的細節,希望大家看完能有所收穫。

最後再給大家提個醒,使用 Redis 集群做分布式鎖,有一定的爭議性,還需要大家在實際用的時候,根據現實情況,做出更好的選擇和取捨。

原文

「乾貨」redis面試題

Redis 的全稱是:Remote Dictionary.Server,本質上是一個 Key-Value 類型的內存數據庫,很像

memcached,整個數據庫統統加載在內存當中進行操作,定期通過異步操作把數據庫數據 flush 到硬盤

上進行保存。

因為是純內存操作,Redis 的性能非常出色,每秒可以處理超過 10 萬次讀寫操作,是已知性能最快的

Key-Value DB。

Redis 的出色之處不僅僅是性能,Redis 最大的魅力是支持保存多種數據結構,此外單個 value 的最大限

制是 1GB,不像 memcached 只能保存 1MB 的數據,因此 Redis 可以用來實現很多有用的功能。

比方說用他的 List 來做 FIFO 雙向鏈表,實現一個輕量級的高性 能消息隊列服務,用他的 Set 可以做高

性能的 tag 系統等等。

另外 Redis 也可以對存入的 Key-Value 設置 expire 時間,因此也可以被當作一 個功能加強版的

memcached 來用。 Redis 的主要缺點是數據庫容量受到物理內存的限制,不能用作海量數據的高性能

讀寫,因此 Redis 適合的場景主要局限在較小數據量的高性能操作和運算上。

1.memcached 所有的值均是簡單的字符串,redis 作為其替代者,支持更為豐富的數據類型

2.redis 的速度比 memcached 快很多 redis 的速度比 memcached 快很多

3.redis 可以持久化其數據 redis 可以持久化其數據

String、List、Set、Sorted Set、hashes

內存。

1.noeviction:返回錯誤當內存限制達到,並且客戶端嘗試執行會讓更多內存被使用的命令。

2.allkeys-lru: 嘗試回收最少使用的鍵(LRU),使得新添加的數據有空間存放。

3.volatile-lru: 嘗試回收最少使用的鍵(LRU),但僅限於在過期集合的鍵,使得新添加的數據有空間存

放。

4.allkeys-random: 回收隨機的鍵使得新添加的數據有空間存放。

5.volatile-random: 回收隨機的鍵使得新添加的數據有空間存放,但僅限於在過期集合的鍵。

6.volatile-ttl: 回收在過期集合的鍵,並且優先回收存活時間(TTL)較短的鍵,使得新添加的數據有空間

存放。

因為目前 Linux 版本已經相當穩定,而且用戶量很大,無需開發 windows 版本,反而會帶來兼容性等問

題。

512M

Redis 為了達到最快的讀寫速度將數據都讀到內存中,並通過異步的方式將數據寫入磁盤。

所以 redis 具有快速和數據持久化的特徵,如果不將數據放在內存中,磁盤 I/O 速度為嚴重影響 redis 的

性能。

在內存越來越便宜的今天,redis 將會越來越受歡迎, 如果設置了最大使用的內存,則數據已有記錄數達

到內存限值後不能繼續插入新值。

1.codis 2.目前用的最多的集群方案,基本和 twemproxy 一致的效果,但它支持在節點數量改變情況下,舊節點

數據可恢復到新 hash 節點。

redis cluster3.0 自帶的集群,特點在於他的分布式算法不是一致性 hash,而是 hash 槽的概念,以及自

身支持節點設置從節點。具體看官方文檔介紹。

3.在業務代碼層實現,起幾個毫無關聯的 redis 實例,在代碼層,對 key 進行 hash 計算,然後去對應的

redis 實例操作數據。這種方式對 hash 層代碼要求比較高,考慮部分包括,節點失效後的替代算法方

案,數據震蕩後的自動腳本恢復,實例的監控,等等。

有 A,B,C 三個節點的集群,在沒有複製模型的情況下,如果節點 B 失敗了,那麼整個集群就會以為缺少

5501-11000 這個範圍的槽而不可用。

redis 內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略。

(1)會話緩存(Session Cache)

最常用的一種使用 Redis 的情景是會話緩存(sessioncache),用 Redis 緩存會話比其他存儲(如

Memcached)的優勢在於:Redis 提供持久化。當維護一個不是嚴格要求一致性的緩存時,如果用戶的

購物車信息全部丟失,大部分人都會不高興的,現在,他們還會這樣嗎?

幸運的是,隨着 Redis 這些年的改進,很容易找到怎麼恰當的使用 Redis 來緩存會話的文檔。甚至廣為

人知的商業平台 Magento 也提供 Redis 的插件。

(2)全頁緩存(FPC)

除基本的會話 token 之外,Redis 還提供很簡便的 FPC 平台。回到一致性問題,即使重啟了 Redis 實

例,因為有磁盤的持久化,用戶也不會看到頁面加載速度的下降,這是一個極大改進,類似 PHP 本地

FPC。

再次以 Magento 為例,Magento 提供一個插件來使用 Redis 作為全頁緩存後端。

此外,對 WordPress 的用戶來說,Pantheon 有一個非常好的插件 wp-redis,這個插件能幫助你以最快

速度加載你曾瀏覽過的頁面。

(3)隊列

Reids 在內存存儲引擎領域的一大優點是提供 list 和 set 操作,這使得 Redis 能作為一個很好的消息隊列

平台來使用。Redis 作為隊列使用的操作,就類似於本地程序語言(如 Python)對 list 的 push/pop

操作。

如果你快速的在 Google 中搜索“Redis queues”,你馬上就能找到大量的開源項目,這些項目的目的

就是利用 Redis 創建非常好的後端工具,以滿足各種隊列需求。例如,Celery 有一個後台就是使用

Redis 作為 broker,你可以從這裡去查看。

(4)排行榜/計數器 Redis 在內存中對數字進行遞增或遞減的操作實現的非常好。集合(Set)和有序集合(SortedSet)也使

得我們在執行這些操作的時候變的非常簡單,Redis 只是正好提供了這兩種數據結構。

所以,我們要從排序集合中獲取到排名最靠前的 10 個用戶–我們稱之為“user_scores”,我們只需要像

下面一樣執行即可:

當然,這是假定你是根據你用戶的分數做遞增的排序。如果你想返回用戶及用戶的分數,你需要這樣執

行:

ZRANGE user_scores 0 10 WITHSCORES

Agora Games 就是一個很好的例子,用 Ruby 實現的,它的排行榜就是使用 Redis 來存儲數據的,你可

以在這裡看到。

立聊天系統!

Redisson、Jedis、lettuce 等等,官方推薦使用 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)。

Jedis 是 Redis 的 Java 實現的客戶端,其 API 提供了比較全面的 Redis 命令的支持;

Redisson 實現了分布式和可擴展的 Java 數據結構,和 Jedis 相比,功能較為簡單,不支持字符串操作,

Redis 集群沒有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 個哈希槽,每個 key 通

過 CRC16 校驗後對 16384 取模來決定放置哪個槽,集群的每個節點負責一部分 hash 槽。

為了使在部分節點失敗或者大部分節點無法通信的情況下集群仍然可用,所以集群使用了主從複製模型,

每個節點都會有 N-1 個複製品.

Redis 並不能保證數據的強一致性,這意味這在實際中集群在特定的條件下可能會丟失寫操作。

異步複製

16384 個

Redis 集群目前無法做數據庫選擇,默認在 0 數據庫。

一次請求/響應服務器能實現處理新的請求即使舊的請求還未被響應,這樣就可以將多個命令發送到服務

器,而不用等待回復,最後在一個步驟中讀取該答覆。

這就是管道(pipelining),是一種幾十年來廣泛使用的技術。例如許多 POP3 協議已經實現支持這個功

能,大大加快了從服務器下載新郵件的過程。

事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行,事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。

事務是一個原子操作:事務中的命令要麼全部被執行,要麼全部都不執行。

MULTI、EXEC、DISCARD、WATCH

EXPIRE 和 PERSIST 命令

儘可能使用散列表(hashes),散列表(是說散列表裡面存儲的數少)使用的內存非常小,所以你應該儘可能的將你的數據模型抽象到一個散列表裡面。

比如你的 web 系統中有一個用戶對象,不要為這個用戶的名稱,姓氏,郵箱,密碼設置單獨的 key,而是應該把這個用戶的所有信息存儲到一張散列表裡面。

一個客戶端運行了新的命令,添加了新的數據。Redi 檢查內存使用情況,如果大於 maxmemory 的限制, 則根據設定好的策略進行回收。一個新的命令被執行,等等。

所以我們不斷地穿越內存限制的邊界,通過不斷達到邊界然後不斷地回收回到邊界以下。

如果一個命令的結果導致大量內存被使用(例如很大的集合的交集保存到一個新的鍵),不用多久內存限制就會被這個內存使用量超越。

咱們來看上面那張圖,現在某個客戶端要加鎖。如果該客戶端面對的是一個 redis cluster 集 群,他首先會根據 hash 節點選擇一台機器。這裡注意,僅僅只是選擇一台機器!這點很關 鍵!緊接着,就會發送一段 lua 腳本到 redis 上,那段 lua 腳本如下所示:

為啥要用 lua 腳本呢?因為一大坨複雜的業務邏輯,可以通過封裝在 lua 腳本中發送給 redis, 保證這段複雜業務邏輯執行的原子性。

那麼,這段 lua 腳本是什麼意思呢?這裡 KEYS[1]代表的是你加鎖的那個 key,比如說:RLoc

k lock = redisson.getLock(“myLock”);這裡你自己設置了加鎖的那個鎖 key 就是“myLock”。

ARGV[1]代表的就是鎖 key 的默認生存時間,默認 30 秒。ARGV[2]代表的是加鎖的客戶端的 I D,類似於下面這樣:8743c9c0-0795-4907-87fd-6c719a6b4586:1

給大家解釋一下,第一段 if 判斷語句,就是用“exists myLock”命令判斷一下,如果你要加鎖 的那個鎖 key 不存在的話,你就進行加鎖。如何加鎖呢?很簡單,用下面的命令:hset myLoc k 8743c9c0-0795-4907-87fd-6c719a6b4586:1 1,通過這個命令設置一個 hash 數據結構,這行 命令執行後,會出現一個類似下面的數據結構:

上述就代表“8743c9c0-0795-4907-87fd-6c719a6b4586:1”這個客戶端對“myLock”這個鎖 key 完 成了加鎖。接着會執行“pexpire myLock 30000”命令,設置 myLock 這個鎖 key 的生存時間 是 30 秒。好了,到此為止,ok,加鎖完成了。

那麼在這個時候,如果客戶端 2 來嘗試加鎖,執行了同樣的一段 lua 腳本,會咋樣呢?很簡 單,第一個 if 判斷會執行“exists myLock”,發現 myLock 這個鎖 key 已經存在了。接着第二 個 if 判斷,判斷一下,myLock 鎖 key 的 hash 數據結構中,是否包含客戶端 2 的 ID,但是明 顯不是的,因為那裡包含的是客戶端 1 的 ID。

所以,客戶端 2 會獲取到 pttl myLock 返回的一個數字,這個數字代表了 myLock 這個鎖 key 的剩餘生存時間。比如還剩 15000 毫秒的生存時間。此時客戶端 2 會進入一個 while 循環,不 停的嘗試加鎖。

客戶端 1 加鎖的鎖 key 默認生存時間才 30 秒,如果超過了 30 秒,客戶端 1 還想一直持有這把 鎖,怎麼辦呢?

簡單!只要客戶端 1 一旦加鎖成功,就會啟動一個 watch dog 看門狗,他是一個後台線程,會 每隔 10 秒檢查一下,如果客戶端 1 還持有鎖 key,那麼就會不斷的延長鎖 key 的生存時間。

31.可重入加鎖機制

那如果客戶端 1 都已經持有了這把鎖了,結果可重入的加鎖會怎麼樣呢?比如下面這種代碼:

這時我們來分析一下上面那段 lua 腳本。第一個 if 判斷肯定不成立,“exists myLock”會顯示鎖 key 已經存在了。第二個 if 判斷會成立,因為 myLock 的 hash 數據結構中包含的那個 ID,就 是客戶端 1 的那個 ID,也就是“8743c9c0-0795-4907-87fd-6c719a6b4586:1” 此時就會執行可重入加鎖的邏輯,他會用:

incrby myLock 8743c9c0-0795-4907-87fd-6c71a6b4586:1 1 ,通過這個命令,對客戶端 1 的加鎖次數,累加 1。此時 myLock 數據結構變為下面這樣:

大家看到了吧,那個 myLock 的 hash 數據結構中的那個客戶端 ID,就對應着加鎖的次數

如果執行 lock.unlock(),就可以釋放分布式鎖,此時的業務邏輯也是非常簡單的。其實說白 了,就是每次都對 myLock 數據結構中的那個加鎖次數減 1。如果發現加鎖次數是 0 了,說明 這個客戶端已經不再持有鎖了,此時就會用:“del myLock”命令,從 redis 里刪除這個 key。 然後呢,另外的客戶端 2 就可以嘗試完成加鎖了。這就是所謂的分布式鎖的開源 Redisson 框 架的實現機制。

一般我們在生產系統中,可以用 Redisson 框架提供的這個類庫來基於 redis 進行分布式鎖的加 鎖與釋放鎖。

其實上面那種方案最大的問題,就是如果你對某個 redis master 實例,寫入了 myLock 這種鎖 key 的 value,此時會異步複製給對應的 master slave 實例。但是這個過程中一旦發生 redis m aster 宕機,主備切換,redis slave 變為了 redis master。

接着就會導致,客戶端 2 來嘗試加鎖的時候,在新的 redis master 上完成了加鎖,而客戶端 1 也以為自己成功加了鎖。此時就會導致多個客戶端對一個分布式鎖完成了加鎖。這時系統在業 務語義上一定會出現問題,導致各種臟數據的產生。

所以這個就是 redis cluster,或者是 redis master-slave 架構的主從異步複製導致的 redis 分布 式鎖的最大缺陷:在 redis master 實例宕機的時候,可能導致多個客戶端同時完成加鎖。

先拿 setnx 來爭搶鎖,搶到之後,再用 expire 給鎖加一個過期時間防止鎖忘記了釋放。

如果在 setnx 之後執行 expire 之前進程意外 crash 或者要重啟維護了,那會怎麼樣?

set 指令有非常複雜的參數,這個應該是可以同時把 setnx 和 expire 合成一條指令來用的!

緩存穿透

一般的緩存系統,都是按照 key 去緩存查詢,如果不存在對應的 value,就應該去後端系統查找(比如DB)。一些惡意的請求會故意查詢不存在的 key,請求量很大,就會對後端系統造成很大的壓力。這就叫做緩存穿透。

如何避免?

1:對查詢結果為空的情況也進行緩存,緩存時間設置短一點,或者該 key 對應的數據 insert 了之後清理緩存。

2:對一定不存在的 key 進行過濾。可以把所有的可能存在的 key 放到一個大的 Bitmap 中,查詢時通過該 bitmap 過濾。

緩存雪崩

當緩存服務器重啟或者大量緩存集中在某一個時間段失效,這樣在失效的時候,會給後端系統帶來很大壓力。導致系統崩潰。

如何避免?

1:在緩存失效後,通過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。比如對某個 key 只允許一個線程查詢數據和寫緩存,其他線程等待。

2:做二級緩存,A1 為原始緩存,A2 為拷貝緩存,A1 失效時,可以訪問 A2,A1 緩存失效時間設置為短期,A2 設置為長期

3:不同的 key,設置不同的過期時間,讓緩存失效的時間點盡量均勻

面試中問到Redis持久化的原理,本篇在做詳細解答

我們知道redis是一個 高效的分布式內存數據庫 ,由於是操作內存所以性能非常之快,通常用它來做分布式緩存,用來提高微服務的高性能,但是因為是內存操作,所以當出現服務器故障,斷電等情況就會造成 內存數據丟失 ,不可恢復,因此redis 引入了持久化機制來將內存數據寫入磁盤,從而保障了Redis的數據不被丟失。

Redis有兩種持久化的方式,一種是RDB,另外種是AOF。

RDB是將Redis內存中數據的快照存儲在磁盤內,是Redis的默認持久化方案。

RDB持久化默認有三種策略

可在redis.conf中配置,會以一段時間內達到指定修改的次數為規則來觸發快照操作,快照文件名為dump.rdb。每當Redis服務重啟的時候都會從該文件中把數據加載到內存中。

在60秒內有10000次操作即觸發RDB持久化。

沒有滿足第一種條件時,在900秒內有1次操作即觸發RDB持久化。

沒有滿足第二種條件時,在300秒內有10次操作即觸發RDB持久化。

RDB持久化除了可以根據配置中的策略來觸發外,還可以使用save和bgsave命令手動來觸發。這兩個命令的區別在於save會阻塞服務器進程。在執行save命令的過程中,服務器不能處理任何請求,但是bgsave(background save,後台保存)命令會通過一個子進程在後台處理數據RDB持久化。本質上save和bgsave調用的都是rdbSave函數,所以Redis不允許save和bgsave命令同時執行,當然這也是為了避免RDB文件數據出現不一致性的問題。

每次都是一個大文件,備份寫入IO操作筆記大,很容易耗時,影響進程資源使用。

如果最近一次進程崩潰,那麼最近一次數據備份後的數據就被丟失。

文件直接就可以當冷備使用

AOF(Append Only File)以獨立日誌的方式記錄每次的寫命令,可以很好地解決了數據持久化的實時性。系統重啟時可以重新執行AOF文件中的命令來恢複數據。AOF會先把命令追加在AOF緩衝區,然後根據對應策略寫入硬盤。

AOF的實現流程有三個步驟

步驟一

把命令追加到AOF緩衝區,

步驟二

將緩衝區的內容寫入程序緩衝區

步驟三

將程序緩衝區的內容寫入文件

當AOF持久化功能處於開啟狀態時,服務器每執行完一個命令就會將命令以協議格式追加寫入redisServer結構體的aof_buf緩衝區。而在服務重啟的時候會把AOF文件加載到緩衝區中。

AOF有 三種觸發機制

·always:每次發生數據變更都會被立即記錄到磁盤,性能較差,但數據完整性比較好。

·everysec:每秒鐘將aof_buf緩衝區的內容寫入AOF文件,如果宕機,就會有1秒內的數據丟失。

·no:將數據同步操作交給操作系統來處理,性能最好,但是數據可靠性最差。在配置文件中設置appendonly=yes後,若沒有指定apendfsync,默認會使用everysec選項。

寫入指令隨着時間的推移,記錄了很多重複的指令,導致數據量非常大。

RDB優先級高於AOF

RDB小,AOF較大

RDB慢,AOF快

RDB快,AOF慢

技術面試應該問些什麼?應聘者應該如何應對?

最近經歷了一波面試,個人談一談心得感受。

首先我發現很多面試官根本不知道要問些什麼?想到哪問到哪。應聘者可能幾個回答的他比較滿意就覺得還不錯,又或者幾個不滿意就覺得不好。這樣是片面的,也盲目和缺乏目標的。我覺得這樣的面試官是不合格的。根本不能有效的為企業找到合適的人才。

怎麼樣更好的為企業招到真正需要的人才呢?

我認為,首先要有清晰的目標,公司招聘的目的是做什麼?崗位的基本要求是什麼?這個崗位未來可能會有什麼樣的發展等。

基於以上原因我覺得招聘面試的內容也分為兩種類型。必須的和擴展的。

什麼是必須的呢?

就是如果必須的知識點超過三個不清楚就可以判斷為不合格,因為這是工作中一定會用到的,或者可能性極大會用到的。如果不懂可能會影響工作的進展。

擴展的就是理論,概念,其他方案,深度了解程度等。這方面的了解是加法項,了解的越多,越深越好。但如果不是太了解,在沒有更好的候選人的時候也是可以考慮的。

最後呢,作為面試官一定技術夠紮實,夠深度。因為技術能力不夠就很難招到技術較好的人。也不要以個人好惡來評判,要站在公司高層的高度去看待,最好多個人面試。避免因個人原因招到同一類性格的人。對團隊的健康發展不利。

但作為應聘者應該怎樣應對那些不合格的招聘者呢?

我覺得,你要主動出擊,引導面試官的問題。因為如果面試官問一個你答一個,不發揮,不引導出你熟悉的技術,就失去展秀自己的機會。另外,很多面試官也不知道問什麼,通常想到什就問什麼。這樣,通常他會問自己擅長的點,因為每個人的擅長的點是不一樣的,萬一問到你不擅長的領域你就被動了。更甚至給面試官你技術不好的印象,殊不知有可能他問的不全面而已,但他會以偏概全的以為你不合適。

比如:當面試官問你redis熟悉嗎?你就要把你了解的redis相關的技術點大概說一下,比如數據結構,使用場景,雪崩,擊穿,穿透,存儲模型,高可用,集群等。

這樣面試官很可能基於你列到的知識點問一問,因為他也沒去想到要問什麼,就是順勢去聊了。當然你列出的知識點你還是比較熟悉的,剛好給自己展現的機會,也給面試官留下較好的印象。

相反,如果你僅僅回答個:熟悉。

那麼面試官此刻也沒想好該問什麼,他很可能挑自己比較熟悉的知識點問。可能他最近在研究內存模型,他極大可能問這個,而你這方面不太熟悉,必然回答的支支吾吾。好吧,面試官知道你不懂,便又想到一個他熟悉的問題。如果剛好你也不懂這個知識點,那麼面試官可能就認為你Redis不熟悉。就這樣兩個問題就把你的Redis給pass了,其實你Redis還是蠻熟的,只是對內存方面不太熟而已。接着,他可能會問MySQL,如果又剛好遇到類似的問題,那麼你基本上就掛了。

反觀上面兩種場景,一個其樂融融,一個不歡而散。是不是引導很重要呢。當然如果是一個較為合格面試官就不會出現這樣的情況。因為必須的知識點和擴展知識點他列的很清楚,無論你引導與否,他都會問及,這就要看你的基本功了。

另外,如果問及到你管理方面的知識,說明這個崗位會有管理傾向,一定要站在管理者的角度去思考,認真回答好。我曾經就在技術崗面試時問到管理方面,當時就隨便說說,以為技術崗,這方面隨便聊聊而已。後來才知道,原來人家還是偏管理崗的。所以每一個問題都認真對待吧。

祝你好運!

大家覺得我說的有道理嗎?歡迎批評指正!

後續會加一些 PHP 技術面試題及答案,都是個人總結,未必準確,僅供參考。喜歡的朋友可以先關注下。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/259641.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-15 16:29
下一篇 2024-12-15 16:30

相關推薦

  • PHP和Python哪個好找工作?

    PHP和Python都是非常流行的編程語言,它們被廣泛應用於不同領域的開發中。但是,在考慮擇業方向的時候,很多人都會有一個問題:PHP和Python哪個好找工作?這篇文章將從多個方…

    編程 2025-04-29
  • OpenJudge答案1.6的C語言實現

    本文將從多個方面詳細闡述OpenJudge答案1.6在C語言中的實現方法,幫助初學者更好地學習和理解。 一、需求概述 OpenJudge答案1.6的要求是,輸入兩個整數a和b,輸出…

    編程 2025-04-29
  • PHP怎麼接幣

    想要在自己的網站或應用中接受比特幣等加密貨幣的支付,就需要對該加密貨幣擁有一定的了解,並使用對應的API進行開發。本文將從多個方面詳細闡述如何使用PHP接受加密貨幣的支付。 一、環…

    編程 2025-04-29
  • 學堂雲Python語言程序設計答案

    學堂雲Python語言程序設計是一門重要的計算機專業課程。它涵蓋了Python語言及其應用,包括基礎語法、函數、文件處理、數據結構、圖形界面和網絡編程等內容。在學習中,我們經常會需…

    編程 2025-04-29
  • 南京郵電大學Python慕課答案

    本文將詳細闡述南京郵電大學Python慕課答案,為大家提供學習Python課程的參考。 一、應用範圍 Python是一種高級通用編程語言,應用範圍廣泛,包括Web開發、數據分析與科…

    編程 2025-04-28
  • 大學化學科學出版社教材答案

    本文將從以下幾個方面對大學化學科學出版社教材答案進行詳細闡述,幫助您更好地應對學習中的問題: 一、獲取教材答案的渠道 學習過程中,有時候會遇到難以解答的問題,這時候就需要查看教材答…

    編程 2025-04-28
  • Python初探答案第七關——解題指南

    Python初探答案第七關是一道典型的Python編程題目,涉及字符串的判斷和操作。下面我們將從多個方面詳細闡述這道題目的解題方法。 一、題目分析 首先,我們需要仔細研究題目要求以…

    編程 2025-04-28
  • 使用PHP foreach遍歷有相同屬性的值

    本篇文章將介紹如何使用PHP foreach遍歷具有相同屬性的值,並給出相應的代碼示例。 一、基礎概念 在講解如何使用PHP foreach遍歷有相同屬性的值之前,我們需要先了解幾…

    編程 2025-04-28
  • 在CentOS上安裝Redis

    Redis是一款非關係型數據庫,它支持多種數據結構,包括字符串、哈希、列表、集合、有序集合等。Redis運行內存內並且支持數據持久化,它還可以應用於緩存、消息隊列等場景。本文將介紹…

    編程 2025-04-28
  • 小甲魚Python課後作業及答案百度雲

    小甲魚課程是一門 Python 開發的視頻課程,自 2008 年以來一直廣受歡迎。本文主要介紹小甲魚 Python 課後作業及答案所在的百度雲地址。以下是詳細內容: 一、百度雲地址…

    編程 2025-04-27

發表回復

登錄後才能評論