redis

最近參與了一些項目,其中包含單點登陸(集群),因為使用的redis,所以這里簡單對redis做一個學習總結(jié),reids的API的話就不放在本文浪費時間了,主要談談知識的本身

在開始redis之前,我們要了解,現(xiàn)在當作非關(guān)系型數(shù)據(jù)庫遠遠不止redis這一種,當然,以后可能也會更多,若是要依次學習所有的這類數(shù)據(jù)庫,那是很困難的,但他們都屬于nosql(not only sql非關(guān)系型數(shù)據(jù)庫),所以,我們有必要先了解其根源,找到他們的通性,從其名字也可以看出,他和關(guān)系型數(shù)據(jù)庫不是對立的,更多的是一種補充

Nosql

為什么要有Nosql?

目前互聯(lián)網(wǎng)對技術(shù)提出了更多的要求,主要體現(xiàn)在以下方面:

低延遲的讀寫速度:應用快速地反應能極大地提升用戶的滿意度;

海量的數(shù)據(jù)和流量:對于搜索這樣大型應用而言,需要利用PB級別的數(shù)據(jù)和能應對百萬級的流量;

大規(guī)模集群的管理:系統(tǒng)管理員希望分布式應用能更簡單的部署和管理;

龐大運營成本的考量:IT經(jīng)理們希望在硬件成本、軟件成本和人力成本能夠有大幅度地降低;

但是,關(guān)系型數(shù)據(jù)庫由于自身的特點,讓他很難實現(xiàn)這些需求:

擴展困難

讀寫慢

成本高

支撐容量有限

所以,Nosql非常關(guān)注并發(fā)讀寫,大量數(shù)據(jù)存儲,它的優(yōu)點如下:

高可擴展性

分布式計算

低成本

架構(gòu)的靈活性,半結(jié)構(gòu)化數(shù)據(jù)

沒有復雜的關(guān)系

當然,Nosql也有缺點:

不提供SQL語句支持

特性不夠多(例如事務,在等會redis中會總結(jié))

Nosql四大分類

鍵值(Key-Value)存儲數(shù)據(jù)庫

相關(guān)產(chǎn)品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB 典型應用: 內(nèi)容緩存,主要用于處理大量數(shù)據(jù)的高訪問負載。 數(shù)據(jù)模型: 一系列鍵值對 優(yōu)勢: 快速查詢 劣勢: 存儲的數(shù)據(jù)缺少結(jié)構(gòu)化

列存儲數(shù)據(jù)庫

相關(guān)產(chǎn)品:Cassandra, HBase, Riak 典型應用:分布式的文件系統(tǒng) 數(shù)據(jù)模型:以列簇式存儲,將同一列數(shù)據(jù)存在一起 優(yōu)勢:查找速度快,可擴展性強,更容易進行分布式擴展 劣勢:功能相對局限

文檔型數(shù)據(jù)庫

相關(guān)產(chǎn)品:CouchDB、MongoDB 典型應用:Web應用(與Key-Value類似,Value是結(jié)構(gòu)化的) 數(shù)據(jù)模型: 一系列鍵值對 優(yōu)勢:數(shù)據(jù)結(jié)構(gòu)要求不嚴格 劣勢: 查詢性能不高,而且缺乏統(tǒng)一的查詢語法

圖形(Graph)數(shù)據(jù)庫

相關(guān)數(shù)據(jù)庫:Neo4J、InfoGrid、Infinite Graph 典型應用:社交網(wǎng)絡 數(shù)據(jù)模型:圖結(jié)構(gòu) 優(yōu)勢:利用圖結(jié)構(gòu)相關(guān)算法。 劣勢:需要對整個圖做計算才能得出結(jié)果,不容易做分布式的集群方案。

CAP定理

CAP定理意思是在分布式計算系統(tǒng)中只能同時最多滿足以下兩點

一致性(Consistency) (所有節(jié)點在同一時間具有相同的數(shù)據(jù))

可用性(Availability) (保證每個請求不管成功或者失敗都有響應)

分隔容忍(Partition tolerance) (系統(tǒng)中任意信息的丟失或失敗不會影響系統(tǒng)的繼續(xù)運作)

CAP理論的核心是:一個分布式系統(tǒng)不可能同時很好的滿足一致性,可用性和分區(qū)容錯性這三個需求,最多只能同時較好的滿足兩個。

因此,根據(jù) CAP 原理將 NoSQL 數(shù)據(jù)庫分成了滿足 CA 原則、滿足 CP 原則和滿足 AP 原則三 大類:

CA - 單點集群,滿足一致性,可用性的系統(tǒng),通常在可擴展性上不太強大。(傳統(tǒng)Oracle數(shù)據(jù)庫)

CP - 滿足一致性,分區(qū)容忍性的系統(tǒng),通常性能不是特別高。(Redis、Mongodb)

AP - 滿足可用性,分區(qū)容忍性的系統(tǒng),通??赡軐σ恢滦砸蟮鸵恍?大多數(shù)網(wǎng)站架構(gòu)的選擇)

image

注意:分布式架構(gòu)的時候必須做出取舍。一致性和可用性之間取一個平衡。多余大多數(shù)web應用,其實并不需要強一致性。因此犧牲C換取P,這是目前分布式數(shù)據(jù)庫產(chǎn)品的方向

Nosql總結(jié)

綜上所述,Nosql的出現(xiàn)更多的是為了解決數(shù)據(jù)量大,分布式中的問題,為了數(shù)據(jù)吞吐量上的數(shù)量而對數(shù)據(jù)一致性打一點折扣。

e.g:

微博上一篇文章的點贊數(shù),可能三秒內(nèi)就會新增幾百個贊(行為數(shù)據(jù)),這時,不可能保證用戶點一個贊就更新一次,這時,就可以使用Nosql了。

而對于像轉(zhuǎn)賬這類(交易數(shù)據(jù))的事務型操作,只能使用關(guān)系型數(shù)據(jù)庫了。

Redis

Redis是什么

