Python面試題解析之數據庫與緩存

python面試題解析(數據庫和緩存)

 
  1. 答:

關係型數據庫:Mysql,Oracel,Microsoft SQL Serverpython

非關係型數據庫:MongoDB,memcache,Redis。mysql

 

  1. 答:

     MyISAM:在Web、數據倉儲和其餘應用環境下最常使用的存儲引擎之一。linux

  InnoDB:用於事務處理應用程序,具備衆多特性,包括ACID事務支持(提供行級鎖),Mysql在V5.1以前默認存儲引擎是MyISAM;在此以後默認存儲引擎是InnoDB面試

  BDB:可替代InnoDB的事務引擎,支持COMMIT、ROLLBACK和其餘事務特性。redis

  Memory:將全部數據保存在RAM中,在須要快速查找引用和其餘相似數據的環境下,可提供極快的訪問。sql

  Merge:容許MySQL DBA或開發人員將一系列等同的MyISAM表以邏輯方式組合在一塊兒,並做爲1個對象引用它們。對於諸如數據倉儲等VLDB環境十分適合。數據庫

  Archive:爲大量不多引用的歷史、歸檔、或安全審計信息的存儲和檢索提供了完美的解決方案。編程

  Federated:可以將多個分離的MySQL服務器連接起來,從多個物理服務器建立一個邏輯數據庫。十分適合於分佈式環境或數據集市環境。windows

  Cluster/NDB:MySQL的簇式數據庫引擎,尤爲適合於具備高性能查找要求的應用程序,這類查找需求還要求具備最高的正常工做時間和可用性。緩存

Other:其餘存儲引擎包括CSV(引用由逗號隔開的用做數據庫表的文件),Blackhole(用於臨時禁止對數據庫的應用程序輸入),以及Example引擎(可爲快速建立定製的插件式存儲引擎提供幫助)。

 

  1. 答:

第一範式:確保每列的原子性.
    若是每列(或者每一個屬性)都是不可再分的最小數據單元(也稱爲最小的原子單元),則知足第一範式.
    例如:顧客表(姓名、編號、地址、……)其中"地址"列還能夠細分爲國家、省、市、區等。

第二範式:在第一範式的基礎上更進一層,目標是確保表中的每列都和主鍵相關.
    例如:訂單表(訂單編號、產品編號、定購日期、價格、……),"訂單編號"爲主鍵,"產品編號"和主鍵列沒有直接的關係,即"產品編號"列不依賴於主鍵列,應刪除該列。

第三範式:在第二範式的基礎上更進一層,目標是確保每列都和主鍵列直接相關,而不是間接相關.
    爲了理解第三範式,須要根據Armstrong千米之必定義傳遞依賴。假設A、B和C是關係R的三個屬性,若是A-〉B且B-〉C,則從這些函數依賴中,能夠得出A-〉C,如上所述,依賴A-〉C是傳遞依賴。
    例如:訂單表(訂單編號,定購日期,顧客編號,顧客姓名,……),初看該表沒有問題,知足第二範式,每列都和主鍵列"訂單編號"相關,再細看你會發現"顧客姓名"和"顧客編號"相關,"顧客編號"和"訂單編號"又相關,最後通過傳遞依賴,"顧客姓名"也和"訂單編號"相關。爲了知足第三範式,應去掉"顧客姓名"列,放入客戶表中。

4.答:

       通常來講,事務是必須知足4個條件(ACID)::原子性(Atomicity,或稱不可分割性)、一致性(Consistency)、隔離性(Isolation,又稱獨立性)、持久性(Durability)。

原子性:一個事務(transaction)中的全部操做,要麼所有完成,要麼所有不完成,不會結束在中間某個環節。事務在執行過程當中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務歷來沒有執行過同樣。

一致性:在事務開始以前和事務結束之後,數據庫的完整性沒有被破壞。這表示寫入的資料必須徹底符合全部的預設規則,這包含資料的精確度、串聯性以及後續數據庫能夠自發性地完成預約的工做。

隔離性:數據庫容許多個併發事務同時對其數據進行讀寫和修改的能力,隔離性能夠防止多個事務併發執行時因爲交叉執行而致使數據的不一致。事務隔離分爲不一樣級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和串行化(Serializable)。

持久性:事務處理結束後,對數據的修改就是永久的,即使系統故障也不會丟失。

 

