NOsql
泛指非關(guān)系型數(shù)據(jù)庫,為了克服超大規(guī)模的高并發(fā)的問題,NoSQL在當今大數(shù)據(jù)環(huán)境下發(fā)展的十分迅速,Redis是發(fā)展最快的。
方便擴展(數(shù)據(jù)之間沒有關(guān)系)
大數(shù)據(jù)量高性能(Redis一秒寫8萬次,讀取11萬次,NoSQL的緩存記錄級,是一種細粒度的緩存,性能會比較高)
數(shù)據(jù)類型是多樣的(不需要事先設計數(shù)據(jù)庫)
發(fā)展歷程
單機MySQL->緩存+Mysql+垂直拆分(讀寫分離)->分庫分表+水平拆分+服務器集群
四大分類
K-V鍵值對 -Redis
文檔型數(shù)據(jù)庫
MongoDB是一個基于分布式文件存儲的數(shù)據(jù)庫,C++編寫,主要用來處理大量的文檔!
MongoDB是一個介于關(guān)系型數(shù)據(jù)庫和非關(guān)系型數(shù)據(jù)庫中間的產(chǎn)品
MongoDB是非關(guān)系型數(shù)據(jù)庫中功能最豐富的
列存儲數(shù)據(jù)庫 -HBase? ? ? ? ? ? ? ? ? ? ? ? ? ? ? -分布式文件系統(tǒng)
圖關(guān)系數(shù)據(jù)庫 -Neo4J? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? -InfoGird
Redis入門
簡介:一個開源的使用ANSI C語言編寫,支持網(wǎng)絡,可基于內(nèi)存衣可持久化的日志型,K-V數(shù)據(jù)庫,并提供多種語言的API。免費和開源!
windows安裝
下載安裝包
通過CMD啟動,cd到redis的安裝目錄下
運行命令 redis-server redis.windows.conf
Linux安裝
下載安裝包,放到/opt目錄下 ,解壓
進入解壓后的文件,找到redis.conf
yum install gcc-c++ ? ?
make ? //下載環(huán)境
make install
redis的默認安裝路徑? /usr/local/bin
復制配置文件到指定目錄

redis默認不是后臺啟動的,修改配置文件,使redis后臺啟動

啟動redis服務

查看redis進程是否開啟
Redis性能測試
redis -benchmark