它是一個緩存數(shù)據(jù)庫,由C語言編寫,key-value存儲系統(tǒng),屬于nosql

五大基本數(shù)據(jù)類型

1.字符串類型(String)

2.散列類型(hash)

3.列表類型(list)

4.集合類型(set)

5.有序集合類型(zset)

因為redis中都是存取的k-v鍵值對形式,這里的基本數(shù)據(jù)類型指的是value的數(shù)據(jù)類型,所有的key都是字符串類型

關(guān)于它的API,這里就不贅述了,看官方文檔即可

字符串類型

字符串是Redis最基本的數(shù)據(jù)類型,不僅所有key都是字符串類型,其它幾種數(shù)據(jù)類型構(gòu)成的元素也是字符串。注意字符串的長度不能超過512M。

這里的字符串可以是字符串,整數(shù)或者是浮點數(shù),例如想知道一個ip訪問了多少次本網(wǎng)站,就可以用INCRBY實現(xiàn)遞增。

列表類型

一個List結(jié)構(gòu)可以有序的存儲多個字符串,并且是允許元素重復的,可以按照插入順序排序,可以添加一個元素到列表的頭部(左邊)或者尾部(右邊),它的底層實際上是個雙向鏈表結(jié)構(gòu)。

Set集合類型

集合對象 set 是 string 類型(整數(shù)也會轉(zhuǎn)換成string類型進行存儲)的無序集合。通過散列表來保證自己存儲的每個字符串都是各不相同的,即內(nèi)部使用值為空的散列表。

集合和列表的區(qū)別:集合中的元素是無序的,因此不能通過索引來操作元素;集合中的元素不能有重復。

Hash散列類型

哈希對象的鍵是一個字符串類型,值是一個鍵值對集合。

有序集合ZSET

有序集合對象是有序的。與列表使用索引下標作為排序依據(jù)不同,有序集合為每個元素設(shè)置一個分數(shù)(score)作為排序依據(jù)。

應用場景

對于string 數(shù)據(jù)類型,因為string 類型是二進制安全的,可以用來存放圖片,視頻等內(nèi)容,另外由于Redis的高性能讀寫功能,而string類型的value也可以是數(shù)字,可以用作計數(shù)器(INCR,DECR),比如分布式環(huán)境中統(tǒng)計系統(tǒng)的在線人數(shù),秒殺等。

對于 hash 數(shù)據(jù)類型,value 存放的是鍵值對,比如可以做單點登錄存放用戶信息。

對于 list 數(shù)據(jù)類型,可以實現(xiàn)簡單的消息隊列,另外可以利用lrange命令,做基于redis的分頁功能

對于 set 數(shù)據(jù)類型,由于底層是字典實現(xiàn)的,查找元素特別快,另外set 數(shù)據(jù)類型不允許重復,利用這兩個特性我們可以進行全局去重,比如在用戶注冊模塊,判斷用戶名是否注冊;另外就是利用交集、并集、差集等操作,可以計算共同喜好,全部的喜好,自己獨有的喜好等功能。

對于 zset 數(shù)據(jù)類型,有序的集合,可以做范圍查找,排行榜應用,取 TOP N 操作等。

推薦一個Java工程師學習交流群:795632998,群內(nèi)有分布式架構(gòu)、高性能、高并發(fā)、性能優(yōu)化、Spring boot、Redis、ActiveMQ、Nginx、Netty、Jvm等視頻資料提供學習參考

配置文件介紹

redis.conf

Redis configuration file example.

./redis-server /path/to/redis.conf

################################## INCLUDES ###################################

這在你有標準配置模板但是每個redis服務器又需要個性設(shè)置的時候很有用。

include /path/to/local.conf

include /path/to/other.conf

################################ GENERAL #####################################

是否在后臺執(zhí)行,yes:后臺運行;no:不是后臺運行(老版本默認)

daemonize yes

3.2里的參數(shù),是否開啟保護模式,默認開啟。要是配置里沒有指定bind和密碼。開啟該參數(shù)后,redis只會本地進行訪問,拒絕外部訪問。要是開啟了密碼 和bind,可以開啟。否 則最好關(guān)閉,設(shè)置為no。

protected-mode yes

redis的進程文件

pidfile /var/run/redis/redis-server.pid

redis監(jiān)聽的端口號。

port 6379

此參數(shù)確定了TCP連接中已完成隊列(完成三次握手之后)的長度, 當然此值必須不大于Linux系統(tǒng)定義的/proc/sys/net/core/somaxconn值,默認是511,而Linux的默認參數(shù)值是128。當系統(tǒng)并發(fā)量大并且客戶端速度緩慢的時候,可以將這二個參數(shù)一起參考設(shè)定。該內(nèi)核參數(shù)默認值一般是128,對于負載很大的服務程序來說大大的不夠。一般會將它修改為2048或者更大。在/etc/sysctl.conf中添加:net.core.somaxconn = 2048,然后在終端中執(zhí)行sysctl -p。

tcp-backlog 511

指定 redis 只接收來自于該 IP 地址的請求,如果不進行設(shè)置,那么將處理所有請求

bind 127.0.0.1

配置unix socket來讓redis支持監(jiān)聽本地連接。

unixsocket /var/run/redis/redis.sock

配置unix socket使用文件的權(quán)限

unixsocketperm 700

此參數(shù)為設(shè)置客戶端空閑超過timeout,服務端會斷開連接,為0則服務端不會主動斷開連接,不能小于0。

timeout 0

tcp keepalive參數(shù)。如果設(shè)置不為0,就使用配置tcp的SO_KEEPALIVE值,使用keepalive有兩個好處:檢測掛掉的對端。降低中間設(shè)備出問題而導致網(wǎng)絡看似連接卻已經(jīng)與對端端口的問題。在Linux內(nèi)核中,設(shè)置了keepalive,redis會定時給對端發(fā)送ack。檢測到對端關(guān)閉需要兩倍的設(shè)置值。

tcp-keepalive 0

