一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Redis 指南

 lguo001 2016-08-16

來(lái)源:http:///2016/07/05/redis-guide/


Redis 是 C 實(shí)現(xiàn)的基于內(nèi)存并可持久的鍵值對(duì)數(shù)據(jù)庫(kù),在分布式服務(wù)中常常被用作緩存。除此之外還可以利用其特點(diǎn)做許多有趣的應(yīng)用,所以我們不僅需要會(huì)用,更需要理解其工作機(jī)制。




Redis 的具體介紹在官方網(wǎng)站和維基百科都有,這里我們只要記住幾個(gè)關(guān)鍵詞既可:開(kāi)源、C 語(yǔ)言、網(wǎng)絡(luò)交互、基于內(nèi)存、可持久化、鍵值對(duì)、數(shù)據(jù)庫(kù)。作者是 Salvatore Sanfilippo,他的博客和 github 主頁(yè)都放到文末的參考鏈接里,有興趣的同學(xué)可以去看看。


根據(jù) Redis 主頁(yè)上的介紹,許多公司都在使用 Redis,比較著名的有 Twitter GitHub Weibo Pinterest Snapchat Craigslist Digg StackOverflow Flickr 等等,想要了解更多的話(huà),可以參考 Who uses Redis?


也有另一種叫法,稱(chēng)為數(shù)據(jù)結(jié)構(gòu)服務(wù)器,因?yàn)楸4娴?value 可以是字符串(string)、字典(map)、列表(list)、集合(sets)或有序集合(sorted set)。那么鍵值對(duì)存儲(chǔ)這么多,到底 Redis 有什么不同之處呢?一是原子性操作,二是在內(nèi)存中運(yùn)行。


Redis 腳本使用 Lua 解釋器來(lái)執(zhí)行腳本。 Reids 2.6 版本通過(guò)內(nèi)嵌支持 Lua 環(huán)境。執(zhí)行腳本的常用命令為 EVAL?;菊Z(yǔ)法為 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]


基本使用


安裝


在 Mac 下的安裝非常簡(jiǎn)單,只需要 brew install redis 即可,如果需要開(kāi)機(jī)啟動(dòng),按照安裝完成后的提示輸出一條命令即可。然后我們輸入 redis-server 應(yīng)該就能看到如下信息



我們看到目前 Redis 運(yùn)行在 standalone 模式(相對(duì)于分布式),對(duì)應(yīng)的端口是 6379。至于為什么是 6379,這背后是有故事的,原文在這里 http://oldblog./post/redis-as-LRU-cache.html(打開(kāi)之后搜索6379),我簡(jiǎn)要翻譯一下:


6379 是 MERZ 這個(gè)單詞在九宮格輸入時(shí)的按鍵順序,那么問(wèn)題來(lái)了,MERZ 又是什么鬼?簡(jiǎn)單來(lái)說(shuō)來(lái)自于一個(gè)意大利 showgirl,名字叫做 Alessia Merz,圖片這里就不放了。作者日常生活中會(huì)創(chuàng)造一些『俚語(yǔ)』,merz 這個(gè)詞已經(jīng)用了十年,意思也一直在變化。起初他們 merz 來(lái)表示很蠢的事情,比方說(shuō)『Hey, that’s merz!』,之后意思有些變化,指的是那些有一定技術(shù)含量但沒(méi)什么意義而且還很蠢(stupid)的事兒,或者是那些需要大量技能和耐心才能完成但仍舊很蠢(stupid)的事兒(看出來(lái)了嗎,核心是 Stupid)。作者舉了兩個(gè)例子,比方說(shuō)用一臺(tái) GPS 和一輛破車(chē)大半夜為制作 3D 地圖采樣,或者在明知道自己不會(huì)去買(mǎi)彩票的情況下還是研究大量的彩票信息來(lái)找到其『不隨機(jī)』的證據(jù)。總結(jié)一下就是有 hack value 的事情,或者是那些為了 hack value 而去做事的人。于是自然而然的,merz 在撥號(hào)鍵盤(pán)上對(duì)應(yīng)的數(shù)字就成為了 Redis 的端口號(hào)。


除了前面使用過(guò)的 redis-server 命令,我們還可以使用 redis-cli 命令來(lái)啟動(dòng) redis 客戶(hù)端,比如:



如果需要在遠(yuǎn)程 Redis 上執(zhí)行命令,也可以用 redis-cli 命令,具體的方式為 redis-cli -h host -p port -a password


連接


基本命令有 5 個(gè),可以覆蓋日常使用的大部分場(chǎng)景,比方說(shuō)心跳檢測(cè)、切換數(shù)據(jù)庫(kù)之類(lèi)的:


  • AUTH password: 驗(yàn)證密碼

  • ECHO message: 打印字符串

  • PING: 查看服務(wù)是否在運(yùn)行,如果在運(yùn)行,就輸出 PONG

  • QUIT: 關(guān)閉當(dāng)前連接

  • SELECT index: 選擇指定的數(shù)據(jù)庫(kù)


狀態(tài)


我們可以使用 INFO 命令來(lái)了解當(dāng)前 Redis 數(shù)據(jù)庫(kù)的基本狀態(tài),更多的命令請(qǐng)查閱參考鏈接中給出的地址,這里不贅述:



配置


Redis 的配置文件可以在安裝目錄下找到,名為 redis.conf,我們來(lái)看看都有什么配置