Redis基礎(chǔ)
redis有16個數(shù)據(jù)庫,默認使用第0個。
Redis是單線程的,基于內(nèi)存操作,CPU不是Redis的性能瓶頸,Redis的瓶頸是根據(jù)機器的內(nèi)存和網(wǎng)絡帶寬,既然可以使用單線程來實現(xiàn),就使用單線程來實現(xiàn)
Redis是C語言寫的,每秒100000+的QPS,完全不比同樣是使用key-value的Memecache(一套分布式的快取系統(tǒng))差.
Redis為什么單線程還這么快?
誤區(qū)1:高性能的服務器一定是多線程的?
誤區(qū)2:多線程(CPU上下文會切換)一定比單線程效率高!
核心:redis將所有的數(shù)據(jù)全部放在內(nèi)存中,所以使用單線程去操作效率最高,多線程(CPU上下文會切換:耗時的操作),對于內(nèi)存系統(tǒng)來說,如果沒有上下文切換效率就是最高的!多次讀寫都是在一個CPU上的,這就是最佳方案。
五大數(shù)據(jù)類型
Redis-Key
setkey value#set key
keys *#查看所有key
exists key#判斷當前key是否存在
move key database#移除當前key
expire key seconds#設置key的過期時間,單位秒
tll key#查看當前key的剩余時間
type key#查看當前key的類型
append key “”#追加/如key不存在就相當于set
strlen key#獲取字符創(chuàng)的長度
################################################
#步長 i+=
#i++
setviews0#初始瀏覽量為0
incr views#自增1
decr views#自減1
incrby views10#可以設置步長,指定增量
###################################################
#字符串范圍? range
GETRANGE key03#截取字符串[0,3]
GETRANGE key0-1#獲取全部的字符串
#替換
SETRANGE key1xx#替換指定位置開始的字符串
#######################################################
#setex (set with expire) #設置過期時間
#setnx (set if not exist) #不存在 再設置 (在分布式鎖種會常常使用!)
############################################################
mset#同時設置多個值
mget#同時獲取多個值
#對象
setuser:1 {name:wir,age:3}#設置一個user:1對象值為json字符來保存一個對象
#######################################################################
getset#先get再set
#如果不存在值,怎創(chuàng)建返回nil;如果存在值,獲取原來的值并設置新值
String
String類似的使用場景:value除了是字符串還可以是數(shù)字
計數(shù)器
統(tǒng)計多單位的數(shù)量
List(命令l開頭)
基本的數(shù)據(jù)類型,列表;可以用list實現(xiàn)棧,隊列,阻塞隊列。
LPUSH list one#將一個值(多個),插入到列表的頭部(左)
RPUSH list right#將一個值(多個),插入到列表的頭部(右)
LRANGE list0-1#查詢list
#####################################################
LPOP
RPOP
LPOP list#移除list的第一個元素
RPOP list#移除list的最后一個元素
#########################################################
Llen? list#返回list的長度
###############################
lrem list1one#移除 list集合中指定個數(shù)的value
ltrim list12#通過下標截取指定的長度
##################################################
rpoplpush#移除列表的最后一個元素,將它移動到新的列表中!
rpoplpush list1 list2
###################################################
小結(jié)
list實際上類似鏈表,left,right,before Node after 都可以插入值
如果key不存在,創(chuàng)建新的鏈表
如果key存在,新增內(nèi)容
如果移除了所有值,鏈表空,表示不存在
在兩邊插入或者改動值效率最高!中間元素,相對來說效率會低一點~
消息排隊!消息隊列(Lpush Rpop),棧(Lpush Lpop)
Set(集合)
##########################################################
sadd myset"hello"#set集合紅添加元素
SMEMBERS myser#查看指定set的所有值
SISMEMBER myset hello#判斷某一個值在集合中是否存在
########################################
srem myset hello#移除set集合中的指定元素
########################################
SRANDMEMBER myset /2#隨機拿出一個元素 /指定個數(shù)的元素
#################################
spop myset#隨機刪除key中的元素
#########################
smove key1 key2"xxx"#將xxx移動到key2 中
##############################
SDIFF k1 k2#查看k1 k2兩個集合中不同的元素
SINTER k1 k2#查看k1 k2兩個集合中相同的元素
SUNION k1 k2#查看k1 k2兩個集合中所有元素
Hash(哈希)
key -<key,value>(map)!這個value是一個map集合 ;可以做變更數(shù)據(jù),例如用戶信息
##############################################
hset key field1 value#set一個具體的 key-value
hmset key field1 value11 field2 value22#同時set多個具體的k-v
hmget key field1 field2#獲取多個字段
hgetall key#獲取全部數(shù)據(jù)
######################################################
hdel key field1#刪除hash指定的key
#####################################################
hlen key#獲取hash表的字段數(shù)量
#####################################
HEXISTS key field1#判斷hash中指定字段是否存在
############################################
hkeys key#獲取所有的key
hvalues key#獲取所有的value
Zset(有序集合)
三種特殊數(shù)據(jù)類型
Geospatial-地理空間
#geoadd
#規(guī)則:兩極無法直接添加,一般通過程序一次性導入
#參數(shù) key 值(緯度,經(jīng)度,名稱)
geoadd china:city116.40.39.90 beijing#添加坐標
#geopos
geopos china:city beijing#獲取指定的城市的經(jīng)度和緯度
#geodist
geodist china:china beijin shanghai km# 兩地距離? 單位:m,km,mi(英里),ft(英尺)
#georadius
georadius china:city110301000km withdist withcoord count1#以經(jīng)緯度為中心1000km為半徑查找 顯示到中間距離的位置 顯示他人的定位信息 篩選出指定的結(jié)果
#georadiusbymember
georadiusbymember china:city beijing1000km#找出位于指定元素周圍的其他元素
Hyperloglog
占用的內(nèi)存是固定的,2^64不同的元素基數(shù),只要12KB內(nèi)存。0.18%錯誤率!
PFadd key
PFCOUNT key#統(tǒng)計
Bitmaps-位存儲
bitmaps位圖,數(shù)據(jù)結(jié)構(gòu)!都是操作二進制位來進行記錄,就只有0和1兩個狀態(tài)!
事務
Redis事務本質(zhì):一組命令的集合!一個事務中的所有命令都會被序列化,在事務執(zhí)行過程中,會按照順序執(zhí)行!
一次性,順序性,排他性!執(zhí)行一些列的命令!
Redis事務沒有隔離級別的概念!(不會出現(xiàn)臟讀,幻讀,不可重復讀)
所有的命令在事務中,并沒有直接被執(zhí)行!只有發(fā)起執(zhí)行命令的時候才會執(zhí)行!Exec
Redis單條命令是保證原子性的,但是事務不保證原子性
redis事務
開啟事務(multi)
命令入隊()
執(zhí)行事務(exec)
正常執(zhí)行事務