指定了服務端日志的級別。級別包括:debug(很多信息,方便開發(fā)、測試),verbose(許多有用的信息,但是沒有debug級別信息多),notice(適當?shù)娜罩炯墑e,適合生產(chǎn)環(huán)境),warn(只有非常重要的信息)

loglevel notice

指定了記錄日志的文件??兆址脑?,日志會打印到標準輸出設(shè)備。后臺運行的redis標準輸出是/dev/null。

logfile /var/log/redis/redis-server.log

是否打開記錄syslog功能

syslog-enabled no

syslog的標識符。

syslog-ident redis

日志的來源、設(shè)備

syslog-facility local0

數(shù)據(jù)庫的數(shù)量,默認使用的數(shù)據(jù)庫是DB 0??梢酝ㄟ^”SELECT “命令選擇一個db

databases 16

################################ SNAPSHOTTING ################################

快照配置

注釋掉“save”這一行配置項就可以讓保存數(shù)據(jù)庫功能失效

設(shè)置sedis進行數(shù)據(jù)庫鏡像的頻率。

900秒(15分鐘)內(nèi)至少1個key值改變(則進行數(shù)據(jù)庫保存--持久化)

300秒(5分鐘)內(nèi)至少10個key值改變(則進行數(shù)據(jù)庫保存--持久化)

60秒(1分鐘)內(nèi)至少10000個key值改變(則進行數(shù)據(jù)庫保存--持久化)

save 900 1

save 300 10

save 60 10000

當RDB持久化出現(xiàn)錯誤后,是否依然進行繼續(xù)進行工作,yes:不能進行工作,no:可以繼續(xù)進行工作,可以通過info中的rdb_last_bgsave_status了解RDB持久化是否有錯誤

stop-writes-on-bgsave-error yes

使用壓縮rdb文件,rdb文件壓縮使用LZF壓縮算法,yes:壓縮,但是需要一些cpu的消耗。no:不壓縮,需要更多的磁盤空間

rdbcompression yes

是否校驗rdb文件。從rdb格式的第五個版本開始,在rdb文件的末尾會帶上CRC64的校驗和。這跟有利于文件的容錯性,但是在保存rdb文件的時候,會有大概10%的性能損耗,所以如果你追求高性能,可以關(guān)閉該配置。

rdbchecksum yes

rdb文件的名稱

dbfilename dump.rdb

數(shù)據(jù)目錄,數(shù)據(jù)庫的寫入會在這個目錄。rdb、aof文件也會寫在這個目錄

dir /var/lib/redis

################################# REPLICATION #################################

復制選項,slave復制對應的master。

slaveof <masterip> <masterport>

如果master設(shè)置了requirepass,那么slave要連上master,需要有master的密碼才行。masterauth就是用來配置master的密碼,這樣可以在連上master后進行認證。

masterauth <master-password>

當從庫同主機失去連接或者復制正在進行,從機庫有兩種運行方式:1) 如果slave-serve-stale-data設(shè)置為yes(默認設(shè)置),從庫會繼續(xù)響應客戶端的請求。2) 如果slave-serve-stale-data設(shè)置為no,除去INFO和SLAVOF命令之外的任何請求都會返回一個錯誤”SYNC with master in progress”。

slave-serve-stale-data yes

作為從服務器,默認情況下是只讀的(yes),可以修改成NO,用于寫(不建議)。

slave-read-only yes

是否使用socket方式復制數(shù)據(jù)。目前redis復制提供兩種方式,disk和socket。如果新的slave連上來或者重連的slave無法部分同步,就會執(zhí)行全量同步,master會生成rdb文件。有2種方式:disk方式是master創(chuàng)建一個新的進程把rdb文件保存到磁盤,再把磁盤上的rdb文件傳遞給slave。socket是master創(chuàng)建一個新的進程,直接把rdb文件以socket的方式發(fā)給slave。disk方式的時候,當一個rdb保存的過程中,多個slave都能共享這個rdb文件。socket的方式就的一個個slave順序復制。在磁盤速度緩慢,網(wǎng)速快的情況下推薦用socket方式。

repl-diskless-sync no

diskless復制的延遲時間,防止設(shè)置為0。一旦復制開始,節(jié)點不會再接收新slave的復制請求直到下一個rdb傳輸。所以最好等待一段時間,等更多的slave連上來。

repl-diskless-sync-delay 5

slave根據(jù)指定的時間間隔向服務器發(fā)送ping請求。時間間隔可以通過 repl_ping_slave_period 來設(shè)置,默認10秒。

repl-ping-slave-period 10

復制連接超時時間。master和slave都有超時時間的設(shè)置。master檢測到slave上次發(fā)送的時間超過repl-timeout,即認為slave離線,清除該slave信息。slave檢測到上次和master交互的時間超過repl-timeout,則認為master離線。需要注意的是repl-timeout需要設(shè)置一個比repl-ping-slave-period更大的值,不然會經(jīng)常檢測到超時。

repl-timeout 60

是否禁止復制tcp鏈接的tcp nodelay參數(shù),可傳遞yes或者no。默認是no,即使用tcp nodelay。如果master設(shè)置了yes來禁止tcp nodelay設(shè)置,在把數(shù)據(jù)復制給slave的時候,會減少包的數(shù)量和更小的網(wǎng)絡帶寬。但是這也可能帶來數(shù)據(jù)的延遲。默認我們推薦更小的延遲,但是在數(shù)據(jù)量傳輸很大的場景下,建議選擇yes。

repl-disable-tcp-nodelay no

復制緩沖區(qū)大小,這是一個環(huán)形復制緩沖區(qū),用來保存最新復制的命令。這樣在slave離線的時候,不需要完全復制master的數(shù)據(jù),如果可以執(zhí)行部分同步,只需要把緩沖區(qū)的部分數(shù)據(jù)復制給slave,就能恢復正常復制狀態(tài)。緩沖區(qū)的大小越大,slave離線的時間可以更長,復制緩沖區(qū)只有在有slave連接的時候才分配內(nèi)存。沒有slave的一段時間,內(nèi)存會被釋放出來,默認1m。