具體解釋


  1. Redis 默認(rèn)不是以守護(hù)進(jìn)程的方式運(yùn)行,可以通過(guò)該配置項(xiàng)修改,使用yes啟用守護(hù)進(jìn)程daemonize no

  2. 當(dāng) Redis 以守護(hù)進(jìn)程方式運(yùn)行時(shí),Redis 默認(rèn)會(huì)把 pid 寫(xiě)入 /var/run/redis.pid 文件,可以通過(guò) pidfile 指定 pidfile /var/run/redis.pid

  3. 指定 Redis 監(jiān)聽(tīng)端口,默認(rèn)端口為 6379 port 6379

  4. 綁定的主機(jī)地址 bind 127.0.0.1

  5. 當(dāng)客戶(hù)端閑置多長(zhǎng)時(shí)間后關(guān)閉連接,如果指定為 0,表示關(guān)閉該功能 timeout 300

  6. 指定日志記錄級(jí)別,Redis 總共支持四個(gè)級(jí)別:debug、verbose、notice、warning,默認(rèn)為 verbose, loglevel verbose

  7. 日志記錄方式,默認(rèn)為標(biāo)準(zhǔn)輸出,如果配置 Redis 為守護(hù)進(jìn)程方式運(yùn)行,而這里又配置為日志記錄方式為標(biāo)準(zhǔn)輸出,則日志將會(huì)發(fā)送給 /dev/null, logfile stdout

  8. 設(shè)置數(shù)據(jù)庫(kù)的數(shù)量,默認(rèn)數(shù)據(jù)庫(kù)為 0,可以使用 SELECT 命令在連接上指定數(shù)據(jù)庫(kù) id, databases 16

  9. 指定在多長(zhǎng)時(shí)間內(nèi),有多少次更新操作,就將數(shù)據(jù)同步到數(shù)據(jù)文件,可以多個(gè)條件配合 save Redis默認(rèn)配置文件中提供了三個(gè)條件:save 900 1, save 300 10, save 60 10000, 分別表示 900 秒(15 分鐘)內(nèi)有 1 個(gè)更改,300 秒(5 分鐘)內(nèi)有 10 個(gè)更改以及 60 秒內(nèi)有 10000 個(gè)更改。

  10. 指定存儲(chǔ)至本地?cái)?shù)據(jù)庫(kù)時(shí)是否壓縮數(shù)據(jù),默認(rèn)為 yes,Redis 采用 LZF 壓縮,如果為了節(jié)省 CPU 時(shí)間,可以關(guān)閉該選項(xiàng),但會(huì)導(dǎo)致數(shù)據(jù)庫(kù)文件變的巨大 rdbcompression yes

  11. 指定本地?cái)?shù)據(jù)庫(kù)文件名,默認(rèn)值為 dump.rdb, dbfilename dump.rdb

  12. 指定本地?cái)?shù)據(jù)庫(kù)存放目錄 dir ./

  13. 設(shè)置當(dāng)本機(jī)為 slave 服務(wù)時(shí),設(shè)置 master 服務(wù)的IP地址及端口,在 Redis 啟動(dòng)時(shí),它會(huì)自動(dòng)從 master 進(jìn)行數(shù)據(jù)同步 slaveof

  14. 當(dāng) master 服務(wù)設(shè)置了密碼保護(hù)時(shí),slave 服務(wù)連接 master 的密碼 masterauth

  15. 設(shè)置 Redis 連接密碼,如果配置了連接密碼,客戶(hù)端在連接 Redis 時(shí)需要通過(guò) AUTH 命令提供密碼,默認(rèn)關(guān)閉 requirepass foobared

  16. 設(shè)置同一時(shí)間最大客戶(hù)端連接數(shù),默認(rèn)無(wú)限制,Redis 可以同時(shí)打開(kāi)的客戶(hù)端連接數(shù)為Redis 進(jìn)程可以打開(kāi)的最大文件描述符數(shù),如果設(shè)置 maxclients 0,表示不作限制。當(dāng)客戶(hù)端連接數(shù)到達(dá)限制時(shí),Redis 會(huì)關(guān)閉新的連接并向客戶(hù)端返回 max number of clients reached 錯(cuò)誤信息 maxclients 128

  17. 指定 Redis 最大內(nèi)存限制,Redis 在啟動(dòng)時(shí)會(huì)把數(shù)據(jù)加載到內(nèi)存中,達(dá)到最大內(nèi)存后,Redis 會(huì)先嘗試清除已到期或即將到期的 Key,當(dāng)此方法處理后,仍然到達(dá)最大內(nèi)存設(shè)置,將無(wú)法再進(jìn)行寫(xiě)入操作,但仍然可以進(jìn)行讀取操作。Redis 新的 vm 機(jī)制,會(huì)把 Key 存放內(nèi)存,Value 會(huì)存放在 swap 區(qū), maxmemory

  18. 指定是否在每次更新操作后進(jìn)行日志記錄,Redis 在默認(rèn)情況下是異步的把數(shù)據(jù)寫(xiě)入磁盤(pán),如果不開(kāi)啟,可能會(huì)在斷電時(shí)導(dǎo)致一段時(shí)間內(nèi)的數(shù)據(jù)丟失。因?yàn)?redis 本身同步數(shù)據(jù)文件是按上面 save 條件來(lái)同步的,所以有的數(shù)據(jù)會(huì)在一段時(shí)間內(nèi)只存在于內(nèi)存中。默認(rèn)為 no, appendonly no

  19. 指定更新日志文件名,默認(rèn)為 appendonly.aof, appendfilename appendonly.aof

  20. 指定更新日志條件,共有3個(gè)可選值:

    1. no:表示等操作系統(tǒng)進(jìn)行數(shù)據(jù)緩存同步到磁盤(pán)(快)

    2. always:表示每次更新操作后手動(dòng)調(diào)用fsync()將數(shù)據(jù)寫(xiě)到磁盤(pán)(慢,安全)

    3. everysec:表示每秒同步一次(折衷,默認(rèn)值)appendfsync everysec

  21. 指定是否啟用虛擬內(nèi)存機(jī)制,默認(rèn)值為 no,簡(jiǎn)單的介紹一下,VM 機(jī)制將數(shù)據(jù)分頁(yè)存放,由Redi s將訪問(wèn)量較少的頁(yè)即冷數(shù)據(jù) swap 到磁盤(pán)上,訪問(wèn)多的頁(yè)面由磁盤(pán)自動(dòng)換出到內(nèi)存中 vm-enabled no

  22. 虛擬內(nèi)存文件路徑,默認(rèn)值為 /tmp/redis.swap,不可多個(gè) Redis 實(shí)例共享 vm-swap-file /tmp/redis.swap

  23. 將所有大于 vm-max-memory 的數(shù)據(jù)存入虛擬內(nèi)存,無(wú)論 vm-max-memory 設(shè)置多小,所有索引數(shù)據(jù)都是內(nèi)存存儲(chǔ)的(Redis 的索引數(shù)據(jù) 就是 keys),也就是說(shuō),當(dāng) vm-max-memory 設(shè)置為 0 的時(shí)候,其實(shí)是所有 value 都存在于磁盤(pán)。默認(rèn)值為 0, vm-max-memory 0

  24. Redis swap 文件分成了很多的 page,一個(gè)對(duì)象可以保存在多個(gè) page 上面,但一個(gè) page 上不能被多個(gè)對(duì)象共享,vm-page-size 是要根據(jù)存儲(chǔ)的 數(shù)據(jù)大小來(lái)設(shè)定的,作者建議如果存儲(chǔ)很多小對(duì)象,page 大小最好設(shè)置為 32 或者 64bytes;如果存儲(chǔ)很大大對(duì)象,則可以使用更大的 page,如果不確定,就使用默認(rèn)值 vm-page-size 32

  25. 設(shè)置 swap 文件中的 page 數(shù)量,由于頁(yè)表(一種表示頁(yè)面空閑或使用的 bitmap)是在放在內(nèi)存中的,在磁盤(pán)上每 8 個(gè) pages 將消耗 1byte 的內(nèi)存。vm-pages 134217728

  26. 設(shè)置訪問(wèn) swap 文件的線(xiàn)程數(shù),最好不要超過(guò)機(jī)器的核數(shù),如果設(shè)置為 0,那么所有對(duì) swap 文件的操作都是串行的,可能會(huì)造成比較長(zhǎng)時(shí)間的延遲。默認(rèn)值為 4, vm-max-threads 4

  27. 設(shè)置在向客戶(hù)端應(yīng)答時(shí),是否把較小的包合并為一個(gè)包發(fā)送,默認(rèn)為開(kāi)啟 glueoutputbuf yes

  28. 指定在超過(guò)一定的數(shù)量或者最大的元素超過(guò)某一臨界值時(shí),采用一種特殊的哈希算法, hash-max-zipmap-entries 64, hash-max-zipmap-value 512

  29. 指定是否激活重置哈希,默認(rèn)為開(kāi)啟(后面在介紹Redis的哈希算法時(shí)具體介紹)activerehashing yes

  30. 指定包含其它的配置文件,可以在同一主機(jī)上多個(gè) Redis 實(shí)例之間使用同一份配置文件,而同時(shí)各個(gè)實(shí)例又擁有自己的特定配置文件 include /path/to/local.conf