放棄事務-discard#取消事務
編譯型異常(代碼有問題!命令有錯),事務中所有的命令都不會被執(zhí)行
運行時異常,如果事務隊列中存在語法錯誤,那么執(zhí)行命令的時候,其他命令是可以正常執(zhí)行的,錯誤命令會拋出異常
監(jiān)控! Watch
悲觀鎖:
悲觀,無論做什么都加鎖!效率低下
樂觀鎖:
樂觀,認為不會出問題,所以不加鎖!更新數(shù)據(jù)時去判斷在此期間是否有人修改數(shù)據(jù)。
獲取version
更新時比較version
Redis監(jiān)控測試
正常執(zhí)行成功!
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money #監(jiān)視money對象
OK
127.0.0.1:6379> multi #事務正常結(jié)束,數(shù)據(jù)期間沒有發(fā)生變動,這個時候就正常執(zhí)行成功
OK
127.0.0.1:6379(TX)> DECRBY money 20
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20
如果事務執(zhí)行失??!就先unwatch(解除監(jiān)視)然后再watch(再次監(jiān)視),最后對比監(jiān)視的值是否發(fā)生變化,如果沒有變化,那么可以成功,如果有變化就執(zhí)行失敗!繼續(xù)重復。
Jedis
Jedis是Redis官方推薦的Java連接開發(fā)工具!使用Java操作Redis中間件
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.5.1</version>
</dependency>
具體方法同redis命令
Spring Boot整合
SpringBoot2.x之后,原來使用的jedis被替換為lettuce
jedis:才用的直連,多個線程操作的話,是不安全的,如果想要避免不安全,需要使用jedis pool 連接池!
lettuce :采用netty,實例可以在多個線程中進行共享,可以減少線程數(shù)量
源碼分析:
@Bean
@ConditionalOnMissingBean(name="redisTemplate")//如果沒有配置Bean會生效,所以可以自己定義一個redisTemplate來替換
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
publicRedisTemplate<Object,Object>redisTemplate(RedisConnectionFactoryredisConnectionFactory) {
//默認的RedisTemplate沒有過多的設置,redis對象都是需要序列化的
//泛型都是object,類型,使用后需要強制類型轉(zhuǎn)換
RedisTemplate<Object,Object>template=newRedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
returntemplate;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)//String是redis中最常使用的類型,所以單獨提出來一個bean
publicStringRedisTemplatestringRedisTemplate(RedisConnectionFactoryredisConnectionFactory) {
StringRedisTemplatetemplate=newStringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
returntemplate;
}
Redis持久化
Redis是基于內(nèi)存的數(shù)據(jù)庫,如果不將內(nèi)存中的數(shù)據(jù)保存到磁盤,那么一旦服務器進程退出,服務器中的數(shù)據(jù)庫狀態(tài)也會消失,所以Redis提供了持久化功能!
RDB(默認RDB,一般情況下不需要修改配置)
在指定的時間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤,也就是快照。它恢復時是將快照文件直接讀到內(nèi)存里。
redis會單獨創(chuàng)建一個子進程來進行持久化,先將數(shù)據(jù)寫入一個臨時文件中,待持久化過程結(jié)束,在用臨時文件替換上次持久化好的文件。整個過程中,主進程是不進行任何IO操作的。這就確保了極高的性能。
如果需要進行大規(guī)模數(shù)據(jù)的恢復,且對于數(shù)據(jù)恢復的完整性不是非常敏感,那RDB方式要比AOF方式更加搞笑。
RDB的缺點是最后一個持久化后的數(shù)據(jù)可能丟失。
rdb保存的文件是dump.rdb,在配置文件中的快照進行配置
觸發(fā)機制
save的規(guī)則滿足的情況下,會自動觸發(fā)rdb規(guī)則
執(zhí)行flushall命令,也會觸發(fā)rdb規(guī)則!
退出redis,也會產(chǎn)生rdb文件
備份會自動生成一個dump.rdb
如何恢復rdb文件!
只需要將rdb文件放在我們的redis啟動目錄就可以,redis啟動時會自動檢查dump.rdb并恢復其中的數(shù)據(jù)
優(yōu)點
適合大規(guī)模的數(shù)據(jù)恢復!
對數(shù)據(jù)的完整性要求不高!
缺點
需要一定的時間間隔進行操作!如果redis宕機了,這個最后一次修改的數(shù)據(jù)就沒有了
fork進程的時候,會占用一定的內(nèi)存空間
AOF(Append Only File)
將所有命令都記錄下來,恢復的時候會把這個文件全部執(zhí)行一遍
以日志的形式來記錄每個寫操縱,將Redis執(zhí)行過的所有指令記錄下來(讀操作不記錄),只許追加文件但不可以改寫文件,redis啟動之初會讀取該文件重新構(gòu)建數(shù)據(jù),換言之,Redis重啟的話就根據(jù)日志文件的內(nèi)容將寫指令從前到后執(zhí)行一次以完成數(shù)據(jù)的恢復工作
Aof保存的文件是appendonly.aof文件
redis默認不開啟aof,需要手動修改配置文件!將appendonly改為yes才能開啟aof
如果aof文件有問題,無法重新啟動redis服務,需要用redis-check-aof --fix appendonly-aof
如果aof文件大于64m!fork一個新的進程來將文件進行重寫
優(yōu)點和缺點
優(yōu)點:
每一次修改都同步,文件的完整性更好
默認每秒同步一次,可能會丟失一秒的數(shù)據(jù)
若從不同步,效率最高!
缺點:
相對于數(shù)據(jù)文件來說,aof遠遠大于rdb,修復的速度也比rdb慢!
Aof運行的效率也要比rdb慢,所以redis默認的持久化方式是rdb!
擴展:
RDB持久化方式能夠在指定的時間間隔內(nèi)對數(shù)據(jù)進行快照存儲
AOF持久化方式記錄每次對服務器的寫操作,當服務器重啟的時候回重新執(zhí)行這些命令來恢復原始數(shù)據(jù),AOF命令以Redis協(xié)議追加保存每次寫的操作到文件末尾,Redis還能對aof文件進行后臺重寫,防止aof文件體積不至于過大。
只做緩存,不需要使用任何持久化
同時開啟兩種持久化方式
在這種情況下當redis重啟的時候會優(yōu)先載入aof文件來恢復原始數(shù)據(jù),因為在通常情況下aof文件保存的數(shù)據(jù)集要比RDB文件保存的數(shù)據(jù)集完整
RDB的數(shù)據(jù)不實時,同時使用兩者時服務器重啟也只會找AOF文件,不建議只使用AOF,因為RDB更適合用于數(shù)據(jù)備份(AOF在不斷變化不好備份),快速重啟,而且不會有AOF可能潛在的Bug,留著作為一個萬一的手段。
性能建議
因為RDB文件只用作備份用途,建議只在Slave(從盤)上持久化RDB文件,而且只要15分鐘備份一次即可,只保留 save 900 1(15分鐘至少修改一條就開啟備份)這個規(guī)則。
如果Enable AOF,好處是在最惡劣情況下也只會丟失不超過兩秒數(shù)據(jù),啟動腳本較簡單只load自己的AOF文件就可以了,代價一是帶來了持續(xù)的IO,二是AOF rewirte的最后將重寫過程中產(chǎn)生的新數(shù)據(jù)寫到新文件造成的阻塞幾乎是不可避免的。只要硬盤許可,應該盡量減少AOF重寫的頻率,AOF重寫的基礎(chǔ)大小默認值64M太小了,可以設置到5G以上,默認超過原大小100%重寫可以改到適當?shù)臄?shù)值。
如果不開啟AOF,僅靠Master-Slave(主從復制) Repllcation實現(xiàn)高可用性也可以,能減少很多IO操作,也減少了重寫時帶來的系統(tǒng)波動,代價是Master/Slave同時宕機(斷電),會丟失十幾分鐘的數(shù)據(jù),啟動腳本也要比較兩個Master/Slave中的RDB文件,載入較新的那個,微博就是這種架構(gòu)。
Redis發(fā)布訂閱
Redis發(fā)布訂閱(pub/sub)是一種消息通信模式:發(fā)送者(pub)發(fā)送消息,訂閱者(sub)接收消息。微信,微博,關(guān)注系統(tǒng)!
Redis客戶端可以訂閱任意數(shù)量的頻道。
訂閱/發(fā)布消息圖:

測試
訂閱端:
127.0.0.1:6379> SUBSCRIBE wirdeos#訂閱一個頻道
Reading messages... (press Ctrl-C to quit)
1)"subscribe"
2)"wirdeos"
3) (integer)1
#等待讀取推送的信息
1)"message"#消息
2)"wirdeos"#頻道
3)"1231341"#內(nèi)容
發(fā)送端:
127.0.0.1:6379> PUBLISH wirdeos 1231341 #發(fā)送者發(fā)送消息到頻道!
(integer) 1
原理
Redis是使用C實現(xiàn)的,通過分析Redis源碼里的pubsub.c文件,了解發(fā)布和訂閱機制的底層實現(xiàn),籍此加深對Redis的理解。
Redis通過PUBLISH,SUBSCRIBE和PSUBSCRIBE等命令實現(xiàn)發(fā)布和訂閱功能。
通過SUBSCRIBE命令訂閱某頻道后,redis-server里維護了一個字典,字典的鍵就是一個個channel,而字典的值則是一個鏈表,鏈表中保存了所有訂閱這個channel客戶端。SUBSCRIBE命令的關(guān)鍵,就是將客戶端添加到給定channel的訂閱鏈表中。
通過PUBLISH命令向訂閱者發(fā)送消息,redis-server會使用給定的頻道作為鍵,在它所維護的channel字典中查找記錄了訂閱這個頻道的所有客戶端鏈表,遍歷這個鏈表,將消息發(fā)布給所有訂閱者
Pub/Sub從字面理解就是發(fā)布(Publish)與訂閱(Subscribe),在Redis中可以設定對某一個key值進行消息發(fā)布及消息訂閱,當一個key值上進行了消息發(fā)布后,所有訂閱他的客戶端都會收到相應的消息。這一功能最明顯的用法就是用作實時消息系統(tǒng),比如普通的即使聊天,群聊等。
使用場景:
實時消息系統(tǒng)!
實時聊天!
訂閱關(guān)注系統(tǒng)!
Redis主從復制
主從復制,是指將一臺Redis服務器的數(shù)據(jù),復制到其他的Redis服務器。前者成為主節(jié)點(Master/leader),后者稱為從節(jié)點(slave/follower);數(shù)據(jù)的復制是單向的,只能由主節(jié)點到從節(jié)點。Master以寫為主,Slave以讀為主。
默認情況下,每臺Redis服務器都是主節(jié)點;且一個主節(jié)點可以有多個從節(jié)點(或沒有),但一個從節(jié)點只可以有一個主節(jié)點。
主從復制的作用主要包括:
數(shù)據(jù)冗余(重復數(shù)據(jù)):主從復制實現(xiàn)了數(shù)據(jù)的熱備份,是持久化之外的一種數(shù)據(jù)冗余方式。
故障恢復:當主節(jié)點出現(xiàn)問題時,可以由從節(jié)點提供服務,實現(xiàn)快速的故障恢復;實際上是一種服務的冗余
負載均衡:在主從復制的基礎(chǔ)上,配合讀寫分離,可以由主節(jié)點提供寫服務,由從節(jié)點提供讀服務(即寫數(shù)據(jù)時應用連接主節(jié)點,讀Redis數(shù)據(jù)應用連接從節(jié)點),分擔服務器負載;尤其是在寫少讀多的場景下,通過多個從節(jié)點分擔讀負載,可以大大提高Redis服務器的并發(fā)量。
高可用(集群)基石:除了上述作用以外,主從復制還是哨兵和集群能夠?qū)嵤┑幕A(chǔ),因此說主從復制時Redis高可用的基礎(chǔ)。
最少,一主二從
一般來說,要將redis運用于工程項目中,只用一臺redis是不夠的,原因如下:
從結(jié)構(gòu)上,單個Redis服務器會發(fā)色單點故障,并且一臺服務器需要處理所有的請求負載,壓力較大;
從容量上,單個Redis服務器內(nèi)部容量有限,無法將所有內(nèi)存用作Redis存儲內(nèi)存。一般來說,單臺Redis的最大使用內(nèi)存不應該超過20G
環(huán)境配置
只配置從庫,不用配置主庫!
[root@localhost bin]# redis-server wconfig/redis.conf
[root@localhost bin]# redis-cli -p 6379
127.0.0.1:6379> info replication#查看當前庫的信息
# Replication
role:master
connected_slaves:0#從機個數(shù)
master_failover_state:no-failover
master_replid:578832bddda2f86b82bf1cf619620397a44c0d98
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
賦值配置文件,修改對應的信息
端口
pid名字
log文件名字
dump.rdb名字