repl-backlog-size 5mb

master沒有slave一段時間會釋放復制緩沖區(qū)的內(nèi)存,repl-backlog-ttl用來設(shè)置該時間長度。單位為秒。

repl-backlog-ttl 3600

當master不可用,Sentinel會根據(jù)slave的優(yōu)先級選舉一個master。最低的優(yōu)先級的slave,當選master。而配置成0,永遠不會被選舉。

slave-priority 100

redis提供了可以讓master停止寫入的方式,如果配置了min-slaves-to-write,健康的slave的個數(shù)小于N,mater就禁止寫入。master最少得有多少個健康的slave存活才能執(zhí)行寫命令。這個配置雖然不能保證N個slave都一定能接收到master的寫操作,但是能避免沒有足夠健康的slave的時候,master不能寫入來避免數(shù)據(jù)丟失。設(shè)置為0是關(guān)閉該功能。

min-slaves-to-write 3

延遲小于min-slaves-max-lag秒的slave才認為是健康的slave。

min-slaves-max-lag 10

設(shè)置1或另一個設(shè)置為0禁用這個特性。

Setting one or the other to 0 disables the feature.

By default min-slaves-to-write is set to 0 (feature disabled) and

min-slaves-max-lag is set to 10.

################################## SECURITY ###################################

requirepass配置可以讓用戶使用AUTH命令來認證密碼,才能使用其他命令。這讓redis可以使用在不受信任的網(wǎng)絡中。為了保持向后的兼容性,可以注釋該命令,因為大部分用戶也不需要認證。使用requirepass的時候需要注意,因為redis太快了,每秒可以認證15w次密碼,簡單的密碼很容易被攻破,所以最好使用一個更復雜的密碼。

requirepass foobared

把危險的命令給修改成其他名稱。比如CONFIG命令可以重命名為一個很難被猜到的命令,這樣用戶不能使用,而內(nèi)部工具還能接著使用。

rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52

設(shè)置成一個空的值,可以禁止一個命令

rename-command CONFIG ""

################################### LIMITS ####################################

設(shè)置能連上redis的最大客戶端連接數(shù)量。默認是10000個客戶端連接。由于redis不區(qū)分連接是客戶端連接還是內(nèi)部打開文件或者和slave連接等,所以maxclients最小建議設(shè)置到32。如果超過了maxclients,redis會給新的連接發(fā)送’max number of clients reached’,并關(guān)閉連接。

maxclients 10000

redis配置的最大內(nèi)存容量。當內(nèi)存滿了,需要配合maxmemory-policy策略進行處理。注意slave的輸出緩沖區(qū)是不計算在maxmemory內(nèi)的。所以為了防止主機內(nèi)存使用完,建議設(shè)置的maxmemory需要更小一些。

maxmemory <bytes>

內(nèi)存容量超過maxmemory后的處理策略。

volatile-lru:利用LRU算法移除設(shè)置過過期時間的key。

volatile-random:隨機移除設(shè)置過過期時間的key。

volatile-ttl:移除即將過期的key,根據(jù)最近過期時間來刪除(輔以TTL)

allkeys-lru:利用LRU算法移除任何key。

allkeys-random:隨機移除任何key。

noeviction:不移除任何key,只是返回一個寫錯誤。

推薦一個Java工程師學習交流群:795632998,群內(nèi)有分布式架構(gòu)、高性能、高并發(fā)、性能優(yōu)化、Spring boot、Redis、ActiveMQ、Nginx、Netty、Jvm等視頻資料提供學習參考

上面的這些驅(qū)逐策略,如果redis沒有合適的key驅(qū)逐,對于寫命令,還是會返回錯誤。redis將不再接收寫請求,只接收get請求。寫命令包括:set setnx setex append incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby getset mset msetnx exec sort。

maxmemory-policy noeviction

lru檢測的樣本數(shù)。使用lru或者ttl淘汰算法,從需要淘汰的列表中隨機選擇sample個key,選出閑置時間最長的key移除。

maxmemory-samples 5

############################## APPEND ONLY MODE ###############################

默認redis使用的是rdb方式持久化,這種方式在許多應用中已經(jīng)足夠用了。但是redis如果中途宕機,會導致可能有幾分鐘的數(shù)據(jù)丟失,根據(jù)save來策略進行持久化,Append Only File是另一種持久化方式,可以提供更好的持久化特性。Redis會把每次寫入的數(shù)據(jù)在接收后都寫入 appendonly.aof 文件,每次啟動時Redis都會先把這個文件的數(shù)據(jù)讀入內(nèi)存里,先忽略RDB文件。

appendonly no

aof文件名

appendfilename "appendonly.aof"

aof持久化策略的配置

no表示不執(zhí)行fsync,由操作系統(tǒng)保證數(shù)據(jù)同步到磁盤,速度最快。

always表示每次寫入都執(zhí)行fsync,以保證數(shù)據(jù)同步到磁盤。

everysec表示每秒執(zhí)行一次fsync,可能會導致丟失這1s數(shù)據(jù)。

appendfsync everysec

在aof重寫或者寫入rdb文件的時候,會執(zhí)行大量IO,此時對于everysec和always的aof模式來說,執(zhí)行fsync會造成阻塞過長時間,no-appendfsync-on-rewrite字段設(shè)置為默認設(shè)置為no。如果對延遲要求很高的應用,這個字段可以設(shè)置為yes,否則還是設(shè)置為no,這樣對持久化特性來說這是更安全的選擇。設(shè)置為yes表示rewrite期間對新寫操作不fsync,暫時存在內(nèi)存中,等rewrite完成后再寫入,默認為no,建議yes。Linux的默認fsync策略是30秒??赡軄G失30秒數(shù)據(jù)。

no-appendfsync-on-rewrite no

aof自動重寫配置。當目前aof文件大小超過上一次重寫的aof文件大小的百分之多少進行重寫,即當aof文件增長到一定大小的時候Redis能夠調(diào)用bgrewriteaof對日志文件進行重寫。當前AOF文件大小是上次日志重寫得到AOF文件大小的二倍(設(shè)置為100)時,自動啟動新的日志重寫過程。