數(shù)據(jù)結(jié)構(gòu)


Redis 中的 value 支持五種數(shù)據(jù)類(lèi)型: strings, lists, sets, sorted sets, hashes。關(guān)于 key 的設(shè)計(jì),有幾點(diǎn)需要注意:


  • key 不要太長(zhǎng),盡量不要超過(guò) 1024 字節(jié),這不僅消耗內(nèi)存,而且會(huì)降低查找的效率;

  • key 也不要太短,太短的話(huà),key 的可讀性會(huì)降低;

  • 在一個(gè)項(xiàng)目中,key 最好使用統(tǒng)一的命名模式,例如 user:10000:passwd


另外本文只是一個(gè)基本的指南,不會(huì)涵蓋太多的命令,具體請(qǐng)參考 Redis 的官方文檔。


Strings


有人說(shuō),如果只使用 redis 中的字符串類(lèi)型,且不使用 redis 的持久化功能,那么,redis 就和 memcache 非常非常的像了。我們可以做一些基本的嘗試:




在遇到數(shù)值操作的時(shí)候,redis 會(huì)將字符串類(lèi)型轉(zhuǎn)換成數(shù)值,但是如果不是數(shù)值會(huì)怎么樣呢?我們來(lái)試試看:



Redis 中的數(shù)值操作指令有一個(gè)很好的特性是原子性,很多網(wǎng)站都利用 redis 的這個(gè)特性來(lái)做技術(shù)統(tǒng)計(jì)


Lists


Redis 中的 list 的底層實(shí)現(xiàn)不是數(shù)組而是鏈表,這就使得在頭尾插入新元素的復(fù)雜度是常數(shù)級(jí)別的,但定位元素的時(shí)候如果 list 的大小比較大的話(huà)就會(huì)很耗時(shí)。lists 的常用操作包括LPUSH、RPUSH、LRANGE 等。我們可以用 LPUSH 在 lists 的左側(cè)插入一個(gè)新元素,用 RPUSH 在 lists 的右側(cè)插入一個(gè)新元素,用 LRANGE 命令從 lists 中指定一個(gè)范圍來(lái)提取元素。簡(jiǎn)單來(lái)試一下:



lists 的應(yīng)用相當(dāng)廣泛,隨便舉幾個(gè)例子:


  1. 我們可以利用 lists 來(lái)實(shí)現(xiàn)一個(gè)消息隊(duì)列,而且可以確保先后順序,不必像 MySQL 那樣還需要通過(guò) ORDER BY 來(lái)進(jìn)行排序

  2. 利用 LRANGE 還可以很方便的實(shí)現(xiàn)分頁(yè)的功能

  3. 在博客系統(tǒng)中,每片博文的評(píng)論也可以存入一個(gè)單獨(dú)的 list 中


Sets


Redis 中的集合是無(wú)序集合,基本的操作對(duì)應(yīng)于集合的操作,比方說(shuō)添加、刪除、交并差集等等,例如:



集合的常見(jiàn)應(yīng)用場(chǎng)景也很多,比方說(shuō)文章的標(biāo)簽;群聊中的成員等等。


Sorted Sets


顧名思義,就是把無(wú)序的集合弄有序了,每個(gè)元素會(huì)關(guān)聯(lián)一個(gè)分?jǐn)?shù) score,也就是排序的依據(jù)。因?yàn)殛P(guān)于有序集合的相關(guān)操作都是以 z 開(kāi)頭的,所以通常我們把有序集合稱(chēng)為 zsets。還是來(lái)看看具體的例子:




Hashes


哈希是 Redis 2.0 之后才增加支持的數(shù)據(jù)結(jié)構(gòu),簡(jiǎn)單來(lái)說(shuō)就是一個(gè)字典,直接看具體例子就很好懂了:




Redis 2.8.9 版本中添加了這個(gè)新的結(jié)構(gòu),命名也很有趣,走 ABB 的套路,比如范冰冰高圓圓李思思就是這么個(gè)意思。這個(gè)結(jié)構(gòu)是用來(lái)做基數(shù)統(tǒng)計(jì)的,基數(shù)統(tǒng)計(jì)是什么,來(lái)看兩個(gè)例子:1) 數(shù)據(jù)集 {1, 3, 5, 7, 5, 7, 8}, 那么這個(gè)數(shù)據(jù)集的基數(shù)集為 {1, 3, 5 ,7, 8}, 基數(shù)(不重復(fù)元素)為 5。2) 一個(gè)網(wǎng)站有很多訪客記錄,因?yàn)槊總€(gè)人不一定只訪問(wèn)一次,如果我想知道獨(dú)立訪客的人數(shù)的話(huà),就需要計(jì)算一個(gè)基數(shù),這時(shí)候就可以用 HyperLogLog。好處在于即使數(shù)據(jù)量非常大,計(jì)算所需的空間是小而固定的。每個(gè) HyperLogLog 的鍵只占用 12KB 的內(nèi)存,但是可以計(jì)算 264264 個(gè)不同的基數(shù)。具體怎么實(shí)現(xiàn)的我還沒(méi)有看源碼,但估計(jì)跟 bloomfilter 的思路是一樣的。簡(jiǎn)單舉個(gè)例子:




因?yàn)閮?nèi)部設(shè)計(jì)的算法,會(huì)盡量避免出現(xiàn)碰撞,所以在例子中大概不會(huì)出現(xiàn)統(tǒng)計(jì)不準(zhǔn)的情況,不過(guò)在數(shù)據(jù)量變大之后,統(tǒng)計(jì)數(shù)值就不再是準(zhǔn)確值。


持久化


雖然是內(nèi)存數(shù)據(jù)庫(kù),一般來(lái)說(shuō)為了保險(xiǎn)起見(jiàn),還是會(huì)有一些持久化的機(jī)制,Redis 采用了其中兩種方式,一是 RDB(Redis DataBase),也就是存數(shù)據(jù),另一種是 AOF(Append Only File),也就是存操作。當(dāng)然,即使是 Redis 本身提供的,我們也可以選擇用還是不用,如果兩種都不用的化,Redis 就和 memcache 差不多了。


具體的命令也很簡(jiǎn)單,直接 SAVE 即可,會(huì)在安裝目錄中創(chuàng)建 dump.rdb 文件?;謴?fù)數(shù)據(jù)時(shí),只需要將備份文件移動(dòng)到 redis 安裝目錄并啟動(dòng) redis 即可,具體目錄在哪里可以通過(guò) CONFIG GET dir 來(lái)查看,比方說(shuō)在我的機(jī)器上:


127.0.0.1:6379> CONFIG GET dir

1) 'dir'

2) '/usr/local/var/db/redis'


如果用 BGSAVE 的話(huà),就是在后臺(tái)進(jìn)行備份,不會(huì)阻塞進(jìn)程。


RDB


本段內(nèi)容來(lái)自 Linux大棚版redis入門(mén)教程(http:///?p=3196)


RDB 方式,是將 redis 某一時(shí)刻的數(shù)據(jù)持久化到磁盤(pán)中,是一種快照式的持久化方法。


Redis 在進(jìn)行數(shù)據(jù)持久化的過(guò)程中,會(huì)先將數(shù)據(jù)寫(xiě)入到一個(gè)臨時(shí)文件中,待持久化過(guò)程都結(jié)束了,才會(huì)用這個(gè)臨時(shí)文件替換上次持久化好的文件。正是這種特性,讓我們可以隨時(shí)來(lái)進(jìn)行備份,因?yàn)榭煺瘴募偸峭暾捎玫摹?/span>


對(duì)于 RDB 方式,redis 會(huì)單獨(dú)創(chuàng)建(fork)一個(gè)子進(jìn)程來(lái)進(jìn)行持久化,而主進(jìn)程是不會(huì)進(jìn)行任何IO操作的,這樣就確保了redis極高的性能。


如果需要進(jìn)行大規(guī)模數(shù)據(jù)的恢復(fù),且對(duì)于數(shù)據(jù)恢復(fù)的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。


雖然 RDB 有不少優(yōu)點(diǎn),但它的缺點(diǎn)也是不容忽視的。如果你對(duì)數(shù)據(jù)的完整性非常敏感,那么 RDB 方式就不太適合你,因?yàn)榧词鼓忝?5 分鐘都持久化一次,當(dāng) redis 故障時(shí),仍然會(huì)有近 5 分鐘的數(shù)據(jù)丟失。所以,redis 還提供了另一種持久化方式,那就是 AOF。


AOF