MYSQL 事務處理主要有兩種方法:

一、用 BEGIN, ROLLBACK, COMMIT來實現

BEGIN 開始一個事務

ROLLBACK 事務回滾

COMMIT 事務確認

二、直接用 SET 來改變 MySQL 的自動提交模式:

SET AUTOCOMMIT=0 禁止自動提交

SET AUTOCOMMIT=1 開啓自動提交

 

5. 答:

做者模型:一個做者有姓名。

做者詳細模型:把做者的詳情放到詳情表,包含性別,email地址和出生日期,做者詳情模型和做者模型之間是一對一的關係(one-to-one)(相似於每一個人和他的身份證之間的關係),在大多數狀況下咱們沒有必要將他們拆分紅兩張表,這裏只是引出一對一的概念。

出版商模型:出版商有名稱,地址,所在城市,省,國家和網站。

書籍模型:書籍有書名和出版日期,一本書可能會有多個做者,一個做者也能夠寫多本書,因此做者和書籍的關係就是多對多的關聯關係(many-to-many),一本書只應該由一個出版商出版,因此出版商和書籍是一對多關聯關係(one-to-many),也被稱做外鍵。

 

6. 答:

高併發之下使用內存數據庫Redis,正常則使用表來進行計數。

DROP TABLE access_counter;

CREATE TABLE access_counter(
  cnt  INT UNSIGNED NOT NULL 
);

INSERT INTO access_counter VALUES(0);
UPDATE access_counter SET cnt=cnt+1;
SELECT * FROM access_counter;

7.略

8.答:

視圖:視圖是由查詢結果造成的一張虛擬表,是表經過某種運算獲得的一個投影。

同一張表能夠建立多個視圖

存儲過程:概念相似於函數,就是把一段代碼封裝起來,當要執行這一段代碼的時候,能夠經過調用該存儲過程來實現。在封裝的語句體裏面,

能夠同if/else ,case,while等控制結構。

能夠進行sql編程。

查看現有的存儲過程。

函數:須要先定義,而後調用(使用)。

只是規定,這個函數,必需要返回數據——要有返回值

觸發器:(1)觸發器是一個特殊的存儲過程,它是MySQL在insert、update、delete的時候自動執行的代碼塊。

(2)觸發器必須定義在特定的表上。

(3)自動執行,不能直接調用,

做用:監視某種狀況並觸發某種操做。

 

9.答:
單列:B+樹/哈希索引  --> 查詢速度快更新速度慢

    - 普通索引 :加速查找

    - 惟一索引 :加速查詢 + 約束(不能重複)

    - 主鍵索引 :加速查詢 + 約束(不能重複) + 不能爲空

    - 全文索引 :

多列:遵循最左前綴規則

    - 聯合索引 :

    - 聯合惟一索引 :

其餘:

- 索引合併 :利用多個單例索引查詢

    - 覆蓋索引 :在索引表中就能將想要的數據查詢到

    - 組合索引遵循最左前綴規則

        若是組合索引爲:(name,email)

        name and email       -- 使用索引

        name                 -- 使用索引

        email                -- 不使用索引

 

10. 答:

     假設聯合索引是state/city/zipCode

那麼state就是第一關,city是第二關,zipCode就是第三關

必須匹配了第一關,才能匹配第二關,匹配了第一關和第二關,才能匹配第三關

你不能直接到第二關的

索引的格式就是第一層是state,第二層纔是city

多列索引是先按照第一列進行排序,而後在第一列排好序的基礎上再對第二列排序,若是沒有第一列的話,直接訪問第二列,那第二列確定是無序的,直接訪問後面的列就用不到索引了

 

11. 答:主鍵是惟一標識一條記錄,不能有重複,不容許爲空,表的外鍵就是另外一表的逐漸,外鍵能夠有重複,能夠是空值。

       主鍵用來保證數據完整性,外鍵用來和其它表創建聯繫

       主鍵只能夠有一個,而一個表能夠有多個外鍵。

 

12. 答:數學函數:ABS,BIN,MOD,PI

              聚合函數,AVG,MIN,MAX

              字符串函數,ASCII,CONCAT

              日期和時間函數,DATE_ADD,DATE_SUB

              加密函數

 

13. 答:

一、查詢謂詞沒有使用索引的主要邊界,換句話說就是select *,可能會致使不走索引。

好比,你查詢的是SELECT * FROM T WHERE Y=XXX;假如你的T表上有一個包含Y值的組合索引,可是優化器會認爲須要一行行的掃描會更有效,這個時候,優化器可能會選擇TABLE ACCESS FULL,可是若是換成了SELECT Y FROM T WHERE Y = XXX,優化器會直接去索引中找到Y的值,由於從B樹中就能夠找到相應的值。

 

二、單鍵值的b樹索引列上存在null值,致使COUNT(*)不能走索引。

若是在B樹索引中有一個空值,那麼查詢諸如SELECT COUNT(*) FROM T 的時候,由於HASHSET中不能存儲空值的,因此優化器不會走索引,有兩種方式可讓索引有效,一種是SELECT COUNT(*) FROM T WHERE XXX IS NOT NULL或者把這個列的屬性改成not null (不能爲空)。

 

三、索引列上有函數運算,致使不走索引

若是在T表上有一個索引Y,可是你的查詢語句是這樣子SELECT * FROM T WHERE FUN(Y) = XXX。這個時候索引也不會被用到,由於你要查詢的列中全部的行都須要被計算一遍,所以,若是要讓這種sql語句的效率提升的話,在這個表上創建一個基於函數的索引,好比CREATE INDEX IDX FUNT ON T(FUN(Y));這種方式,等於Oracle會創建一個存儲全部函數計算結果的值,再進行查詢的時候就不須要進行計算了,由於不少函數存在不一樣返回值,所以必須標明這個函數是有固定返回值的。

 

四、隱式轉換致使不走索引。

索引不適用於隱式轉換的狀況,好比你的SELECT * FROM T WHERE Y = 5 在Y上面有一個索引,可是Y列是VARCHAR2的,那麼Oracle會將上面的5進行一個隱式的轉換,SELECT * FROM T WHERE TO_NUMBER(Y) = 5,這個時候也是有可能用不到索引的。

 

五、表的數據庫小或者須要選擇大部分數據,不走索引

在Oracle的初始化參數中,有一個參數是一次讀取的數據塊的數目,好比你的表只有幾個數據塊大小,並且能夠被Oracle一次性抓取,那麼就沒有使用索引的必要了,由於抓取索引還須要去根據rowid從數據塊中獲取相應的元素值,所以在表特別小的狀況下,索引沒有用到是情理當中的事情。

六、cbo優化器下統計信息不許確,致使不走索引

很長時間沒有作表分析,或者從新收集表狀態信息了,在數據字典中,表的統計信息是不許確的,這個狀況下,可能會使用錯誤的索引,這個效率可能也是比較低的。

七、!=或者<>(不等於),可能致使不走索引,也可能走 INDEX FAST FULL SCAN

例如select id  from test where id<>100

八、表字段的屬性致使不走索引,字符型的索引列會致使優化器認爲須要掃描索引大部分數據且聚簇因子很大,最終致使棄用索引掃描而改用全表掃描方式,

因爲字符型和數值型的在insert的時候排序不一樣,字符類型致使了聚簇因子很大,緣由是插入順序與排序順序不一樣。詳細點說,就是按照數字類型插入(1..3200000),按字符類型('1'...'32000000')t排序,在對字符類型使用大於運算符時,會致使優化器認爲須要掃描索引大部分數據且聚簇因子很大,最終致使棄用索引掃描而改用全表掃描方式。

 

 

14.答: 

slow_query_log = OFF                 # 是否開啓慢日誌記錄

long_query_time = 2                  # 時間限制,超過此時間,則記錄

slow_query_log_file = /usr/slow.log  # 日誌文件

log_queries_not_using_indexes = OFF  # 爲使用索引的搜索是否記錄

 

15. 答:

   MySQL命令行導出數據庫

1,進入MySQL目錄下的bin文件夾:cd MySQL中到bin文件夾的目錄

如我輸入的命令行:cd C:\Program Files\MySQL\MySQL Server 4.1\bin

(或者直接將windows的環境變量path中添加該目錄)

2,導出數據庫:mysqldump -u 用戶名 -p 數據庫名 > 導出的文件名

如我輸入的命令行:mysqldump -u root -p news > news.sql   (輸入後會讓你輸入進入MySQL的密碼)