auto-aof-rewrite-percentage 100

設(shè)置允許重寫的最小aof文件大小,避免了達到約定百分比但尺寸仍然很小的情況還要重寫

auto-aof-rewrite-min-size 64mb

aof文件可能在尾部是不完整的,當redis啟動的時候,aof文件的數(shù)據(jù)被載入內(nèi)存。重啟可能發(fā)生在redis所在的主機操作系統(tǒng)宕機后,尤其在ext4文件系統(tǒng)沒有加上data=ordered選項(redis宕機或者異常終止不會造成尾部不完整現(xiàn)象。)出現(xiàn)這種現(xiàn)象,可以選擇讓redis退出,或者導入盡可能多的數(shù)據(jù)。如果選擇的是yes,當截斷的aof文件被導入的時候,會自動發(fā)布一個log給客戶端然后load。如果是no,用戶必須手動redis-check-aof修復AOF文件才可以。

aof-load-truncated yes

################################ LUA SCRIPTING ###############################

如果達到最大時間限制(毫秒),redis會記個log,然后返回error。當一個腳本超過了最大時限。只有SCRIPT KILL和SHUTDOWN NOSAVE可以用。第一個可以殺沒有調(diào)write命令的東西。要是已經(jīng)調(diào)用了write,只能用第二個命令殺。

lua-time-limit 5000

################################ REDIS CLUSTER ###############################

集群開關(guān),默認是不開啟集群模式。

cluster-enabled yes

集群配置文件的名稱,每個節(jié)點都有一個集群相關(guān)的配置文件,持久化保存集群的信息。這個文件并不需要手動配置,這個配置文件有Redis生成并更新,每個Redis集群節(jié)點需要一個單獨的配置文件,請確保與實例運行的系統(tǒng)中配置文件名稱不沖突

cluster-config-file nodes-6379.conf

節(jié)點互連超時的閥值。集群節(jié)點超時毫秒數(shù)

cluster-node-timeout 15000

在進行故障轉(zhuǎn)移的時候,全部slave都會請求申請為master,但是有些slave可能與master斷開連接一段時間了,導致數(shù)據(jù)過于陳舊,這樣的slave不應該被提升為master。該參數(shù)就是用來判斷slave節(jié)點與master斷線的時間是否過長。判斷方法是:

比較slave斷開連接的時間和(node-timeout * slave-validity-factor) + repl-ping-slave-period

如果節(jié)點超時時間為三十秒, 并且slave-validity-factor為10,假設(shè)默認的repl-ping-slave-period是10秒,即如果超過310秒slave將不會嘗試進行故障轉(zhuǎn)移

cluster-slave-validity-factor 10

master的slave數(shù)量大于該值,slave才能遷移到其他孤立master上,如這個參數(shù)若被設(shè)為2,那么只有當一個主節(jié)點擁有2 個可工作的從節(jié)點時,它的一個從節(jié)點會嘗試遷移。

cluster-migration-barrier 1

默認情況下,集群全部的slot有節(jié)點負責,集群狀態(tài)才為ok,才能提供服務。設(shè)置為no,可以在slot沒有全部分配的時候提供服務。不建議打開該配置,這樣會造成分區(qū)的時候,小分區(qū)的master一直在接受寫請求,而造成很長時間數(shù)據(jù)不一致。

cluster-require-full-coverage yes

################################## SLOW LOG ###################################

slog log是用來記錄redis運行中執(zhí)行比較慢的命令耗時。當命令的執(zhí)行超過了指定時間,就記錄在slow log中,slog log保存在內(nèi)存中,所以沒有IO操作。

執(zhí)行時間比slowlog-log-slower-than大的請求記錄到slowlog里面,單位是微秒,所以1000000就是1秒。注意,負數(shù)時間會禁用慢查詢?nèi)罩?,?則會強制記錄所有命令。

slowlog-log-slower-than 10000

慢查詢?nèi)罩鹃L度。當一個新的命令被寫進日志的時候,最老的那個記錄會被刪掉。這個長度沒有限制。只要有足夠的內(nèi)存就行。你可以通過 SLOWLOG RESET 來釋放內(nèi)存。

slowlog-max-len 128

################################ LATENCY MONITOR ##############################

延遲監(jiān)控功能是用來監(jiān)控redis中執(zhí)行比較緩慢的一些操作,用LATENCY打印redis實例在跑命令時的耗時圖表。只記錄大于等于下邊設(shè)置的值的操作。0的話,就是關(guān)閉監(jiān)視。默認延遲監(jiān)控功能是關(guān)閉的,如果你需要打開,也可以通過CONFIG SET命令動態(tài)設(shè)置。

latency-monitor-threshold 0

############################# EVENT NOTIFICATION ##############################

鍵空間通知使得客戶端可以通過訂閱頻道或模式,來接收那些以某種方式改動了 Redis 數(shù)據(jù)集的事件。因為開啟鍵空間通知功能需要消耗一些 CPU ,所以在默認配置下,該功能處于關(guān)閉狀態(tài)。

notify-keyspace-events 的參數(shù)可以是以下字符的任意組合,它指定了服務器該發(fā)送哪些類型的通知:

K 鍵空間通知,所有通知以 keyspace@ 為前綴

E 鍵事件通知,所有通知以 keyevent@ 為前綴

g DEL 、 EXPIRE 、 RENAME 等類型無關(guān)的通用命令的通知

$ 字符串命令的通知

l 列表命令的通知

s 集合命令的通知

h 哈希命令的通知

z 有序集合命令的通知

x 過期事件:每當有過期鍵被刪除時發(fā)送

e 驅(qū)逐(evict)事件:每當有鍵因為 maxmemory 政策而被刪除時發(fā)送

A 參數(shù) g$lshzxe 的別名