一主二從
默認情況下,每臺Redis服務器都是主節(jié)點;一般情況下只需要配置從機就好了!
SLAVEOF 主機ip 端口號#在從機中配置
真實的主從配置應該在配置文件中配置,這樣才是永久的,使用命令配置是暫時的.

細節(jié)
主機可以寫,從機只能讀!主機中的所有信息和數(shù)據(jù),都會自動的被從機保存
測試:主機斷開連接,從機依舊連接到主機,但是沒有寫操作;主機如果重連,從機依舊可以獲取主機寫入的信息
如果是使用命令行配置主從,如果重啟從機,從機就會變回主機。如果重新設置成從機,那么還可以獲取主機數(shù)據(jù)
復制原理
從機啟動成功連接到主機后會發(fā)送一個同步命令
主機接到命令,啟動后臺的存盤進程,同時收集所有接受到的用于修改數(shù)據(jù)集命令,在后臺進程執(zhí)行完畢之后主機將整個數(shù)據(jù)文件傳到從機,并完成一次完全同步。
全量賦值:從機服務在接收到數(shù)據(jù)庫文件數(shù)據(jù)后,將其存盤并加載到內(nèi)存中
增量賦值:主機繼續(xù)將新的所有收集到的修改命令一次傳給從機完成同步
但是只要重新連接主機,一次完全同步(全量復制)將被自動執(zhí)行!數(shù)據(jù)一定可以在從機中看到