(若是導出單張表的話在數據庫名後面輸入表名便可)

三、會看到文件news.sql自動生成到bin文件下 

命令行導入數據庫

1,將要導入的.sql文件移至bin文件下,這樣的路徑比較方便
2,同上面導出的第1步
3,進入MySQL:mysql -u 用戶名 -p

如我輸入的命令行:mysql -u root -p   (輸入一樣後會讓你輸入MySQL的密碼)

4,在MySQL-Front中新建你要建的數據庫,這時是空數據庫,如新建一個名爲news的目標數據庫
5,輸入:mysql>use 目標數據庫名

如我輸入的命令行:mysql>use news;

6,導入文件:mysql>source 導入的文件名;

 

16. 答:

   選取最適用的字段屬性。

   使用鏈接(join)來代替子查詢(Sub-Queries)

   使用聯合(UNION)來代替手動建立的臨時表

   事務

   鎖定表

   使用外鍵

   使用索引

   優化的查詢語句

 

 

17. 答:char長度不可變,varchar長度是可變的。char的存取數度仍是要比varchar要快得多,由於其長度固定,方便程序的存儲與查找;可是char也爲此付出的是空間的代價,由於其長度固定,因此不免會有多餘的空格佔位符佔據空間,可謂是以空間換取時間效率,而varchar是以空間效率爲首位的。

再者,char的存儲方式是,對英文字符(ASCII)佔用1個字節,對一個漢字佔用兩個字節;而varchar的存儲方式是,對每一個英文字符佔用2個字節,漢字也佔用2個字節。

 

18. 答:

弄明白了explain語法返回的每一項結果,咱們就能知道查詢大體的運行時間了,若是查詢裏沒有用到索引、或者須要掃描的行過多,那麼能夠感到明顯的延遲。所以須要改變查詢方式或者新建索引。mysql中的explain語法能夠幫助咱們改寫查詢,優化表的結構和索引的設置,從而最大地提升查詢效率。固然,在大規模數據量時,索引的創建和維護的代價也是很高的,每每須要較長的時間和較大的空間,若是在不一樣的列組合上創建索引,空間的開銷會更大。所以索引最好設置在須要常常查詢的字段中。

 

19. 答:兩個查詢語句的區別在於,下面那一句是從從第一行開始查詢。

 

20. 答:

        若是使用子查詢去優化LIMIT的話,則子查詢必須是連續的,某種意義來說,子查詢不該該有where條件,where會過濾數據,使數據失去連續性。
   若是你查詢的記錄比較大,而且數據傳輸量比較大,好比包含了text類型的field,則能夠經過創建子查詢。

   SELECT id,title,content FROM items WHERE id IN (SELECT id FROM items ORDER BY id limit 900000, 10);

   若是limit語句的offset較大,你能夠經過傳遞pk鍵值來減少offset = 0,這個主鍵最好是int類型而且auto_increment優化方法有子查詢優化法,倒排表優化法,反向查找優化法,limit限制優化法,只查優化法。

 

21. 答:

       一、索引合併是把幾個索引的範圍掃描合併成一個索引。

二、索引合併的時候,會對索引進行並集,交集或者先交集再並集操做,以便合併成一個索引。

三、這些須要合併的索引只能是一個表的。不能對多表進行索引合併。

22. 答:

覆蓋索引只是特定於具體select語錄而言的聯合索引。也就是說一個聯合索引對於某個select語句,經過索引能夠直接獲取查詢結果,而再也不須要回表查詢啦,就稱該聯合索引覆蓋了這條select語句。

或者: MySQL能夠利用索引返回SELECT 列表中的字段。而沒必要根據索引再次讀取數據文件。包含全部知足查詢須要的數據的索引成爲覆蓋索引(Covering Index)。也就是平時所說的不須要回表操做。

或者:就是select的數據列只用從索引中就可以取得,沒必要從數據表中讀取,換句話說查詢列要被所使用的索引覆蓋。

 

23. 答:

       經過設置主從數據庫實現讀寫分離,主數據庫負責「寫操做」,從數據庫負責「讀操做」,根據壓力狀況,從數據庫能夠部署多個提升「讀」的速度,藉此來提升系統整體的性能。

要實現讀寫分離,就要解決主從數據庫數據同步的問題,在主數據庫寫入數據後要保證從數據庫的數據也要更新。

 