輸入的參數(shù)中至少要有一個 K 或者 E,否則的話,不管其余的參數(shù)是什么,都不會有任何 通知被分發(fā)。詳細使用可以參考http://redis.io/topics/notifications

notify-keyspace-events ""

############################### ADVANCED CONFIG ###############################

數(shù)據(jù)量小于等于hash-max-ziplist-entries的用ziplist,大于hash-max-ziplist-entries用hash

hash-max-ziplist-entries 512

value大小小于等于hash-max-ziplist-value的用ziplist,大于hash-max-ziplist-value用hash。

hash-max-ziplist-value 64

數(shù)據(jù)量小于等于list-max-ziplist-entries用ziplist,大于list-max-ziplist-entries用list。

list-max-ziplist-entries 512

value大小小于等于list-max-ziplist-value的用ziplist,大于list-max-ziplist-value用list。

list-max-ziplist-value 64

數(shù)據(jù)量小于等于set-max-intset-entries用iniset,大于set-max-intset-entries用set。

set-max-intset-entries 512

數(shù)據(jù)量小于等于zset-max-ziplist-entries用ziplist,大于zset-max-ziplist-entries用zset。

zset-max-ziplist-entries 128

value大小小于等于zset-max-ziplist-value用ziplist,大于zset-max-ziplist-value用zset。

zset-max-ziplist-value 64

value大小小于等于hll-sparse-max-bytes使用稀疏數(shù)據(jù)結(jié)構(gòu)(sparse),大于hll-sparse-max-bytes使用稠密的數(shù)據(jù)結(jié)構(gòu)(dense)。一個比16000大的value是幾乎沒用的,建議的value大概為3000。如果對CPU要求不高,對空間要求較高的,建議設(shè)置到10000左右。

hll-sparse-max-bytes 3000

Redis將在每100毫秒時使用1毫秒的CPU時間來對redis的hash表進行重新hash,可以降低內(nèi)存的使用。當你的使用場景中,有非常嚴格的實時性需要,不能夠接受Redis時不時的對請求有2毫秒的延遲的話,把這項配置為no。如果沒有這么嚴格的實時性要求,可以設(shè)置為yes,以便能夠盡可能快的釋放內(nèi)存。

activerehashing yes

對客戶端輸出緩沖進行限制可以強迫那些不從服務器讀取數(shù)據(jù)的客戶端斷開連接,用來強制關(guān)閉傳輸緩慢的客戶端。

對于normal client,第一個0表示取消hard limit,第二個0和第三個0表示取消soft limit,normal client默認取消限制,因為如果沒有尋問,他們是不會接收數(shù)據(jù)的。

client-output-buffer-limit normal 0 0 0

對于slave client和MONITER client,如果client-output-buffer一旦超過256mb,又或者超過64mb持續(xù)60秒,那么服務器就會立即斷開客戶端連接。

client-output-buffer-limit slave 256mb 64mb 60

對于pubsub client,如果client-output-buffer一旦超過32mb,又或者超過8mb持續(xù)60秒,那么服務器就會立即斷開客戶端連接。

client-output-buffer-limit pubsub 32mb 8mb 60

redis執(zhí)行任務的頻率為1s除以hz。

hz 10

在aof重寫的時候,如果打開了aof-rewrite-incremental-fsync開關(guān),系統(tǒng)會每32MB執(zhí)行一次fsync。這對于把文件寫入磁盤是有幫助的,可以避免過大的延遲峰值。

aof-rewrite-incremental-fsync yes

持久化

前文說過,redis是內(nèi)存數(shù)據(jù)庫,為了保證數(shù)據(jù)在斷電后不會丟失,需要將它持久化到硬盤上。redis持久化分為兩種。

RDB持久化

RDB持久化是指在指定的時間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤。

也是默認的持久化方式,這種方式是就是將內(nèi)存中數(shù)據(jù)以快照的方式寫入到二進制文件中,默認的文件名為dump.rdb。

可以通過配置設(shè)置自動做快照持久化的方式。我們可以配置redis在n秒內(nèi)如果超過m個key被修改就自動做快照,下面是默認的快照保存配置

save 900 1 #900秒內(nèi)如果超過1個key被修改,則發(fā)起快照保存

save 300 10 #300秒內(nèi)容如超過10個key被修改,則發(fā)起快照保存

save 60 10000

RDB保存過程

redis調(diào)用fork,現(xiàn)在有了子進程和父進程

父進程繼續(xù)處理client請求,子進程負責將內(nèi)存內(nèi)容寫入到臨時文件。由于os的寫時復制機制(copy on write)父子進程會共享相同的物理頁面,當父進程處理寫請求時os會為父進程要修改的頁面創(chuàng)建副本,而不是寫共享的頁面。所以子進程的地址空間內(nèi)的數(shù) 據(jù)是fork時刻整個數(shù)據(jù)庫的一個快照。

當子進程將快照寫入臨時文件完畢后,用臨時文件替換原來的快照文件,然后子進程退出。

推薦一個Java工程師學習交流群:795632998,群內(nèi)有分布式架構(gòu)、高性能、高并發(fā)、性能優(yōu)化、Spring boot、Redis、ActiveMQ、Nginx、Netty、Jvm等視頻資料提供學習參考

如何觸發(fā)快照

client 也可以使用save或者bgsave命令通知redis做一次快照持久化。save操作是在主線程中保存快照的,由于redis是用一個主線程來處理所有 client的請求,這種方式會阻塞所有client請求。所以不推薦使用。

另一點需要注意的是,每次快照持久化都是將內(nèi)存數(shù)據(jù)完整寫入到磁盤一次,并不 是增量的只同步臟數(shù)據(jù)。如果數(shù)據(jù)量大的話,而且寫操作比較多,必然會引起大量的磁盤io操作,可能會嚴重影響性能。

優(yōu)勢

一旦采用該方式,那么你的整個Redis數(shù)據(jù)庫將只包含一個文件,這樣非常方便進行備份。

方便備份,我們可以很容易的將一個一個RDB文件移動到其他的存儲介質(zhì)上