本段內(nèi)容來(lái)自 Linux大棚版redis入門(mén)教程(http:///?p=3196)


AOF,英文是 Append Only File,即只允許追加不允許改寫(xiě)的文件。如前面介紹的,AOF 方式是將執(zhí)行過(guò)的寫(xiě)指令記錄下來(lái),在數(shù)據(jù)恢復(fù)時(shí)按照從前到后的順序再將指令都執(zhí)行一遍,就這么簡(jiǎn)單。


我們通過(guò)配置 redis.conf 中的 appendonly yes 就可以打開(kāi) AOF 功能。如果有寫(xiě)操作(如SET等),redis 就會(huì)被追加到 AOF 文件的末尾。


默認(rèn)的 AOF 持久化策略是每秒鐘 fsync 一次(fsync 是指把緩存中的寫(xiě)指令記錄到磁盤(pán)中),因?yàn)樵谶@種情況下,redis 仍然可以保持很好的處理性能,即使 redis 故障,也只會(huì)丟失最近 1 秒鐘的數(shù)據(jù)。


如果在追加日志時(shí),恰好遇到磁盤(pán)空間滿(mǎn)、inode 滿(mǎn)或斷電等情況導(dǎo)致日志寫(xiě)入不完整,也沒(méi)有關(guān)系,redis 提供了 redis-check-aof 工具,可以用來(lái)進(jìn)行日志修復(fù)。


因?yàn)椴捎昧俗芳臃绞?,如果不做任何處理的?huà),AOF 文件會(huì)變得越來(lái)越大,為此,redis 提供了 AOF 文件重寫(xiě)(rewrite)機(jī)制,即當(dāng) AOF 文件的大小超過(guò)所設(shè)定的閾值時(shí),redis 就會(huì)啟動(dòng) AOF 文件的內(nèi)容壓縮,只保留可以恢復(fù)數(shù)據(jù)的最小指令集。舉個(gè)例子或許更形象,假如我們調(diào)用了 100 次INCR指令,在 AOF 文件中就要存儲(chǔ) 100 條指令,但這明顯是很低效的,完全可以把這 100 條指令合并成一條 SET 指令,這就是重寫(xiě)機(jī)制的原理。


在進(jìn)行 AOF 重寫(xiě)時(shí),仍然是采用先寫(xiě)臨時(shí)文件,全部完成后再替換的流程,所以斷電、磁盤(pán)滿(mǎn)等問(wèn)題都不會(huì)影響 AOF 文件的可用性,這點(diǎn)大家可以放心。


AOF方式的另一個(gè)好處,我們通過(guò)一個(gè)“場(chǎng)景再現(xiàn)”來(lái)說(shuō)明。某同學(xué)在操作 redis 時(shí),不小心執(zhí)行了 FLUSHALL,導(dǎo)致 redis 內(nèi)存中的數(shù)據(jù)全部被清空了,這是很悲劇的事情。不過(guò)這也不是世界末日,只要 redis 配置了 AOF 持久化方式,且 AOF 文件還沒(méi)有被重寫(xiě)(rewrite),我們就可以用最快的速度暫停 redis 并編輯 AOF 文件,將最后一行的 FLUSHALL 命令刪除,然后重啟 redis,就可以恢復(fù) redis 的所有數(shù)據(jù)到 FLUSHALL 之前的狀態(tài)了。是不是很神奇,這就是 AOF 持久化方式的好處之一。但是如果 AOF 文件已經(jīng)被重寫(xiě)了,那就無(wú)法通過(guò)這種方法來(lái)恢復(fù)數(shù)據(jù)了。


雖然優(yōu)點(diǎn)多多,但 AOF 方式也同樣存在缺陷,比如在同樣數(shù)據(jù)規(guī)模的情況下,AOF 文件要比 RDB 文件的體積大。而且,AOF 方式的恢復(fù)速度也要慢于 RDB 方式。


如果你直接執(zhí)行 BGREWRITEAOF 命令,那么 redis 會(huì)生成一個(gè)全新的 AOF 文件,其中便包括了可以恢復(fù)現(xiàn)有數(shù)據(jù)的最少的命令集。


如果運(yùn)氣比較差,AOF 文件出現(xiàn)了被寫(xiě)壞的情況,也不必過(guò)分擔(dān)憂(yōu),redis 并不會(huì)貿(mào)然加載這個(gè)有問(wèn)題的 AOF 文件,而是報(bào)錯(cuò)退出。這時(shí)可以通過(guò)以下步驟來(lái)修復(fù)出錯(cuò)的文件:


  1. 備份被寫(xiě)壞的 AOF 文件

  2. 運(yùn)行 redis-check-aof –fix 進(jìn)行修復(fù)

  3. 用 diff -u 來(lái)看下兩個(gè)文件的差異,確認(rèn)問(wèn)題點(diǎn)

  4. 重啟 redis,加載修復(fù)后的 AOF 文件


AOF 重寫(xiě)的內(nèi)部運(yùn)行原理,我們有必要了解一下。在重寫(xiě)即將開(kāi)始之際,redis 會(huì)創(chuàng)建(fork)一個(gè)“重寫(xiě)子進(jìn)程”,這個(gè)子進(jìn)程會(huì)首先讀取現(xiàn)有的 AOF 文件,并將其包含的指令進(jìn)行分析壓縮并寫(xiě)入到一個(gè)臨時(shí)文件中。


與此同時(shí),主工作進(jìn)程會(huì)將新接收到的寫(xiě)指令一邊累積到內(nèi)存緩沖區(qū)中,一邊繼續(xù)寫(xiě)入到原有的 AOF 文件中,這樣做是保證原有的 AOF 文件的可用性,避免在重寫(xiě)過(guò)程中出現(xiàn)意外。


當(dāng)“重寫(xiě)子進(jìn)程”完成重寫(xiě)工作后,它會(huì)給父進(jìn)程發(fā)一個(gè)信號(hào),父進(jìn)程收到信號(hào)后就會(huì)將內(nèi)存中緩存的寫(xiě)指令追加到新 AOF 文件中。


當(dāng)追加結(jié)束后,redis 就會(huì)用新 AOF 文件來(lái)代替舊 AOF 文件,之后再有新的寫(xiě)指令,就都會(huì)追加到新的 AOF 文件中了。