24.答:

垂直切分

    把不一樣功能,不一樣模塊的數據分別放到不一樣的表中,可是若是同一個模塊的數據量太大就會存在性能瓶頸

   水平切分

  垂直切分解決不了大表的瓶頸,若是同一個功能中表的數據量過大,就要對該表進行切分,爲水平切分

通俗理解:垂直切分---分不一樣的模塊表;水平切分---分同一個模塊下的多個表。

 

25. 答:

一、Redis和Memcache都是將數據存放在內存中,都是內存數據庫。不過memcache還可用於緩存其餘東西,例如圖片、視頻等等;

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

三、虛擬內存--Redis當物理內存用完時,能夠將一些好久沒用到的value 交換到磁盤;

四、過時策略--memcache在set時就指定,例如set key1 0 0 8,即永不過時。Redis能夠經過例如expire 設定,例如expire name 10;

五、分佈式--設定memcache集羣,利用magent作一主多從;redis能夠作一主多從。均可以一主一從;

六、存儲數據安全--memcache掛掉後,數據沒了;redis能夠按期保存到磁盤(持久化);

七、災難恢復--memcache掛掉後,數據不可恢復; redis數據丟失後能夠經過aof恢復;

八、Redis支持數據的備份,即master-slave模式的數據備份;

 

26. 答:

     默認狀況下是十六個。

 

27. 答:安裝Redis, import  redis

 

28. 答:

Redis實例須要裝載大量用戶在短期內產生的數據,數以百萬計的keys須要被快速的建立。即大量數據插入(mass insertion)

使用Luke協議

使用正常模式的Redis客戶端執行大量數據插入是不明智的:由於一個個的插入會有大量的時間浪費在每個命令往返時間上。 
使用管道(pipelining)還比較靠譜,可是在大量插入數據的同時又須要執行其餘新命令時,這時讀取數據的同時須要確保儘量快的寫入數據。 
只有一小部分的客戶端支持非阻塞/輸出(non-blocking I/O),而且並非全部客戶端能以最大限度的提升吞吐量到高效的方式來分析答覆。 

 

同時,在分析回覆的時候,咱們會採用計數器的方法計數,以便在最後可以告訴咱們大量插入數據的數據量

 

29. 答:

 

Redis主從複製能夠根據是不是全量分爲全量同步和增量同步。

1 全量同步

  Redis全量複製通常發生在Slave初始化階段,這時Slave須要將Master上的全部數據都複製一份。具體步驟以下: 
  1)從服務器鏈接主服務器,發送SYNC命令; 
  2)主服務器接收到SYNC命名後,開始執行BGSAVE命令生成RDB文件並使用緩衝區記錄此後執行的全部寫命令; 
  3)主服務器BGSAVE執行完後,向全部從服務器發送快照文件,並在發送期間繼續記錄被執行的寫命令; 
  4)從服務器收到快照文件後丟棄全部舊數據,載入收到的快照; 
  5)主服務器快照發送完畢後開始向從服務器發送緩衝區中的寫命令; 
  6)從服務器完成對快照的載入,開始接收命令請求,並執行來自主服務器緩衝區的寫命令; 

2 增量同步

  Redis增量複製是指Slave初始化後開始正常工做時主服務器發生的寫操做同步到從服務器的過程。 
增量複製的過程主要是主服務器每執行一個寫命令就會向從服務器發送相同的寫命令,從服務器接收並執行收到的寫命令。

Redis的正常部署中通常都是一個master用於寫操做,若干個slave用於讀操做,另外按期的數據備份操做也是單獨選址一個slave完成,這樣能夠最大程度發揮出redis的性能。在部署完成,各master\slave程序啓動以後,首先進行第一階段初始化時的全同步操做,全同步操做完成以後,後續全部寫操做都是在master上進行,全部讀操做都是在slave上進行,所以用戶的寫操做須要及時擴散到全部的slave以便保持數據最大程度上的同步。

 

30. 答:

Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案,當用Redis作Master-slave的高可用方案時,假如master宕機了,Redis自己(包括它的不少客戶端)都沒有實現自動進行主備切換,而Redis-sentinel自己也是一個獨立運行的進程,它能監控多個master-slave集羣,發現master宕機後能進行自動切換。

它的主要功能有如下幾點