RDB 在恢復大數(shù)據(jù)集時的速度比 AOF 的恢復速度要快。

RDB 可以最大化 Redis 的性能:父進程在保存 RDB 文件時唯一要做的就是 fork 出一個子進程,然后這個子進程就會處理接下來的所有保存工作,父進程無須執(zhí)行任何磁盤 I/O 操作。

劣勢

如果你需要盡量避免在服務器故障時丟失數(shù)據(jù),那么 RDB 不適合你。 雖然 Redis 允許你設(shè)置不同的保存點(save point)來控制保存 RDB 文件的頻率, 但是, 因為RDB 文件需要保存整個數(shù)據(jù)集的狀態(tài), 所以它并不是一個輕松的操作。 因此你可能會至少 5 分鐘才保存一次 RDB 文件。 在這種情況下,一旦發(fā)生故障停機, 你就可能會丟失好幾分鐘的數(shù)據(jù)。(丟失數(shù)據(jù))

每次保存 RDB 的時候,Redis 都要 fork() 出一個子進程,并由子進程來進行實際的持久化工作。 在數(shù)據(jù)集比較龐大時, fork() 可能會非常耗時,造成服務器在某某毫秒內(nèi)停止處理客戶端; 如果數(shù)據(jù)集非常巨大,并且 CPU 時間非常緊張的話,那么這種停止時間甚至可能會長達整整一秒。 雖然 AOF 重寫也需要進行 fork() ,但無論 AOF 重寫的執(zhí)行間隔有多長,數(shù)據(jù)的耐久性都不會有任何損失。(耗時)

rdb總結(jié)

image

AOF持久化

AOF保存過程

redis會將每一個收到的寫命令都通過write函數(shù)追加到文件中(默認是 appendonly.aof)。

當redis重啟時會通過重新執(zhí)行文件中保存的寫命令來在內(nèi)存中重建整個數(shù)據(jù)庫的內(nèi)容。當然由于os會在內(nèi)核中緩存 write做的修改,所以可能不是立即寫到磁盤上。這樣aof方式的持久化也還是有可能會丟失部分修改。不過我們可以通過配置文件告訴redis我們想要 通過fsync函數(shù)強制os寫入到磁盤的時機。有三種方式如下(默認是:每秒fsync一次)

appendonly yes //啟用aof持久化方式

appendfsync always //每次收到寫命令就立即強制寫入磁盤,最慢的,但是保證完全的持久化,不推薦使用

appendfsync everysec //每秒鐘強制寫入磁盤一次,在性能和持久化方面做了很好的折中,推薦

appendfsync no //完全依賴os,性能最好,持久化沒保證

aof 的方式也同時帶來了另一個問題。持久化文件會變的越來越大。例如我們調(diào)用incr test命令100次,文件中必須保存全部的100條命令,其實有99條都是多余的。因為要恢復數(shù)據(jù)庫的狀態(tài)其實文件中保存一條set test 100就夠了。

為了壓縮aof的持久化文件。redis提供了bgrewriteaof命令。收到此命令redis將使用與快照類似的方式將內(nèi)存中的數(shù)據(jù)以命令的方式保存到臨時文件中,最后替換原來的文件。具體過程如下

redis調(diào)用fork,現(xiàn)在有父子兩個進程子進程根據(jù)內(nèi)存中的數(shù)據(jù)庫快照,往臨時文件中寫入重建數(shù)據(jù)庫狀態(tài)的命令父進程繼續(xù)處理client請求,除了把寫命令寫入到原來的aof文件中。同時把收到的寫命令緩存起來。這樣就能保證如果子進程重寫失敗的話并不會出問題。當子進程把快照內(nèi)容寫入已命令方式寫到臨時文件中后,子進程發(fā)信號通知父進程。然后父進程把緩存的寫命令也寫入到臨時文件?,F(xiàn)在父進程可以使用臨時文件替換老的aof文件,并重命名,后面收到的寫命令也開始往新的aof文件中追加。 需要注意到是重寫aof文件的操作,并沒有讀取舊的aof文件,而是將整個內(nèi)存中的數(shù)據(jù)庫內(nèi)容用命令的方式重寫了一個新的aof文件,這點和快照有點類似。

優(yōu)勢

耐久

不斷電

易讀

劣勢

數(shù)據(jù)量大

抉擇

一般來說,應該同時使用兩種持久化功能。 如果你非常關(guān)心你的數(shù)據(jù), 但仍然可以承受數(shù)分鐘以內(nèi)的數(shù)據(jù)丟失, 那么你可以只使用 RDB 持久化。

redis事務

是什么

可以一次執(zhí)行多個命令,本質(zhì)是一組命令的集合。一個事務中的,所有命令都會序列化,按順序地串行化執(zhí)行而不會被其它命令插入,不許加塞

能干嘛

一個隊列中,一次性、順序性、排他性的執(zhí)行一系列命令

3個階段

開啟:以MULTI開始一個事務

入隊:將多個命令入隊到事務中,接到這些命令并不會立即執(zhí)行,而是放到等待執(zhí)行的事務隊列里面

執(zhí)行:由EXEC命令觸發(fā)事務

3特性

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

沒有隔離級別的概念:隊列中的命令沒有提交之前都不會實際的被執(zhí)行,因為事務提交前任何指令都不會被實際執(zhí)行,

也就不存在”事務內(nèi)的查詢要看到事務里的更新,在事務外查詢不能看到”這個讓人萬分頭痛的問題

不保證原子性:redis同一個事務中如果有一條命令執(zhí)行失敗,其后的命令仍然會被執(zhí)行,沒有回滾

關(guān)于redis事務

首先,讓我們來看一個例子:

image

這個操作采用了事務模式,并在第6個指令進入隊列的時候就已經(jīng)出錯,所以導致整個事務的命令都不會被執(zhí)行

接下來,再看一個操作

image

實際上這個問題很簡單,這個incr name錯誤指令在入隊的時候沒有出錯,卻在執(zhí)行的時候出錯了,redis默認跳過這個命令執(zhí)行后續(xù)命令