我們應(yīng)該選擇RDB還是AOF,官方的建議是兩個(gè)同時(shí)使用。這樣可以提供更可靠的持久化方案。


增強(qiáng)功能


主從同步


本段內(nèi)容大部分來(lái)自 Linux大棚版redis入門(mén)教程


像 MySQL 一樣,redis 是支持主從同步的,而且也支持一主多從以及多級(jí)從結(jié)構(gòu)。主從結(jié)構(gòu),一是為了純粹的冗余備份,二是為了提升讀性能,比如很消耗性能的 SORT 就可以由從服務(wù)器來(lái)承擔(dān)。在具體的實(shí)踐中,可能還需要考慮到具體的法律法規(guī)原因,單純的主從結(jié)構(gòu)沒(méi)有辦法應(yīng)對(duì)多機(jī)房跨國(guó)可能帶來(lái)的數(shù)據(jù)存儲(chǔ)問(wèn)題,這里需要特別注意一下


redis 的主從同步是異步進(jìn)行的,這意味著主從同步不會(huì)影響主邏輯,也不會(huì)降低 redis 的處理性能。主從架構(gòu)中,可以考慮關(guān)閉主服務(wù)器的數(shù)據(jù)持久化功能,只讓從服務(wù)器進(jìn)行持久化,這樣可以提高主服務(wù)器的處理性能。


在主從架構(gòu)中,從服務(wù)器通常被設(shè)置為只讀模式,這樣可以避免從服務(wù)器的數(shù)據(jù)被誤修改。但是從服務(wù)器仍然可以接受 CONFIG 等指令,所以還是不應(yīng)該將從服務(wù)器直接暴露到不安全的網(wǎng)絡(luò)環(huán)境中。如果必須如此,那可以考慮給重要指令進(jìn)行重命名,來(lái)避免命令被外人誤執(zhí)行。


具體的同步原理也值得了解一下:


從服務(wù)器會(huì)向主服務(wù)器發(fā)出 SYNC 指令,當(dāng)主服務(wù)器接到此命令后,就會(huì)調(diào)用 BGSAVE 指令來(lái)創(chuàng)建一個(gè)子進(jìn)程專(zhuān)門(mén)進(jìn)行數(shù)據(jù)持久化工作,也就是將主服務(wù)器的數(shù)據(jù)寫(xiě)入 RDB 文件中。在數(shù)據(jù)持久化期間,主服務(wù)器將執(zhí)行的寫(xiě)指令都緩存在內(nèi)存中。


在 BGSAVE 指令執(zhí)行完成后,主服務(wù)器會(huì)將持久化好的 RDB 文件發(fā)送給從服務(wù)器,從服務(wù)器接到此文件后會(huì)將其存儲(chǔ)到磁盤(pán)上,然后再將其讀取到內(nèi)存中。這個(gè)動(dòng)作完成后,主服務(wù)器會(huì)將這段時(shí)間緩存的寫(xiě)指令再以 redis 協(xié)議的格式發(fā)送給從服務(wù)器。


另外,要說(shuō)的一點(diǎn)是,即使有多個(gè)從服務(wù)器同時(shí)發(fā)來(lái) SYNC 指令,主服務(wù)器也只會(huì)執(zhí)行一次BGSAVE,然后把持久化好的 RDB 文件發(fā)給多個(gè)下游。在 redis2.8 版本之前,如果從服務(wù)器與主服務(wù)器因某些原因斷開(kāi)連接的話(huà),都會(huì)進(jìn)行一次主從之間的全量的數(shù)據(jù)同步;而在 2.8 版本之后,redis 支持了效率更高的增量同步策略,這大大降低了連接斷開(kāi)的恢復(fù)成本。


主服務(wù)器會(huì)在內(nèi)存中維護(hù)一個(gè)緩沖區(qū),緩沖區(qū)中存儲(chǔ)著將要發(fā)給從服務(wù)器的內(nèi)容。從服務(wù)器在與主服務(wù)器出現(xiàn)網(wǎng)絡(luò)瞬斷之后,從服務(wù)器會(huì)嘗試再次與主服務(wù)器連接,一旦連接成功,從服務(wù)器就會(huì)把“希望同步的主服務(wù)器ID”和“希望請(qǐng)求的數(shù)據(jù)的偏移位置(replication offset)”發(fā)送出去。主服務(wù)器接收到這樣的同步請(qǐng)求后,首先會(huì)驗(yàn)證主服務(wù)器ID是否和自己的ID匹配,其次會(huì)檢查“請(qǐng)求的偏移位置”是否存在于自己的緩沖區(qū)中,如果兩者都滿(mǎn)足的話(huà),主服務(wù)器就會(huì)向從服務(wù)器發(fā)送增量?jī)?nèi)容。


事務(wù)處理


本段內(nèi)容大部分來(lái)自 Linux大棚版redis入門(mén)教程


數(shù)據(jù)庫(kù)原理中很重要的一個(gè)概念是『事務(wù)』,簡(jiǎn)單來(lái)說(shuō)就是把一系列動(dòng)作看做一個(gè)整體,如果其中一個(gè)出了問(wèn)題,應(yīng)該把狀態(tài)恢復(fù)到執(zhí)行該整體之前的狀態(tài)。在 Redis 中,MULTI、EXEC、DISCARD、WATCH 這四個(gè)指令是事務(wù)處理的基礎(chǔ)。


  • MULTI用來(lái)組裝一個(gè)事務(wù);

  • EXEC用來(lái)執(zhí)行一個(gè)事務(wù);

  • DISCARD用來(lái)取消一個(gè)事務(wù);

  • WATCH用來(lái)監(jiān)視一些key,一旦這些key在事務(wù)執(zhí)行之前被改變,則取消事務(wù)的執(zhí)行。


舉個(gè)例子:




在上面的例子中,我們看到了 QUEUED 的字樣,這表示我們?cè)谟?MULTI 組裝事務(wù)時(shí),每一個(gè)命令都會(huì)進(jìn)入到內(nèi)存隊(duì)列中緩存起來(lái),如果出現(xiàn) QUEUED 則表示我們這個(gè)命令成功插入了緩存隊(duì)列,在將來(lái)執(zhí)行 EXEC 時(shí),這些被 QUEUED 的命令都會(huì)被組裝成一個(gè)事務(wù)來(lái)執(zhí)行。


對(duì)于事務(wù)的執(zhí)行來(lái)說(shuō),如果 redis 開(kāi)啟了 AOF 持久化的話(huà),那么一旦事務(wù)被成功執(zhí)行,事務(wù)中的命令就會(huì)通過(guò) write 命令一次性寫(xiě)到磁盤(pán)中去,如果在向磁盤(pán)中寫(xiě)的過(guò)程中恰好出現(xiàn)斷電、硬件故障等問(wèn)題,那么就可能出現(xiàn)只有部分命令進(jìn)行了 AOF 持久化,這時(shí) AOF 文件就會(huì)出現(xiàn)不完整的情況,這時(shí),我們可以使用 redis-check-aof 工具來(lái)修復(fù)這一問(wèn)題,這個(gè)工具會(huì)將 AOF 文件中不完整的信息移除,確保 AOF 文件完整可用。


然后我們來(lái)說(shuō)說(shuō) WATCH 這個(gè)指令,它可以幫我們實(shí)現(xiàn)類(lèi)似于“樂(lè)觀鎖”的效果,即CAS(check and set)。WATCH本身的作用是“監(jiān)視key是否被改動(dòng)過(guò)”,而且支持同時(shí)監(jiān)視多個(gè)key,只要還沒(méi)真正觸發(fā)事務(wù),WATCH都會(huì)盡職盡責(zé)的監(jiān)視,一旦發(fā)現(xiàn)某個(gè)key被修改了,在執(zhí)行EXEC時(shí)就會(huì)返回nil,表示事務(wù)無(wú)法觸發(fā)。例如:



因?yàn)?name 在 exec 之前被改變了,可以認(rèn)為這個(gè)值是臟(dirty) 的,于是之后的操作很可能是危險(xiǎn)且沒(méi)有意義的,自然就不會(huì)執(zhí)行了。


發(fā)布訂閱


Redis 的發(fā)布/訂閱(pub/sub) 是一種消息通信模型,Redis 客戶(hù)端可以訂閱任意數(shù)量的頻道,一旦某頻道接收到消息時(shí),訂閱它的客戶(hù)端便會(huì)收到消息。這里我們需要兩個(gè)終端來(lái)完成這次實(shí)驗(yàn),在終端 1 中做如下操作:


127.0.0.1:6379> SUBSCRIBE wdxtubBlog

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

1) 'subscribe'

2) 'wdxtubBlog'

3) (integer) 1


然后在終端 2 中向該頻道發(fā)送消息


127.0.0.1:6379> PUBLISH wdxtubBlog 'new post updated!'

(integer) 1

127.0.0.1:6379> PUBLISH wdxtubBlog 'visit for more!'

(integer) 1


然后我們?cè)诮K端 1 中就可以看到對(duì)應(yīng)的消息:


127.0.0.1:6379> SUBSCRIBE wdxtubBlog

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

1) 'subscribe'

2) 'wdxtubBlog'

3) (integer) 1

1) 'message'

2) 'wdxtubBlog'

3) 'new post updated!'

1) 'message'

2) 'wdxtubBlog'

3) 'visit for more!'


性能測(cè)試


在配置好 Redis 后,我們可以通過(guò)自帶的性能測(cè)試來(lái)查看 Redis 在這臺(tái)服務(wù)器上的表現(xiàn),據(jù)此決定是否應(yīng)該進(jìn)行配置和服務(wù)調(diào)整,例如:



測(cè)試內(nèi)容還是不少的,可以根據(jù)這些數(shù)據(jù)來(lái)進(jìn)行優(yōu)化相關(guān)工作。


連接與管道


Redis 通過(guò)監(jiān)聽(tīng)一個(gè) TCP 端口或者 Unix socket 的方式來(lái)接收來(lái)自客戶(hù)端的連接,當(dāng)一個(gè)連接建立后,Redis 內(nèi)部會(huì)進(jìn)行以下一些操作:


  1. 客戶(hù)端 socket 會(huì)被設(shè)置為非阻塞模式,因?yàn)?Redis 在網(wǎng)絡(luò)事件處理上采用的是非阻塞多路復(fù)用模型。

  2. 為這個(gè) socket 設(shè)置 TCP_NODELAY 屬性,禁用 Nagle 算法。Nagle 算法實(shí)際就是當(dāng)需要發(fā)送的數(shù)據(jù)攢到一定程度時(shí)才真正進(jìn)行發(fā)包,通過(guò)這種方式來(lái)減少 header 數(shù)據(jù)占比的問(wèn)題。不過(guò)在高互動(dòng)的環(huán)境下是不必要的,一般來(lái)說(shuō),在客戶(hù)端/服務(wù)器模型中會(huì)禁用。更多信息可在參考鏈接中查看。

  3. 創(chuàng)建一個(gè)可讀的文件事件用于監(jiān)聽(tīng)這個(gè)客戶(hù)端 socket 的數(shù)據(jù)發(fā)送


Redis 管道技術(shù)可以在服務(wù)端未響應(yīng)時(shí),客戶(hù)端可以繼續(xù)向服務(wù)端發(fā)送請(qǐng)求,并最終一次性讀取所有服務(wù)端的響應(yīng)。管道技術(shù)最顯著的優(yōu)勢(shì)是提高了 redis 服務(wù)的性能。


分區(qū)