不時地監控redis是否按照預期良好地運行;

若是發現某個redis節點運行出現情況,可以通知另一個進程(例如它的客戶端);

可以進行自動切換。當一個master節點不可用時,可以選舉出master的多個slave(若是有超過一個slave的話)中的一個來做爲新的master,其它的slave節點會將它所追隨的master的地址改成被提高爲master的slave的新地址。

31.答:

       1.客戶端分片

  客戶端分片是把分片的邏輯放在Redis客戶端實現,經過Redis客戶端預先定義好的路由規則,把對Key的訪問轉發到不一樣的Redis實例中,最後把返回結果聚集。

 2.Twemproxy

  Twemproxy是由Twitter開源的Redis代理,其基本原理是:Redis客戶端把請求發送到Twemproxy,Twemproxy根據路由規則發送到正確的Redis實例,最後Twemproxy把結果聚集返回給客戶端。

  Twemproxy經過引入一個代理層,將多個Redis實例進行統一管理,使Redis客戶端只須要在Twemproxy上進行操做,而不須要關心後面有多少個Redis實例,從而實現了Redis集羣。

3.Codis

  Twemproxy不能平滑增長Redis實例的問題帶來了很大的不便,因而豌豆莢自主研發了Codis,一個支持平滑增長Redis實例的Redis代理軟件,其基於Go和C語言開發,並於2014年11月在GitHub上開源。

  Codis包含下面4個部分。

Codis Proxy:Redis客戶端鏈接到Redis實例的代理,實現了Redis的協議,Redis客戶端鏈接到Codis Proxy進行各類操做。Codis Proxy是無狀態的,能夠用Keepalived等負載均衡軟件部署多個Codis Proxy實現高可用。

CodisRedis:Codis項目維護的Redis分支,添加了slot和原子的數據遷移命令。Codis上層的 Codis Proxy和Codisconfig只有與這個版本的Redis通訊才能正常運行。

Codisconfig:Codis管理工具。能夠執行添加刪除CodisRedis節點、添加刪除Codis Proxy、數據遷移等操做。另外,Codisconfig自帶了HTTP server,裏面集成了一個管理界面,方便運維人員觀察Codis集羣的狀態和進行相關的操做,極大提升了運維的方便性,彌補了Twemproxy的缺點。

ZooKeeper:分佈式的、開源的應用程序協調服務,是Hadoop和Hbase的重要組件,其爲分佈式應用提供一致性服務,提供的功能包括:配置維護、名字服務、分佈式同步、組服務等。Codis依賴於ZooKeeper存儲數據路由表的信息和Codis Proxy節點的元信息。另外,Codisconfig發起的命令都會經過ZooKeeper同步到CodisProxy的節點。

4.Redis 3.0集羣

  Redis 3.0集羣採用了P2P的模式,徹底去中心化。Redis把全部的Key分紅了16384個slot,每一個Redis實例負責其中一部分slot。集羣中的全部信息(節點、端口、slot等),都經過節點之間按期的數據交換而更新。

Redis客戶端在任意一個Redis實例發出請求,若是所需數據不在該實例中,經過重定向命 

 5.雲服務器上的集羣服務

  國內的雲服務器提供商阿里雲、UCloud等均推出了基於Redis的雲存儲服務。

令引導客戶端訪問所需的實例。

 

32. 答:默認有16384個哈希槽

33. 答:

Redis的持久化策略:2種

 ---------rdb:快照形式是直接把內存中的數據保存到一個dump文件中,定時保存,保存策略

這種方式不能徹底保證數據持久化,由於是定時保存,因此當redis服務down掉,就會丟失一部分數據,並且數據量大,寫操做多的狀況下,會引發大量的磁盤IO操做,會影響性能。

 ---------aof:把全部的對redis的服務器進行修改的命令都存到一個文件裏,命令的集合

使用aof作持久化,每個寫命令都經過write函數追加到appendonly.aof中.

配置方式:啓動aof持久化的方式 

34.  答:

定時刪除

含義:在設置key的過時時間的同時,爲該key建立一個定時器,讓定時器在key的過時時間來臨時,對key進行刪除

優勢:保證內存被儘快釋放

缺點:

若過時key不少,刪除這些key會佔用不少的CPU時間,在CPU時間緊張的狀況下,CPU不能把全部的時間用來作要緊的事兒,還須要去花時間刪除這些key