所以,這就是為什么我在開頭說redis的事務只是部分事務

redis的鎖機制

redis的鎖CAS類似于樂觀鎖,使用方式為用watch關(guān)鍵字監(jiān)視一個(或多個)數(shù)據(jù),例如:

假設(shè)現(xiàn)在兩個客戶端A,B

1.客戶端A監(jiān)控count,并修改count

image

2.待A執(zhí)行完畢后,客戶端B修改count

image

3.待B執(zhí)行完畢后,A提交事務

image

可以看到,顯示了(nil),即這次事務失敗,count變?yōu)?0

事務總結(jié)

單獨的隔離操作:事務中的所有命令會被序列化、按順序執(zhí)行,在執(zhí)行的過程中不會被其他客戶端發(fā)送來的命令打斷

沒有隔離級別的概念:隊列中的命令在事務沒有被提交之前不會被實際執(zhí)行

不保證原子性:redis中的一個事務中如果存在命令執(zhí)行失敗,那么其他命令依然會被執(zhí)行,沒有回滾機制

消息發(fā)布訂閱

Redis提供了發(fā)布訂閱功能,可用于消息傳輸,進程間的一種通信方式,Redis的發(fā)布訂閱機制包括三個部分,發(fā)布者,訂閱者和Channel。

發(fā)布者和訂閱者都是Redis客戶端,Channel則為Redis服務器端,發(fā)布者將消息發(fā)送到某個的頻道,訂閱了這個頻道的訂閱者就能接收到這條消息。

當然,一般很少人用redis的發(fā)布訂閱,取而代之的是消息隊列MQ(ActiveMQ),但還是有必要了解redis有該功能的。

主從復制

為什么有它

讀寫分離:和關(guān)系型數(shù)據(jù)庫一樣,雖然redis作為內(nèi)存數(shù)據(jù)庫,他同樣面臨讀寫壓力,通過設(shè)置主從redis可以實現(xiàn)讀寫分離減輕壓力

容災恢復:假設(shè)某位程序員不小心把庫房燒了??,主庫沒了,如果我們設(shè)計了從庫,這時我們將完全不用擔心數(shù)據(jù)沒了的問題,因為從庫和主庫有同樣的數(shù)據(jù)

是什么

行話:也就是我們所說的主從復制,主機數(shù)據(jù)更新后根據(jù)配置和策略,自動同步到備機的master/slaver機制,Master以寫為主,Slave以讀為主,一個從服務器只能有一個主服務器,并且不支持主主復制。

復制原理

全量同步

Redis全量復制一般發(fā)生在Slave初始化階段,這時Slave需要將Master上的所有數(shù)據(jù)都復制一份。具體步驟如下:

1.從服務器連接主服務器,發(fā)送SYNC命令;

2.主服務器接收到SYNC命名后,開始執(zhí)行BGSAVE命令生成RDB文件并使用緩沖區(qū)記錄此后執(zhí)行的所有寫命令;

3.主服務器BGSAVE執(zhí)行完后,向所有從服務器發(fā)送快照文件,并在發(fā)送期間繼續(xù)記錄被執(zhí)行的寫命令;

4.從服務器收到快照文件后丟棄所有舊數(shù)據(jù),載入收到的快照;

5.主服務器快照發(fā)送完畢后開始向從服務器發(fā)送緩沖區(qū)中的寫命令;

6.從服務器完成對快照的載入,開始接收命令請求,并執(zhí)行來自主服務器緩沖區(qū)的寫命令;

增量同步

Redis增量復制是指Slave初始化后開始正常工作時主服務器發(fā)生的寫操作同步到從服務器的過程。 增量復制的過程主要是主服務器每執(zhí)行一個寫命令就會向從服務器發(fā)送相同的寫命令,從服務器接收并執(zhí)行收到的寫命令。

現(xiàn)在,出現(xiàn)了幾個問題:

從機是否可以寫?

如果從庫死了之后活了他還是從庫嗎?

如果主庫死了之后它的從庫該怎么辦?(普通模式和哨兵模式)主庫活了之后還是主庫嗎?

為了減少閱讀量,這里就不實驗論證了,客官們可以自行嘗試

先回答第一個問題:

從機不可寫

先回答第二個問題:

在Redis2.8版本之前,從庫死后復活會發(fā)送sync請求和主機全量同步,所以死后復活還是從庫,但是,當多個從庫同時復活的話會導致主機IO劇增而宕機

2.8版本之后,主服務器只需要將斷線期間執(zhí)行的命令發(fā)給從服務器即可

第三個問題:

主機死后,從機待命。并且主庫回來后,他將仍然是主庫

哨兵模式:反客為主,即哨兵模式在后臺監(jiān)控,主庫死后根據(jù)投票將它的從庫設(shè)置為新的主庫

哨兵模式的出現(xiàn)正是為了解決主庫死后無人領(lǐng)導的狀態(tài)。

那么有了哨兵模式后,原來死掉的主庫回來后會發(fā)生什么呢?答案是原來的主庫回來后就變?yōu)榱藦膸臁?/p>

最后一點點

對于一個slave從庫他同樣可以接收其他從庫的連接請求,即該slave作為下一個的master

Redis適用場景

數(shù)據(jù)高并發(fā)讀寫

海量數(shù)據(jù)讀寫

擴展性要求高的數(shù)據(jù)

例子:

1.保存熱點信息 2.排行榜 3.計數(shù) 4.單點登陸(解決session共享問題) 5.等等。。。

歡迎工作一到八年的Java工程師朋友們加入Java工程師學習交流群:860113481

群內(nèi)提供免費的Java架構(gòu)學習資料(里面有高可用、高并發(fā)、高性能及分布式、Jvm性能調(diào)優(yōu)、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構(gòu)資料)合理利用自己每一分每一秒的時間來學習提升自己,趁年輕,使勁拼,給未來的自己一個交代!

作者:老男孩_Misaya
鏈接:http://www.itdecent.cn/p/d05a2774af1e
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容