這個時候也可以完成主從復制
如果主節(jié)點斷開,這個時候只能手動完成(沒有哨兵模式)
SLAVEOF on one;若主機斷開,將從節(jié)點設置成主節(jié)點!其他的結(jié)點就可以手動操作到主節(jié)點
哨兵模式(redis2.8開始提供)
概述
能夠后臺監(jiān)控主機是否故障,如果故障了根據(jù)投票數(shù)自動將從庫轉(zhuǎn)為主庫
哨兵模式是一種特殊的模式,首先Redis提供了哨兵的命令,哨兵是一個獨立的進程,作為進程,它會獨立運行。其原理是哨兵通過發(fā)送命令,等待Redis服務器響應,從而監(jiān)控運行多個Redis實例。

這里的哨兵有兩個作用
通過發(fā)送命令,讓Redis服務器返回監(jiān)控其運行狀態(tài),包括主服務器和從服務器
當哨兵監(jiān)測到master宕機,會自動將slave切換成master,然后通過發(fā)布訂閱模式通知其他的從服務器,修改配置文件,讓它們切換主機
然而一個哨兵進程對Redis服務器進行監(jiān)控,可能會出現(xiàn)問題,因此可以采用多哨兵進行監(jiān)控。各個哨兵之間還會進行監(jiān)控,這樣就形成了多哨兵模式。