定時器的建立耗時,若爲每個設置過時時間的key建立一個定時器(將會有大量的定時器產生),性能影響嚴重

沒人用

惰性刪除

含義:key過時的時候不刪除,每次從數據庫獲取key的時候去檢查是否過時,若過時,則刪除,返回null。

優勢:刪除操做只發生在從數據庫取出key的時候發生,並且只刪除當前key,因此對CPU時間的佔用是比較少的,並且此時的刪除是已經到了非作不可的地步(若是此時還不刪除的話,咱們就會獲取到了已通過期的key了)

缺點:若大量的key在超出超時時間後,好久一段時間內,都沒有被獲取過,那麼可能發生內存泄露(無用的垃圾佔用了大量的內存)

按期刪除

含義:每隔一段時間執行一次刪除過時key操做

優勢:

經過限制刪除操做的時長和頻率,來減小刪除操做對CPU時間的佔用--處理"定時刪除"的缺點

按期刪除過時key--處理"惰性刪除"的缺點

缺點

在內存友好方面,不如"定時刪除"

在CPU時間友好方面,不如"惰性刪除"

難點

合理設置刪除操做的執行時長(每次刪除執行多長時間)和執行頻率(每隔多長時間作一次刪除)(這個要根據服務器運行狀況來定了)

 

 

 

35. 答:

redis 內存數據集大小上升到必定大小的時候,就會施行數據淘汰策略。redis 提供 6種數據淘汰策略:
volatile-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(驅逐):禁止驅逐數據

 

36.略

37.答:

Redis提供了兩種方式來做消息隊列。 
一個是使用生產者消費模式模式, 
另外一個就是發佈訂閱者模式。 
前者會讓一個或者多個客戶端監聽消息隊列,一旦消息到達,消費者立刻消費,誰先搶到算誰的,若是隊列裏沒有消息,則消費者繼續監聽。 
後者也是一個或多個客戶端訂閱消息頻道,只要發佈者發佈消息,全部訂閱者都能收到消息,訂閱者都是平等的。

 

38.答:

  「發佈/訂閱」模式包含兩種角色,分別是發佈者和訂閱者。訂閱者能夠訂閱一個或若干個頻道(channel),而發佈者能夠向指定的頻道發送消息,全部訂閱此頻道的訂閱者都會收到此消息。

     發佈者發送消息的命令是PUBLISH,用法是PUBLISH channel message,如向channel.1說一聲「hi」:

        redis>PUBLISH channel.1 hi

        (integer)  0

      這樣消息就發出去了。返回值表示接收到這條消息的訂閱者數量。發出去的消息不會被持久化,也就是說當客戶端訂閱channel.1後只能收到後續發佈到該頻道的消息,以前發送到就收不到了。

       訂閱頻道的命令是SUBSCRIBE,能夠同時訂閱多個頻道,用法是 SUBSCRIBE channel [channel ...]。

        redis>SUBSCRIBE channel.1

        Reading messages... (press Ctrl-C to quit)

        1) "subscribe"

        2) "channel.1"  

        3) (integer) 1

        執行SUBSCRIBE命令後進入訂閱狀態,處於此狀態下客戶端不能使用除SUBSCRIBE/UNSUBSCRIBE/PSUBSCRIBE/PUNSUBSCRIBE這四個屬於「發佈/訂閱」模式以外的命令,不然會報錯。

        進入訂閱模式後客戶端可能收到三種類型的回覆。每種類型的回覆都包含3個值,第一個值是消息的類型,根據消息類型的不一樣,第二第三個值的含義也不一樣。消息類型可能的取值有:

        (1)Subscribe。表示訂閱成功的反饋信息。第二個值是訂閱成功的頻道名稱,第三個值是當前客戶端訂閱的頻道數。

        (2)message。這個類型的回覆表示收到的消息。第二個值表示產生消息的頻道名稱,第三個值是消息內容。

        (3)unsubscribe。表示成功取消訂閱某個頻道。第二個值是對應的頻道名稱,第三個值是當前客戶端訂閱的頻道數量,當此值爲0時客戶端會退出訂閱狀態。

 

 

39. 答:

