NOsql
泛指非關(guān)系型數(shù)據(jù)庫啊研,為了克服超大規(guī)模的高并發(fā)的問題畏腕,NoSQL在當(dāng)今大數(shù)據(jù)環(huán)境下發(fā)展的十分迅速凸主,Redis是發(fā)展最快的橘券。
方便擴展(數(shù)據(jù)之間沒有關(guān)系)
大數(shù)據(jù)量高性能(Redis一秒寫8萬次,讀取11萬次卿吐,NoSQL的緩存記錄級旁舰,是一種細(xì)粒度的緩存,性能會比較高)
數(shù)據(jù)類型是多樣的(不需要事先設(shè)計數(shù)據(jù)庫)
發(fā)展歷程
單機MySQL->緩存+Mysql+垂直拆分(讀寫分離)->分庫分表+水平拆分+服務(wù)器集群
四大分類
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)絡(luò)磺樱,可基于內(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的默認(rèn)安裝路徑? /usr/local/bin
復(fù)制配置文件到指定目錄
redis默認(rèn)不是后臺啟動的憾儒,修改配置文件询兴,使redis后臺啟動
啟動redis服務(wù)
查看redis進程是否開啟
Redis性能測試
redis -benchmark
Redis基礎(chǔ)
redis有16個數(shù)據(jù)庫乃沙,默認(rèn)使用第0個起趾。
Redis是單線程的,基于內(nèi)存操作警儒,CPU不是Redis的性能瓶頸训裆,Redis的瓶頸是根據(jù)機器的內(nèi)存和網(wǎng)絡(luò)帶寬,既然可以使用單線程來實現(xiàn)蜀铲,就使用單線程來實現(xiàn)
Redis是C語言寫的边琉,每秒100000+的QPS,完全不比同樣是使用key-value的Memecache(一套分布式的快取系統(tǒng))差.
Redis為什么單線程還這么快?
誤區(qū)1:高性能的服務(wù)器一定是多線程的记劝?
誤區(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#判斷當(dāng)前key是否存在
move key database#移除當(dāng)前key
expire key seconds#設(shè)置key的過期時間耕驰,單位秒
tll key#查看當(dāng)前key的剩余時間
type key#查看當(dāng)前key的類型
append key “”#追加/如key不存在就相當(dāng)于set
strlen key#獲取字符創(chuàng)的長度
################################################
#步長 i+=
#i++
setviews0#初始瀏覽量為0
incr views#自增1
decr views#自減1
incrby views10#可以設(shè)置步長爷辱,指定增量
###################################################
#字符串范圍? range
GETRANGE key03#截取字符串[0,3]
GETRANGE key0-1#獲取全部的字符串
#替換
SETRANGE key1xx#替換指定位置開始的字符串
#######################################################
#setex (set with expire) #設(shè)置過期時間
#setnx (set if not exist) #不存在 再設(shè)置 (在分布式鎖種會常常使用!)
############################################################
mset#同時設(shè)置多個值
mget#同時獲取多個值
#對象
setuser:1 {name:wir,age:3}#設(shè)置一個user:1對象值為json字符來保存一個對象
#######################################################################
getset#先get再set
#如果不存在值朦肘,怎創(chuàng)建返回nil饭弓;如果存在值,獲取原來的值并設(shè)置新值
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#通過下標(biāo)截取指定的長度
##################################################
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ī)則:兩極無法直接添加,一般通過程序一次性導(dǎo)入
#參數(shù) key 值(緯度苟耻,經(jīng)度篇恒,名稱)
geoadd china:city116.40.39.90 beijing#添加坐標(biāo)
#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)哮翘!
事務(wù)
Redis事務(wù)本質(zhì):一組命令的集合!一個事務(wù)中的所有命令都會被序列化毛秘,在事務(wù)執(zhí)行過程中饭寺,會按照順序執(zhí)行!
一次性叫挟,順序性艰匙,排他性!執(zhí)行一些列的命令抹恳!
Redis事務(wù)沒有隔離級別的概念员凝!(不會出現(xiàn)臟讀,幻讀奋献,不可重復(fù)讀)
所有的命令在事務(wù)中健霹,并沒有直接被執(zhí)行!只有發(fā)起執(zhí)行命令的時候才會執(zhí)行瓶蚂!Exec
Redis單條命令是保證原子性的糖埋,但是事務(wù)不保證原子性
redis事務(wù)
開啟事務(wù)(multi)
命令入隊()
執(zhí)行事務(wù)(exec)
正常執(zhí)行事務(wù)
放棄事務(wù)-discard#取消事務(wù)
編譯型異常(代碼有問題!命令有錯)窃这,事務(wù)中所有的命令都不會被執(zhí)行
運行時異常瞳别,如果事務(wù)隊列中存在語法錯誤,那么執(zhí)行命令的時候,其他命令是可以正常執(zhí)行的祟敛,錯誤命令會拋出異常
監(jiān)控! Watch
悲觀鎖:
悲觀疤坝,無論做什么都加鎖!效率低下
樂觀鎖:
樂觀,認(rèn)為不會出問題馆铁,所以不加鎖跑揉!更新數(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 #事務(wù)正常結(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
如果事務(wù)執(zhí)行失敼远!就先unwatch(解除監(jiān)視)然后再watch(再次監(jiān)視)具练,最后對比監(jiān)視的值是否發(fā)生變化乍构,如果沒有變化,那么可以成功扛点,如果有變化就執(zhí)行失敻缯凇!繼續(xù)重復(fù)陵究。
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) {
//默認(rèn)的RedisTemplate沒有過多的設(shè)置,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ù)保存到磁盤雅倒,那么一旦服務(wù)器進程退出,服務(wù)器中的數(shù)據(jù)庫狀態(tài)也會消失攀芯,所以Redis提供了持久化功能屯断!
RDB(默認(rèn)RDB,一般情況下不需要修改配置)
在指定的時間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤,也就是快照殖演。它恢復(fù)時是將快照文件直接讀到內(nèi)存里氧秘。
redis會單獨創(chuàng)建一個子進程來進行持久化,先將數(shù)據(jù)寫入一個臨時文件中趴久,待持久化過程結(jié)束丸相,在用臨時文件替換上次持久化好的文件。整個過程中彼棍,主進程是不進行任何IO操作的灭忠。這就確保了極高的性能。
如果需要進行大規(guī)模數(shù)據(jù)的恢復(fù)座硕,且對于數(shù)據(jù)恢復(fù)的完整性不是非常敏感弛作,那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
如何恢復(fù)rdb文件旭旭!
只需要將rdb文件放在我們的redis啟動目錄就可以谎脯,redis啟動時會自動檢查dump.rdb并恢復(fù)其中的數(shù)據(jù)
優(yōu)點
適合大規(guī)模的數(shù)據(jù)恢復(fù)!
對數(shù)據(jù)的完整性要求不高持寄!
缺點
需要一定的時間間隔進行操作源梭!如果redis宕機了,這個最后一次修改的數(shù)據(jù)就沒有了
fork進程的時候际看,會占用一定的內(nèi)存空間
AOF(Append Only File)
將所有命令都記錄下來咸产,恢復(fù)的時候會把這個文件全部執(zhí)行一遍
以日志的形式來記錄每個寫操縱,將Redis執(zhí)行過的所有指令記錄下來(讀操作不記錄)仲闽,只許追加文件但不可以改寫文件脑溢,redis啟動之初會讀取該文件重新構(gòu)建數(shù)據(jù),換言之赖欣,Redis重啟的話就根據(jù)日志文件的內(nèi)容將寫指令從前到后執(zhí)行一次以完成數(shù)據(jù)的恢復(fù)工作
Aof保存的文件是appendonly.aof文件
redis默認(rèn)不開啟aof屑彻,需要手動修改配置文件!將appendonly改為yes才能開啟aof
如果aof文件有問題顶吮,無法重新啟動redis服務(wù)社牲,需要用redis-check-aof --fix appendonly-aof
如果aof文件大于64m!fork一個新的進程來將文件進行重寫
優(yōu)點和缺點
優(yōu)點:
每一次修改都同步悴了,文件的完整性更好
默認(rèn)每秒同步一次搏恤,可能會丟失一秒的數(shù)據(jù)
若從不同步违寿,效率最高!
缺點:
相對于數(shù)據(jù)文件來說熟空,aof遠(yuǎn)遠(yuǎn)大于rdb藤巢,修復(fù)的速度也比rdb慢!
Aof運行的效率也要比rdb慢息罗,所以redis默認(rèn)的持久化方式是rdb掂咒!
擴展:
RDB持久化方式能夠在指定的時間間隔內(nèi)對數(shù)據(jù)進行快照存儲
AOF持久化方式記錄每次對服務(wù)器的寫操作,當(dāng)服務(wù)器重啟的時候回重新執(zhí)行這些命令來恢復(fù)原始數(shù)據(jù)迈喉,AOF命令以Redis協(xié)議追加保存每次寫的操作到文件末尾绍刮,Redis還能對aof文件進行后臺重寫,防止aof文件體積不至于過大挨摸。
只做緩存孩革,不需要使用任何持久化
同時開啟兩種持久化方式
在這種情況下當(dāng)redis重啟的時候會優(yōu)先載入aof文件來恢復(fù)原始數(shù)據(jù),因為在通常情況下aof文件保存的數(shù)據(jù)集要比RDB文件保存的數(shù)據(jù)集完整
RDB的數(shù)據(jù)不實時油坝,同時使用兩者時服務(wù)器重啟也只會找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ù)寫到新文件造成的阻塞幾乎是不可避免的压怠。只要硬盤許可眠冈,應(yīng)該盡量減少AOF重寫的頻率,AOF重寫的基礎(chǔ)大小默認(rèn)值64M太小了菌瘫,可以設(shè)置到5G以上蜗顽,默認(rèn)超過原大小100%重寫可以改到適當(dāng)?shù)臄?shù)值。
如果不開啟AOF雨让,僅靠Master-Slave(主從復(fù)制) 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中可以設(shè)定對某一個key值進行消息發(fā)布及消息訂閱,當(dāng)一個key值上進行了消息發(fā)布后滤港,所有訂閱他的客戶端都會收到相應(yīng)的消息廊蜒。這一功能最明顯的用法就是用作實時消息系統(tǒng)胆建,比如普通的即使聊天正驻,群聊等。
使用場景:
實時消息系統(tǒng)陨闹!
實時聊天樟凄!
訂閱關(guān)注系統(tǒng)聘芜!
Redis主從復(fù)制
主從復(fù)制,是指將一臺Redis服務(wù)器的數(shù)據(jù)缝龄,復(fù)制到其他的Redis服務(wù)器汰现。前者成為主節(jié)點(Master/leader)挂谍,后者稱為從節(jié)點(slave/follower);數(shù)據(jù)的復(fù)制是單向的,只能由主節(jié)點到從節(jié)點瞎饲。Master以寫為主口叙,Slave以讀為主。
默認(rèn)情況下嗅战,每臺Redis服務(wù)器都是主節(jié)點妄田;且一個主節(jié)點可以有多個從節(jié)點(或沒有),但一個從節(jié)點只可以有一個主節(jié)點驮捍。
主從復(fù)制的作用主要包括:
數(shù)據(jù)冗余(重復(fù)數(shù)據(jù)):主從復(fù)制實現(xiàn)了數(shù)據(jù)的熱備份疟呐,是持久化之外的一種數(shù)據(jù)冗余方式。
故障恢復(fù):當(dāng)主節(jié)點出現(xiàn)問題時东且,可以由從節(jié)點提供服務(wù)启具,實現(xiàn)快速的故障恢復(fù);實際上是一種服務(wù)的冗余
負(fù)載均衡:在主從復(fù)制的基礎(chǔ)上珊泳,配合讀寫分離鲁冯,可以由主節(jié)點提供寫服務(wù),由從節(jié)點提供讀服務(wù)(即寫數(shù)據(jù)時應(yīng)用連接主節(jié)點色查,讀Redis數(shù)據(jù)應(yīng)用連接從節(jié)點)薯演,分擔(dān)服務(wù)器負(fù)載;尤其是在寫少讀多的場景下秧了,通過多個從節(jié)點分擔(dān)讀負(fù)載涣仿,可以大大提高Redis服務(wù)器的并發(fā)量。
高可用(集群)基石:除了上述作用以外示惊,主從復(fù)制還是哨兵和集群能夠?qū)嵤┑幕A(chǔ),因此說主從復(fù)制時Redis高可用的基礎(chǔ)愉镰。
最少米罚,一主二從
一般來說,要將redis運用于工程項目中丈探,只用一臺redis是不夠的录择,原因如下:
從結(jié)構(gòu)上,單個Redis服務(wù)器會發(fā)色單點故障碗降,并且一臺服務(wù)器需要處理所有的請求負(fù)載隘竭,壓力較大;
從容量上讼渊,單個Redis服務(wù)器內(nèi)部容量有限动看,無法將所有內(nèi)存用作Redis存儲內(nèi)存。一般來說爪幻,單臺Redis的最大使用內(nèi)存不應(yīng)該超過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#查看當(dāng)前庫的信息
# 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
賦值配置文件,修改對應(yīng)的信息
端口
pid名字
log文件名字
dump.rdb名字
一主二從
默認(rèn)情況下仇轻,每臺Redis服務(wù)器都是主節(jié)點京痢;一般情況下只需要配置從機就好了!
SLAVEOF 主機ip 端口號#在從機中配置
真實的主從配置應(yīng)該在配置文件中配置篷店,這樣才是永久的祭椰,使用命令配置是暫時的.
細(xì)節(jié)
主機可以寫,從機只能讀疲陕!主機中的所有信息和數(shù)據(jù)方淤,都會自動的被從機保存
測試:主機斷開連接,從機依舊連接到主機鸭轮,但是沒有寫操作臣淤;主機如果重連,從機依舊可以獲取主機寫入的信息
如果是使用命令行配置主從窃爷,如果重啟從機邑蒋,從機就會變回主機。如果重新設(shè)置成從機按厘,那么還可以獲取主機數(shù)據(jù)
復(fù)制原理
從機啟動成功連接到主機后會發(fā)送一個同步命令
主機接到命令医吊,啟動后臺的存盤進程,同時收集所有接受到的用于修改數(shù)據(jù)集命令逮京,在后臺進程執(zhí)行完畢之后主機將整個數(shù)據(jù)文件傳到從機卿堂,并完成一次完全同步。
全量賦值:從機服務(wù)在接收到數(shù)據(jù)庫文件數(shù)據(jù)后懒棉,將其存盤并加載到內(nèi)存中
增量賦值:主機繼續(xù)將新的所有收集到的修改命令一次傳給從機完成同步
但是只要重新連接主機草描,一次完全同步(全量復(fù)制)將被自動執(zhí)行!數(shù)據(jù)一定可以在從機中看到
這個時候也可以完成主從復(fù)制
如果主節(jié)點斷開策严,這個時候只能手動完成(沒有哨兵模式)
SLAVEOF on one穗慕;若主機斷開,將從節(jié)點設(shè)置成主節(jié)點妻导!其他的結(jié)點就可以手動操作到主節(jié)點
哨兵模式(redis2.8開始提供)
概述
能夠后臺監(jiān)控主機是否故障逛绵,如果故障了根據(jù)投票數(shù)自動將從庫轉(zhuǎn)為主庫
哨兵模式是一種特殊的模式,首先Redis提供了哨兵的命令倔韭,哨兵是一個獨立的進程术浪,作為進程,它會獨立運行寿酌。其原理是哨兵通過發(fā)送命令胰苏,等待Redis服務(wù)器響應(yīng),從而監(jiān)控運行多個Redis實例份名。
這里的哨兵有兩個作用
通過發(fā)送命令碟联,讓Redis服務(wù)器返回監(jiān)控其運行狀態(tài)妓美,包括主服務(wù)器和從服務(wù)器
當(dāng)哨兵監(jiān)測到master宕機,會自動將slave切換成master鲤孵,然后通過發(fā)布訂閱模式通知其他的從服務(wù)器壶栋,修改配置文件,讓它們切換主機
然而一個哨兵進程對Redis服務(wù)器進行監(jiān)控普监,可能會出現(xiàn)問題贵试,因此可以采用多哨兵進行監(jiān)控。各個哨兵之間還會進行監(jiān)控凯正,這樣就形成了多哨兵模式毙玻。
假設(shè)主服務(wù)器宕機,哨兵1先檢測到這個結(jié)果廊散,系統(tǒng)不會馬上進行重新選舉的過程桑滩,僅僅是哨兵1主觀的認(rèn)為主服務(wù)器不可用,這個現(xiàn)象稱為主觀下線允睹。當(dāng)后面的哨兵也檢測到主服務(wù)器不可用运准,并且數(shù)量達(dá)到一定值時,那么哨兵之間就會進行一次投票缭受,投票的結(jié)果由一個哨兵發(fā)起胁澳,進行故障轉(zhuǎn)移操作。切換成功后米者,就會通過發(fā)布訂閱模式韭畸,讓各個哨兵把自己監(jiān)控的從服務(wù)器實現(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)點:
哨兵集群基于主從復(fù)制模式隘马,所有的主從配置優(yōu)點全都有
主從可以切換,故障可以轉(zhuǎn)義妻顶,系統(tǒng)可用性會更好
哨兵模式類似于主從模式的升級,從手動到自動蜒车,健壯性更好
缺點:
Redis不好在線擴容讳嘱,集群容量一旦到達(dá)上線,在線擴容十分麻煩酿愧!
實現(xiàn)哨兵模式的配置很麻煩沥潭,選擇比較多
哨兵模式的全部配置
# Example ? sentinel.conf
# 哨兵sentinel實例運行的端口 ? 默認(rèn)是26379,如果有哨兵集群嬉挡,還需要配置每個哨兵端口
port26379
#哨兵sentinel的工作目錄
dir /tmp
#哨兵 sentine1 監(jiān)控的redis主節(jié)點的 ip port ?
# master-name? 钝鸽,可以自己命名的主節(jié)點名字 只能由字母A-Z汇恤、數(shù)字0-9、這三個字符"? . ? -? _ "組成拔恰。
# quorum配置多少個sentine1哨兵統(tǒng)- -認(rèn)為master主節(jié)點失聯(lián)那么這時客觀上認(rèn)為主節(jié)點失聯(lián)了
# sentine1 monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster127.0.0.163792
#當(dāng)在Redis實例中開啟了requirepass foobared 授權(quán)密碼這樣所有連接kedis實例的客戶端都要提供密碼
#設(shè)置哨兵sentinel連接主從的密碼注意必須為主從設(shè)置- - 樣的驗證密碼
# sentine1 auth-pass <master-name> <password>
sentine1 auth-pass mymaster MySUPER--secret-0123passwOrd
#指定多少毫秒之后主節(jié)點沒有應(yīng)答哨兵sentine1 此時哨兵主觀上認(rèn)為主節(jié)點下線默認(rèn)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而 不可用。
可以通過將這個值設(shè)為1來保證每次只有一個slave處于不能處理命令請求的狀態(tài)河爹。
# sentine1 paralle1-syncs <master-name> <numslaves>
sentine1 paralle1-syncs mymaster1
#故障轉(zhuǎn)移的超時時間failover-timeout 可以用在以下這些方面:
#1.同一個sentine1對同一 個master兩次fai lover之間的間隔時間匠璧。
#2.當(dāng)一個slave從一 個錯誤的master那里同步數(shù)據(jù)開始計算時間。直到s1ave被糾正為向正確的master那里同步數(shù)據(jù)時咸这。
#3.當(dāng)想要取消一個正在進行的failover所需要的時間夷恍。
#4.當(dāng)進行failover時,配置所有s1aves指向新的master所需的最大時間媳维。不過酿雪,即使過了這個超時,slaves 依然會被正確配置為指向master,但是就不按parallel-syncs所配置的規(guī)則來了
#默認(rèn)三分鐘
# sentine1 failover-timeout <master-name> <milliseconds>
sentine1 fai lover-ti meout mymaster180000
# SCRIPTS EXECUTION
#配置當(dāng)某一事件發(fā)生時所需要執(zhí)行的腳本侨艾,可以通過腳本來通知管理員执虹,例如當(dāng)系統(tǒng)運行不正常時發(fā)郵件通知相關(guān)人員。
#對于腳本的運行結(jié)果有以下規(guī)則:
#若腳本執(zhí)行后返回1唠梨,那么該腳本稍后將會被再次執(zhí)行袋励,重復(fù)次數(shù)目前默認(rèn)為10
#若腳本執(zhí)行后返回2,或者比2更高的一個返回值当叭,腳本將不會重復(fù)執(zhí)行茬故。
#如果腳本在執(zhí)行過程中由于收到系統(tǒng)中斷信號被終止了,則同返回值為1時的行為相同蚁鳖。
#一個腳本的最大執(zhí)行時間為60s磺芭,如果超過這個時間,腳本將會被-一個SIGKILL信號終止醉箕,之后重新執(zhí)行钾腺。
#通知型腳本:當(dāng)sentine1有任何警告級別的事件發(fā)生時(比如說redis實例的主觀失效和客觀失效等等),將會去調(diào)用這個腳本讥裤,這時這個腳本應(yīng)該通過郵件放棒,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ù)腳本
#當(dāng)一個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)通信的
#這個腳本應(yīng)該是通用的,能被多次調(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ù)庫也沒有,因此查詢失敗挎峦。而當(dāng)數(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ù);也就是說布隆過濾器說不存在就一定不存在遗增,說存在那么是可能存在才菠。
緩存空對象
當(dāng)存儲曾不命中后,即使返回空對象也將其緩存起來贡定,同時或設(shè)置一個過期時間,之后再訪問這個數(shù)據(jù)將會從緩存中獲取可都,不會再訪問數(shù)據(jù)庫缓待。
緩存空對象存在問題
如果空值可以被緩存蚓耽,這就意味著需要更多的空間存儲更多的鍵,因為空值的鍵可能會占用很大空間
即使對空值設(shè)置過期時間旋炒,還是會存在緩存和數(shù)據(jù)庫的數(shù)據(jù)會有一段時間窗口不一致步悠,對數(shù)據(jù)的一致性會有影響
緩存擊穿(庫有緩存無,量大)
概述
緩存擊穿指一個key非常熱點瘫镇,在高并發(fā)的環(huán)境下鼎兽,緩存中查不到,但是數(shù)據(jù)庫中可以查到铣除,導(dǎo)致所有訪問都進入到數(shù)據(jù)庫中谚咬,數(shù)據(jù)庫瞬間壓力過大。
解決方案
設(shè)置value永不過期
加互斥鎖(類似synchronized)
分布式鎖:使用分布式鎖尚粘,保證對于每個key同一時間只有一個線程去查詢后端服務(wù),其他線程只能等待择卦。將高并發(fā)的壓力轉(zhuǎn)移到分布式鎖,因此對于分布式鎖的考驗很大
緩存雪崩
概述
緩存雪崩郎嫁,指同一時間緩存大量失效秉继,到時大量訪問全部進入數(shù)據(jù)庫,可能會造成數(shù)據(jù)庫崩潰進而導(dǎo)致網(wǎng)站崩潰
解決方案
Redis高可用-搭建集群
限流降級
數(shù)據(jù)預(yù)熱
正式部署之前泽铛,先把可能的數(shù)據(jù)預(yù)先訪問一遍尚辑,這樣部分可能大量訪問的數(shù)據(jù)就會加載到緩存中。在即將發(fā)生高并發(fā)訪問錢手動觸發(fā)加載緩存不同的key盔腔,設(shè)置不同的過期時間杠茬,讓緩存失效的時間點盡量均勻