假設主服務器宕機,哨兵1先檢測到這個結(jié)果,系統(tǒng)不會馬上進行重新選舉的過程,僅僅是哨兵1主觀的認為主服務器不可用,這個現(xiàn)象稱為主觀下線。當后面的哨兵也檢測到主服務器不可用,并且數(shù)量達到一定值時,那么哨兵之間就會進行一次投票,投票的結(jié)果由一個哨兵發(fā)起,進行故障轉(zhuǎn)移操作。切換成功后,就會通過發(fā)布訂閱模式,讓各個哨兵把自己監(jiān)控的從服務器實現(xiàn)切換主機,這個過程成為客觀下線。
哨兵配置
[root@localhost wconfig]# vim sentinel.conf #在配置文件目錄下新建哨兵配置文件
#sentinel monitor 被監(jiān)控的名稱? host port 1 #開啟投票
sentinel monitor myredis127.0.0.163791
啟動哨兵
[root@localhost bin]# redis-sentinel wconfig/sentinel.conf
[root@localhost bin]# redis-sentinel wconfig/sentinel.conf
3450:X23Mar202114:01:35.952# oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
3450:X23Mar202114:01:35.952# Redis version=6.2.1, bits=64, commit=00000000, modified=0, pid=3450, just started
3450:X23Mar202114:01:35.952# Configuration loaded
3450:X23Mar202114:01:35.953 * Increased maximum number of open files to10032(it was originallysetto1024).
3450:X23Mar202114:01:35.953 * monotonic clock: POSIX clock_gettime
? ? ? ? ? ? ?? _._ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
_.-``__''-._
_.-```.? `_.''-._ ? ? ? ? ? Redis6.2.1 (00000000/0)64bit
.-``.-```.? ```\/ ?? _.,_''-._
(' ? ?? , ? ? ? .-`? | `, ?? ) ? ? Running in sentinel mode
|`-._`-...-` __...-.``-._|'`_.-'| ? ? Port: 26379
|`-._ ? `._ ?? / ? ? _.-' ?? | ? ? PID: 3450
`-._ ?? `-._`-./? _.-' ?? _.-' ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
|`-._`-._`-.__.-' ?? _.-'_.-'| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
|`-._`-._ ? ? ?? _.-'_.-'| ? ? ? ? ? http://redis.io
`-._ ?? `-._`-.__.-'_.-' ?? _.-' ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
|`-._`-._`-.__.-' ?? _.-'_.-'| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
|`-._`-._ ? ? ?? _.-'_.-'|
`-._ ?? `-._`-.__.-'_.-' ?? _.-' ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
`-._ ?? `-.__.-' ?? _.-'
`-._ ? ? ?? _.-' ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
`-.__.-' ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
3450:X23Mar202114:01:35.954# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
3450:X23Mar202114:01:35.955# Sentinel ID is 80bbca2a11769d234d3cfb2b826429af2ae27f80
3450:X23Mar202114:01:35.955# +monitor master myredis 127.0.0.1 6379 quorum 1
3450:X23Mar202114:01:35.956 *+slave slave127.0.0.1:6380127.0.0.16380@ myredis127.0.0.16379
3450:X23Mar202114:01:35.965 *+slave slave127.0.0.1:6381127.0.0.16381@ myredis127.0.0.16379
如果主機宕機,哨兵會自動選出新的主機并做好遷移處理,而原主機重連之后,只能歸并到新的主機下變?yōu)閺臋C
哨兵模式
優(yōu)點:
哨兵集群基于主從復制模式,所有的主從配置優(yōu)點全都有
主從可以切換,故障可以轉(zhuǎn)義,系統(tǒng)可用性會更好
哨兵模式類似于主從模式的升級,從手動到自動,健壯性更好
缺點:
Redis不好在線擴容,集群容量一旦到達上線,在線擴容十分麻煩!
實現(xiàn)哨兵模式的配置很麻煩,選擇比較多
哨兵模式的全部配置
# Example ? sentinel.conf
# 哨兵sentinel實例運行的端口 ? 默認是26379,如果有哨兵集群,還需要配置每個哨兵端口
port26379
#哨兵sentinel的工作目錄
dir /tmp
#哨兵 sentine1 監(jiān)控的redis主節(jié)點的 ip port ?
# master-name? ,可以自己命名的主節(jié)點名字 只能由字母A-Z、數(shù)字0-9、這三個字符"? . ? -? _ "組成。
# quorum配置多少個sentine1哨兵統(tǒng)- -認為master主節(jié)點失聯(lián)那么這時客觀上認為主節(jié)點失聯(lián)了
# sentine1 monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster127.0.0.163792
#當在Redis實例中開啟了requirepass foobared 授權(quán)密碼這樣所有連接kedis實例的客戶端都要提供密碼
#設置哨兵sentinel連接主從的密碼注意必須為主從設置- - 樣的驗證密碼
# sentine1 auth-pass <master-name> <password>
sentine1 auth-pass mymaster MySUPER--secret-0123passwOrd
#指定多少毫秒之后主節(jié)點沒有應答哨兵sentine1 此時哨兵主觀上認為主節(jié)點下線默認30秒
# sentinel down-after-mi 11i seconds <master-name> <mi 11iseconds>
sentine1 down-after-mi 11iseconds mymaster30000
#這個配置項指定了在發(fā)生failover主備切換時最多可以有多少個slave同時對新的master進行同步,
這個數(shù)字越小,完成fai lover所需的時間就越長,
但是如果這個數(shù)字越大,就意味著越多的slave因為replication而 不可用。
可以通過將這個值設為1來保證每次只有一個slave處于不能處理命令請求的狀態(tài)。
# sentine1 paralle1-syncs <master-name> <numslaves>
sentine1 paralle1-syncs mymaster1
#故障轉(zhuǎn)移的超時時間failover-timeout 可以用在以下這些方面:
#1.同一個sentine1對同一 個master兩次fai lover之間的間隔時間。
#2.當一個slave從一 個錯誤的master那里同步數(shù)據(jù)開始計算時間。直到s1ave被糾正為向正確的master那里同步數(shù)據(jù)時。
#3.當想要取消一個正在進行的failover所需要的時間。
#4.當進行failover時,配置所有s1aves指向新的master所需的最大時間。不過,即使過了這個超時,slaves 依然會被正確配置為指向master,但是就不按parallel-syncs所配置的規(guī)則來了
#默認三分鐘
# sentine1 failover-timeout <master-name> <milliseconds>
sentine1 fai lover-ti meout mymaster180000
# SCRIPTS EXECUTION
#配置當某一事件發(fā)生時所需要執(zhí)行的腳本,可以通過腳本來通知管理員,例如當系統(tǒng)運行不正常時發(fā)郵件通知相關(guān)人員。
#對于腳本的運行結(jié)果有以下規(guī)則:
#若腳本執(zhí)行后返回1,那么該腳本稍后將會被再次執(zhí)行,重復次數(shù)目前默認為10
#若腳本執(zhí)行后返回2,或者比2更高的一個返回值,腳本將不會重復執(zhí)行。
#如果腳本在執(zhí)行過程中由于收到系統(tǒng)中斷信號被終止了,則同返回值為1時的行為相同。
#一個腳本的最大執(zhí)行時間為60s,如果超過這個時間,腳本將會被-一個SIGKILL信號終止,之后重新執(zhí)行。
#通知型腳本:當sentine1有任何警告級別的事件發(fā)生時(比如說redis實例的主觀失效和客觀失效等等),將會去調(diào)用這個腳本,這時這個腳本應該通過郵件,SMS等 方式去通知系統(tǒng)管理員關(guān)于系統(tǒng)不正常運行的信息。調(diào)用該腳本時,將傳給腳本兩個參數(shù),一 個是事件的類型,一個是事件的描述。如果sentine1. conf配置文件中配置了這個腳本路徑,那么必須保證這個腳本存在于這個路徑,并且是可執(zhí)行的,否則sentine1無法正常啟動成功。
#通知腳本
# she11編程
# sentine1 notification-script <master-name> <script-path>
sentine1 notificati on-script mymaster /var/redis/notify.sh
#客戶端重新配置主節(jié)點參數(shù)腳本
#當一個master由于failover而發(fā)生改變時,這個腳本將會被調(diào)用,通知相關(guān)的客戶端關(guān)于master地址已經(jīng)發(fā)生改變的信息。
#以下參數(shù)將會在調(diào)用腳本時傳給腳本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
#目前<state>總是“failover",
# <role>是“Teader"或者"observer"中的-一個。
#參數(shù)from-ip, from-port, to-ip,to-port是用來和舊的master和新的master(即舊的s lave)通信的
#這個腳本應該是通用的,能被多次調(diào)用,不是針對性的。
# sentine1 client-reconfig-script <master-name> <script-path>
sentine1 client-reconfig-script mymaster /var/redis/reconfig.sh#一般都是由運維來配置!
Redis緩存穿透和雪崩
緩存穿透(查不到)
概念
緩存穿透,就是查一個數(shù)據(jù)緩存中沒有,然后向數(shù)據(jù)庫中查詢。發(fā)現(xiàn)數(shù)據(jù)庫也沒有,因此查詢失敗。而當數(shù)據(jù)訪問量特別大的時候,會對數(shù)據(jù)庫造成很大壓力,出現(xiàn)了緩存穿透。
解決方案
布隆過濾器
布隆過濾器是一種數(shù)據(jù)結(jié)構(gòu),對所以可能查詢的參數(shù)以hash形式存儲,在控制層先進行校驗,不符合則丟棄,從而避免了對底層存儲系統(tǒng)的查詢壓力。

優(yōu)缺點
優(yōu)點:由于存放的不是完整數(shù)據(jù),所以占用內(nèi)存少,而且新增,查詢速度快
缺點:鎖著數(shù)據(jù)的增加,誤判率會隨之增加;無法做到刪除數(shù)據(jù);也就是說布隆過濾器說不存在就一定不存在,說存在那么是可能存在。
緩存空對象
當存儲曾不命中后,即使返回空對象也將其緩存起來,同時或設置一個過期時間,之后再訪問這個數(shù)據(jù)將會從緩存中獲取,不會再訪問數(shù)據(jù)庫。
緩存空對象存在問題
如果空值可以被緩存,這就意味著需要更多的空間存儲更多的鍵,因為空值的鍵可能會占用很大空間
即使對空值設置過期時間,還是會存在緩存和數(shù)據(jù)庫的數(shù)據(jù)會有一段時間窗口不一致,對數(shù)據(jù)的一致性會有影響
緩存擊穿(庫有緩存無,量大)
概述
緩存擊穿指一個key非常熱點,在高并發(fā)的環(huán)境下,緩存中查不到,但是數(shù)據(jù)庫中可以查到,導致所有訪問都進入到數(shù)據(jù)庫中,數(shù)據(jù)庫瞬間壓力過大。
解決方案
設置value永不過期
加互斥鎖(類似synchronized)
分布式鎖:使用分布式鎖,保證對于每個key同一時間只有一個線程去查詢后端服務,其他線程只能等待。將高并發(fā)的壓力轉(zhuǎn)移到分布式鎖,因此對于分布式鎖的考驗很大
緩存雪崩
概述
緩存雪崩,指同一時間緩存大量失效,到時大量訪問全部進入數(shù)據(jù)庫,可能會造成數(shù)據(jù)庫崩潰進而導致網(wǎng)站崩潰
解決方案
Redis高可用-搭建集群
限流降級
數(shù)據(jù)預熱
正式部署之前,先把可能的數(shù)據(jù)預先訪問一遍,這樣部分可能大量訪問的數(shù)據(jù)就會加載到緩存中。在即將發(fā)生高并發(fā)訪問錢手動觸發(fā)加載緩存不同的key,設置不同的過期時間,讓緩存失效的時間點盡量均勻