Codis 是一個分佈式 Redis 解決方案, 對於上層的應用來講, 鏈接到 Codis Proxy 和鏈接原生的 Redis Server 沒有明顯的區別 (不支持的命令列表), 上層應用能夠像使用單機的 Redis 同樣使用, Codis 底層會處理請求的轉發, 不停機的數據遷移等工做, 全部後邊的一切事情, 對於前面的客戶端來講是透明的, 能夠簡單的認爲後邊鏈接的是一個內存無限大的 Redis 服務.

 

 

40. 答:

Twemproxy 也叫 nutcraker。是 Twtter 開源的一個 Redis 和 Memcache 代理服務器,主要用於管理 Redis 和 Memcached 集羣,減小與Cache 服務器直接鏈接的數量。

Twemproxy特性:

輕量級、快速

保持長鏈接

減小了直接與緩存服務器鏈接的鏈接數量

使用 pipelining 處理請求和響應

支持代理到多臺服務器上

同時支持多個服務器池

自動分片數據到多個服務器上

實現完整的 memcached 的 ASCII 和再分配協議

經過 yaml 文件配置服務器池

支持多個哈希模式,包括一致性哈希和分佈

可以配置刪除故障節點

能夠經過端口監控狀態

支持 linux, *bsd,os x 和 solaris

 

 

41.答:

class CasNormal(object):

  def __init__(self, host, key):

    self.r = redis.Redis(host)

    self.key = key

    if not self.r.exists(self.key):

      self.r.set(self.key, 0)

 

  def inc(self):

    with self.r.pipeline() as pipe:

      while True:

        try:

          #監視一個key,若是在執行期間被修改了,會拋出WatchError

          pipe.watch(self.key)

          next_count = 30 + int(pipe.get(self.key))

          pipe.multi()

          if next_count < int(time.time()):

            next_count = int(time.time())

          pipe.set(self.key, next_count)

          pipe.execute()

          return next_count

        except WatchError:

          continue

        finally:

          pipe.reset()

 

42.答:Redis Watch 命令用於監視一個(或多個) key ,若是在事務執行以前這個(或這些) key 被其餘命令所改動,那麼事務將被打斷

 

43.略

44.答:

分佈式鎖應該具備的特性(Safety & Liveness)

咱們將從三個特性的角度出發來設計RedLock模型:

安全性(Safety):在任意時刻,只有一個客戶端能夠得到鎖(排他性)。

避免死鎖:客戶端最終必定能夠得到鎖,即便鎖住某個資源的客戶端在釋放鎖以前崩潰或者網絡不可達。

容錯性:只要Redsi集羣中的大部分節點存活,client就能夠進行加鎖解鎖操做。


一個Client想要得到一個鎖須要如下幾個操做:

獲得本地時間

Client使用相同的key和隨機數,按照順序在每一個Master實例中嘗試得到鎖。在得到鎖的過程當中,爲每個鎖操做設置一個快速失敗時間(若是想要得到一個10秒的鎖, 那麼每個鎖操做的失敗時間設爲5-50ms)。
這樣能夠避免客戶端與一個已經故障的Master通訊佔用太長時間,經過快速失敗的方式儘快的與集羣中的其餘節點完成鎖操做。

客戶端計算出與master得到鎖操做過程當中消耗的時間,當且僅當Client得到鎖消耗的時間小於鎖的存活時間,而且在一半以上的master節點中得到鎖。才認爲client成功的得到了鎖。

若是已經得到了鎖,Client執行任務的時間窗口是鎖的存活時間減去得到鎖消耗的時間。

若是Client得到鎖的數量不足一半以上,或得到鎖的時間超時,那麼認爲得到鎖失敗。客戶端須要嘗試在全部的master節點中釋放鎖, 即便在第二步中沒有成功得到該Master節點中的鎖,仍要進行釋放操做。



45.答:

一致性哈希要對緩存的key進行哈希,同時也須要服務器也提供一個key進行哈希,而後將其分佈在一個閉圓上,在決定一個key的分佈的時候,這裏經過找到第一個大於這個key的哈希值的服務器就好了。。。

這樣在當一臺服務器退出以後,或者有新的服務器加入進來以後,只會影響一部分的key的哈希分佈,不至於致使全部的key的哈希分佈都失效。

46. 答:獲取指定前綴的key:redis-cli KEYS 「oldboy*」

相關文章
相關標籤/搜索