本段內(nèi)容主要來(lái)自 Redis 分區(qū)(http://www.runoob.com/redis/redis-partitioning.html)


分區(qū)是分割數(shù)據(jù)到多個(gè) Redis 實(shí)例的處理過(guò)程,因此每個(gè)實(shí)例只保存 key 的一個(gè)子集。分區(qū)的優(yōu)勢(shì)有很多,尤其是在大數(shù)據(jù)當(dāng)?shù)赖慕裉欤枰煤侠淼姆謪^(qū)機(jī)制來(lái)完成更加復(fù)雜的工作。


  • 通過(guò)利用多臺(tái)計(jì)算機(jī)內(nèi)存的和值,允許我們構(gòu)造更大的數(shù)據(jù)庫(kù)

  • 通過(guò)多核和多臺(tái)計(jì)算機(jī),允許我們擴(kuò)展計(jì)算能力

  • 通過(guò)多臺(tái)計(jì)算機(jī)和網(wǎng)絡(luò)適配器,允許我們擴(kuò)展網(wǎng)絡(luò)帶寬


分區(qū)實(shí)際上把數(shù)據(jù)進(jìn)行了隔離,如果原本應(yīng)該在同一分區(qū)的數(shù)據(jù)被放在了不同分區(qū),或者原本沒(méi)有太多關(guān)系的數(shù)據(jù)因?yàn)樾碌臉I(yè)務(wù)產(chǎn)生了關(guān)系,就會(huì)遇到一些問(wèn)題:


  • 涉及多個(gè) key 的操作通常是不被支持的。舉例來(lái)說(shuō),當(dāng)兩個(gè) set 映射到不同的 redis 實(shí)例上時(shí),你就不能對(duì)這兩個(gè) set 執(zhí)行交集操作

  • 涉及多個(gè) key 的 redis 事務(wù)不能使用

  • 當(dāng)使用分區(qū)時(shí),數(shù)據(jù)處理較為復(fù)雜,比如你需要處理多個(gè) rdb/aof 文件,并且從多個(gè)實(shí)例和主機(jī)備份持久化文件

  • 增加或刪除容量也比較復(fù)雜。redis 集群大多數(shù)支持在運(yùn)行時(shí)增加、刪除節(jié)點(diǎn)的透明數(shù)據(jù)平衡的能力,但是類(lèi)似于客戶(hù)端分區(qū)、代理等其他系統(tǒng)則不支持這項(xiàng)特性。然而,一種叫做 presharding 的技術(shù)對(duì)此是有幫助的。


Redis 有兩種類(lèi)型分區(qū)。 假設(shè)有 4 個(gè) Redis實(shí)例 R0,R1,R2,R3,和類(lèi)似 user:1,user:2 這樣的表示用戶(hù)的多個(gè) key,對(duì)既定的 key 有多種不同方式來(lái)選擇這個(gè) key 存放在哪個(gè)實(shí)例中。也就是說(shuō),有不同的系統(tǒng)來(lái)映射某個(gè) key 到某個(gè) Redis 服務(wù)。


范圍分區(qū)


最簡(jiǎn)單的分區(qū)方式是按范圍分區(qū),就是映射一定范圍的對(duì)象到特定的 Redis 實(shí)例。比如,ID 從 0 到 10000 的用戶(hù)會(huì)保存到實(shí)例 R0,ID 從 10001 到 20000 的用戶(hù)會(huì)保存到 R1,以此類(lèi)推。這種方式的不足之處是要有一個(gè)區(qū)間范圍到實(shí)例的映射表,同時(shí)還需要各種對(duì)象的映射表,通常對(duì) Redis 來(lái)說(shuō)并非是好的方法。


哈希分區(qū)


另外一種分區(qū)方法是 hash 分區(qū)。這對(duì)任何 key 都適用,也無(wú)需是 object_name: 這種形式,只需要確定統(tǒng)一的哈希函數(shù),然后通過(guò)取模確定應(yīng)該保存在哪個(gè)分區(qū)即可。


總結(jié)


相比于在學(xué)校必須手寫(xiě)自己的緩存,使用 Redis(或是 memcache)簡(jiǎn)直太爽了,工作一段時(shí)間了,越發(fā)覺(jué)得技術(shù)的門(mén)檻其實(shí)越來(lái)越低,如何打造高效團(tuán)隊(duì),如何把架構(gòu)設(shè)計(jì)得更加合理,才是真正體現(xiàn)差距的地方。


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多

    亚洲国产欧美久久精品| 欧美老太太性生活大片| 在线视频三区日本精品| 在线亚洲成人中文字幕高清| 免费在线播放不卡视频| 亚洲中文字幕在线观看黑人| 日韩一本不卡在线观看| 国产亚洲欧美日韩精品一区| 亚洲国产丝袜一区二区三区四| 欧美日韩国产福利在线观看| 91福利视频日本免费看看| 丰满少妇高潮一区二区| 日本午夜免费啪视频在线| 色婷婷视频在线精品免费观看| 一区二区三区亚洲国产| 日韩国产亚洲欧美另类| 粉嫩内射av一区二区| 天堂热东京热男人天堂| 欧美成人国产精品高清| 亚洲日本加勒比在线播放| 激情中文字幕在线观看 | 久热99中文字幕视频在线| 日韩视频在线观看成人| 国产一级性生活录像片| 欧美日韩一区二区午夜| 日韩亚洲精品国产第二页| 成在线人免费视频一区二区| 午夜小视频成人免费看| 妻子的新妈妈中文字幕| 深夜福利欲求不满的人妻| 亚洲高清中文字幕一区二区三区| 国产精品香蕉免费手机视频| 欧美又黑又粗大又硬又爽| 日本午夜乱色视频在线观看| 欧美美女视频在线免费看| 91国内视频一区二区三区| 久久精品少妇内射毛片| 伊人网免费在线观看高清版| 日本人妻免费一区二区三区| 99少妇偷拍视频在线| 日本女人亚洲国产性高潮视频|