文章目錄
- 1 NoSQL入門概述
- 1.1 能干嘛?
- 1.2 傳統RDBMS VS NOSQL
- 1.3 NoSQL數據庫的四大分類
- 1.4 分布式數據庫CAP原理 + BASE原則
- 1.5 分布式+集群簡介
- 1.6 淘寶商品信息的存儲方案
- 2 Redis入門概述
- 2.1 是什么?
- 2.2 能干嘛?
- 2.3 怎么玩?核心
- 2.4 MAC安裝redis
- 2.5 Redis的五大數據類型
- 2.6 常用命令
- 3 Redis配置文件
- 4 Redis持久化【RDB、AOF】
- 持久化之RDB
- 持久化之AOF
- 如何選擇?
- 5 Redis事務(Transacttion)
- 常見CASE
- 6 Redis主從復制、讀寫分離
- case1:一主二仆【中心化架構】
- case2:薪火相傳【去中心化架構】
- case3:反客為主
- case4:哨兵模式(sentinel)
參考文檔
Redis官網: https://redis.io/
Redis中文網: http://www.redis.cn/
Redis 命令參考: http://redisdoc.com/string/set.html
1 NoSQL入門概述
NoSQL(NoSQL = Not Only SQL),意即“不僅僅是SQL”,泛指非關系型的數據庫。隨著互聯網web2.0網站的興起,傳統的關系數據庫在應付web2.0網站,特別是超大規模和高并發的web2.0純動態網站已經顯得力不從心,暴露了很多難以克服的問題,而非關系型的數據庫則由于其本身的特點得到了非常迅速的發展。NoSQL 數據庫的產生就是為了解決大規模數據集合、多重數據種類帶來的挑戰,尤其是大數據應用難題,包括超大規模數據的存儲。讀寫速度 讀:1s/8w、寫:1s/11w
1.1 能干嘛?
易擴展
NoSQL數據庫種類繁多,但是一個共同的特點都是去掉關系數據庫的關系型特性。數據之間無關系,這樣就非常容易擴展,無形之間在架構的層面上帶來了可擴展的能力。大數據量高性能
NoSQL數據庫都具有非常高的讀寫性能,尤其在大數據量下,同樣表現優秀。這得益于它的無關系性,數據庫的結構簡單。一般MySQL使用Query Cache,每次表的更新Cache就失效,是一種大粒度的Cache,在針對web2.0的交互頻繁的應用,Cache性能不高。而NoSQL的Cache是記錄級的,是一種細粒度的Cache,所以NoSQL在這個層面上來說就要性能高很多了。多樣靈活的數據模型
NoSQL無需事先為要存儲的數據建立字段,隨時可以存儲自定義的數據格式。而在關系數據庫里,增刪字段是一件非常麻煩的事情。如果是非常大數據量的表,增加字段簡直就是一個噩夢。
1.2 傳統RDBMS VS NOSQL
RDBMS高度組織化結構化數據、結構化查詢語言(SQL)數據和關系都存儲在單獨的表中、數據操縱語言,數據定義語言嚴格的一致性、 基礎事務
NoSQL代表著不僅僅是SQL、沒有聲明性查詢語言沒有預定義的模式、 鍵-值對存儲,列存儲,文檔存儲,圖形數據庫最終一致性,而非ACID屬性、 非結構化和不可預知的數據:CAP定理、 高性能,高可用性和可伸縮性
1.3 NoSQL數據庫的四大分類
KV新浪: BerkeleyDB + Redis美團: Redis + tair阿里、百度: memcache + Redis文檔型數據庫(bson格式比較多)CouchDB、MongoDB
PS:MongoDB是一個基于分布式文件存儲的數據庫。由C++語言編寫。旨在為WEB應用提供可擴展的高性能數據存儲解決方案。MongoDB是一個介于關系數據庫和非關系數據庫之間的產品,是非關系數據庫當中功能最豐富,最像關系數據庫的。列存儲數據庫Cassandra、Hbase、分布式文件系統
圖關系數據庫Neo4j、InfoGrid它不是放圖形的、放的是關系比如:朋友圈社交網絡、廣告推薦系統、社交網絡、推薦系統。專注于構建關系圖譜
1.4 分布式數據庫CAP原理 + BASE原則
傳統的ACID分別是什么?A (Atomicity) 原子性C (Consistency) 一致性I (Isolation) 獨立性D (Durability) 持久性
CAP【CAP理論就是說在分布式存儲系統中,最多只能實現兩點,三選二】C: Consistency(強一致性)A: Availability(高可用性)P: Partition tolerance(分區容錯性)
而由于當前的網絡硬件肯定會出現延遲丟包等問題,所以分區容忍性P是我們必須需要實現的。所以我們只能在強一致性C和高可用性A之間進行權衡,沒有NoSQL系統能同時保證這三點。CAP理論的核心是:一個分布式系統不可能同時很好的滿足一致性,可用性和分區容錯性這三個需求,最多只能同時較好的滿足兩個。多余大多數web應用,其實并不需要強一致性。因此犧牲C換取P,這是目前分布式數據庫產品的方向。
因此,根據 CAP 原理將 NoSQL 數據庫分成了滿足 CA 原則、滿足 CP 原則和滿足 AP 原則三大類:CA - 傳統Oracle數據庫,單點集群,滿足一致性,可用性的系統,通常在可擴展性上不太強大。AP - 滿足可用性,分區容忍性的系統,通常可能對一致性要求低一些。大多數網站架構的選擇【數據可以不一定精確,犧牲強一致性P,一定要保證網站可用,實現可用性A,電商、金融系統等】CP - Redis、Mongodb,滿足一致性,分區容忍必的系統,通常性能不是特別高。BASE:就是為了解決關系數據庫強一致性引起的問題而引起的可用性降低而提出的解決方案。基本可用(Basically Available)軟狀態(Soft state)最終一致(Eventually consistent)
它的思想是通過讓系統放松對某一時刻數據一致性的要求來換取系統整體伸縮性和性能上改觀。為什么這么說呢,緣由就在于大型系統往往由于地域分布和極高性能的要求,不可能采用分布式事務來完成這些指標,要想獲得這些指標,我們必須采用另外一種方式來完成,這里BASE就是解決這個問題的辦法
1.5 分布式+集群簡介
分布式系統(distributed system):由多臺計算機和通信的軟件組件,并通過計算機網絡連接(本地網絡或廣域網)。分布式系統是建立在網絡之上的軟件系統。正是因為軟件的特性,所以分布式系統具有高度的內聚性和透明性。因此,網絡和分布式系統之間的區別更多的在于高層軟件(特別是操作系統),而不是硬件。分布式系統可以應用在在不同的平臺上如:PC、工作站、局域網和廣域網上等。
簡單來講:
分布式:不同的多臺服務器上面部署不同的服務模塊(工程),他們之間通過RPC之間通信和調用,對外提供服務和組內協作。
集群:不同的多臺服務器上面部署相同的服務模塊,通過分布式調度軟件進行統一的調度,對外提供服務和訪問。
1.6 淘寶商品信息的存儲方案
商品基本信息【名稱、價格,出廠日期,生產廠商等不經常信息】–> 關系型數據庫MySQL
商品描述、詳情、評價信息【多文字信息描述類】–> 文檔數據庫MongDB
商品的圖片 --> 分布式的文件系統【淘寶TFS、Google的GFS、Hadoop的HDFS】
商品的關鍵字 --> 淘寶自家ISearch
商品的波段性的熱點高頻信息【如,情人節的巧克力】 --> 內存數據庫Tair、Redis、Memcache
2 Redis入門概述
2.1 是什么?
Redis: Remote Dictionary Server(遠程字典服務器)是完全開源免費的,用C語言編寫的,遵守BSD協議,是一個高性能的(key/value)分布式內存數據庫,基于內存運行并支持持久化的NoSQL數據庫,是當前最熱門的NoSQL數據庫之一,也被人們稱為數據結構服務器。
Redis與其他 key - value 緩存產品有以下三個特點:Redis支持數據的持久化,可以將內存中的數據保持在磁盤中,重啟的時候可以再次加載進行使用Redis不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲Redis支持數據的備份,即master-slave模式的數據備份
2.2 能干嘛?
內存存儲和持久化:redis支持異步將內存中的數據寫到硬盤上,同時不影響繼續服務取最新N個數據的操作,如:可以將最新的10條評論的ID放在Redis的List集合里面模擬類似于HttpSession這種需要設定過期時間的功能發布、訂閱消息系統定時器、計數器
2.3 怎么玩?核心
數據類型、基本操作和配置持久化和復制,RDB/AOF事務的控制復制(主從關系)
2.4 MAC安裝redis
詳見安裝Redis.txt
cd /usr/local/redis-6.2.6./bin/redis-server etc/redis.conf 啟動服務./bin/redis-cli 打開redis客戶端
2.5 Redis的五大數據類型
String(字符串)string是redis最基本的類型,你可以理解成與Memcached一模一樣的類型,一個key對應一個value。string類型是二進制安全的。意思是redis的string可以包含任何數據。比如jpg圖片或者序列化的對象 。string類型是Redis最基本的數據類型,一個redis中字符串value最多可以是512M。Hash(哈希,類似java里的Map)Redis hash 是一個鍵值對集合。Redis hash是一個string類型的field和value的映射表,hash特別適合用于存儲對象。類似Java里面的Map<String,Object>List(列表)Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素導列表的頭部(左邊)或者尾部(右邊)。它的底層實際是個鏈表Set(集合)Redis的Set是string類型的無序集合。它是通過HashTable實現實現的Zset(sorted set:有序集合)Redis zset 和 set 一樣也是string類型元素的集合,且不允許重復的成員。
不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。zset的成員是唯一的,但分數(score)卻可以重復。
2.6 常用命令
Key
set k1 v1、set k2 1、get k1
mset k7 v7 k8 v8 批量操作
mget k7 k8
del k1、strlen k1
append k1 v11 如果key已經存在,將指定的value追加到該 key 原來值的末尾.如果key不存在,與set k1 v1一致select 1 選擇數據庫,默認16個數據庫,初始使用0號庫
dbsize 查看當前數據庫key的數量
flushdb 清空當前數據庫
flushall 清空所有數據庫
ttl key 查看還有多少秒過期,-1表示永不過期,-2表示已過期 [ttl: time to live]
expire key 秒鐘 為給定的key設置過期時間
type key 查看你的key是什么類型
exists key 判斷某個key是否存在
move key db 當前庫就沒有了,被移除了
String【單值單value】
incr k3、 incrby k3 2
decr k3、 decrby k3 2 一定要是數字才能進行加減
getrange k1 0 3 如果是字符串,則進行截取、如果是數字,則輸出
getrange k1 0 -1 截取全部字符串,等同于get k1
setrange k1 0 aaaa 從下標0開始賦值,會替代字符串后面的字符,而不是后移
setnx k5 v5 setnx(set if not exist)不存在則賦值,存在不賦值
setex k6 5 v6 setex(set with expire)鍵秒值,k6的生命周期只有5s
getset k1 v11111 getset(先get再set),前提是該key已經存在
List 【單值多value,value可重復】 Stack/ArrayList
lpush list01 1 2 3 4 5 類似入棧
lpop list01 從棧上邊、隊列左邊讀 // 5
rpop list01 從棧下邊、隊列右邊讀 // 1
rpush list02 1 2 3 4 5 類似入隊列
lpop list02 從棧上邊、隊列左邊讀 // 1
rpop list02 從棧下邊、隊列右邊讀 // 5
lset list01 0 111 給指定下標賦值,也即是替換
linsert list01 before/after 1 java 在制定元素22之前/之后插入元素java
lrange list01 0 -1 從棧上邊、隊列左邊開始查詢集合list01 // 1 2 3 4 5
lindex list01 1 按照索引下標獲得元素(從棧上邊、隊列左邊讀)
llen list01 list01長度
lrem list01 2 3 刪除list01的2個3
ltrim list01 0 3 截取指定范圍的值后再賦值給key
rpoplpush list01 list02 rpoplpush 源列表 目的列表
性能總結:
- 它是一個字符串鏈表,left、right都可以插入添加;
- 如果鍵不存在,創建新的鏈表;
- 如果鍵已存在,新增內容;
- 如果值全移除,對應的鍵也就消失了。
- 鏈表的操作無論是頭和尾效率都極高,但假如是對中間元素進行操作,效率就很慘淡了。**
Set 【List單值多value,value不可以重復】 HashSet
sadd set01 1 1 2 3 4 4 添加set01= 1 2 3
smembers set01 查看set所有元素
sismember set01 1 查看1是否是set01內元素【0不是,1 是】
scard set01 獲取集合里面的元素個數
srem set01 1 刪除集合中元素
srandmember set01 3 從集合中隨機顯示3個整數
spop set01 集合中元素隨機出棧
smove set01 set02 3 作用是將key1里的某個值賦給key2
sdiff set01 set02 差集,屬于set01,不屬于set02
sinter set01 set02 交集
sunion set01 set02 并集
Hash【KV模式不變,但V是一個鍵值對】
hset user id 11 name zhupeng
hger user id
hgetall user
hdel user id
hexists user id 判斷key里面的某個值的key
hkeys user 查詢所有key值
hvals user 查詢所有value值
hlen user 查詢key長度
hincrby user id 2 value值加
hincrbyfloat user score 0.5
hsetnx user age 27 字段不存在則加入
Zset【在set基礎上,加一個score值。 之前set是k1 v1 v2 v3, 現在zset是k1 score1 v1 score2 v2】zadd zset01 60 v1 70 v2 80 v3 增加
zrange zset01 0 -1 查詢,不包括分數score
zrange zset01 0 -1 withscores 查詢,包括分數score
zrangebyscore zset01 60 90 查詢[60, 90]的value
zrangebyscore zset01 60 (90 查詢[60, 90)的value
zrangebyscore zset01 (60 (90 查詢(60, 90)的value
zrangebyscore zset01 60 90 limit 2 2 limit 開始下標步 多少步[Limit 作用是返回限制]
zrem zset01 v3 刪除某score下對應的value值
zcard zset01 查詢個數
zrank zset01 v1 查詢下標
zrevrank key values值,作用是逆序獲得下標值
zrevrange
zrevrangebyscore key 結束score 開始score
3 Redis配置文件
Redis 的配置文件位于 Redis 安裝目錄下,文件名為 redis.conf,說明如下:
1、Redis 默認不是以守護進程的方式運行,可以通過該配置項修改,使用 yes 啟用守護進程
daemonize no
2、當 Redis 以守護進程方式運行時,Redis 默認會把 pid 寫入 /var/run/redis.pid 文件,可以通過 pidfile 指定pidfile /var/run/redis.pid
3、指定 Redis 監聽端口,默認端口為 6379,【6379 在手機按鍵上 MERZ 對應的號碼,而 MERZ 取自意大利歌女 Alessia Merz 的名字】
port 6379
4、綁定的主機地址bind 127.0.0.1
5、當客戶端閑置多長秒后關閉連接,如果指定為 0 ,表示關閉該功能timeout 300
6、指定日志記錄級別,Redis 總共支持四個級別:debug、verbose、notice、warning,默認為 notice loglevel notice
7、日志記錄方式,默認為標準輸出,如果配置 Redis 為守護進程方式運行,而這里又配置為日志記錄方式為標準輸出,則日志將會發送給 /dev/nulllogfile stdout
8、設置數據庫的數量,默認數據庫為0,可以使用SELECT 命令在連接上指定數據庫iddatabases 16
9、Redis 默認配置文件中提供了三個條件:
save 900 1
save 300 10
save 60 10000
分別表示 900 秒(15 分鐘)內有 1 個更改,300 秒(5 分鐘)內有 10 個更改以及 60 秒內有 10000 個更改。
save <seconds> <changes>
指定在多長時間內,有多少次更新操作,就將數據同步到數據文件,可以多個條件配合
10、指定存儲至本地數據庫時是否壓縮數據,默認為 yes,Redis 采用 LZF 壓縮,如果為了節省 CPU 時間,可以關閉該選項,但會導致數據庫文件變的巨大rdbcompression yes
11、指定本地數據庫文件名,默認值為 dump.rdbdbfilename dump.rdb
12、指定本地數據庫存放目錄dir ./
13、設置當本機為 slave 服務時,設置 master 服務的 IP 地址及端口,在 Redis 啟動時,它會自動從 master 進行數據同步slaveof <masterip> <masterport>
14、當 master 服務設置了密碼保護時,slav 服務連接 master 的密碼masterauth <master-password>
15、設置 Redis 連接密碼,如果配置了連接密碼,客戶端在連接 Redis 時需要通過 AUTH 命令提供密碼,默認關閉requirepass foobaredredis修改登陸密碼config get requirepass # redis默認登陸密碼為空”“config set requirepass “123456” # 設置redis登陸密碼auth 123456 # 登陸
16、設置同一時間最大客戶端連接數,默認無限制,Redis 可以同時打開的客戶端連接數為 Redis 進程可以打開的最大文件描述符數,如果設置 maxclients 0,表示不作限制。當客戶端連接數到達限制時,Redis 會關閉新的連接并向客戶端返回 max number of clients reached 錯誤信息maxclients 128
17、指定 Redis 最大內存限制,Redis 在啟動時會把數據加載到內存中,達到最大內存后,Redis 會先嘗試清除已到期或即將到期的 Key,當此方法處理 后,仍然到達最大內存設置,將無法再進行寫入操作,但仍然可以進行讀取操作。Redis 新的 vm 機制,會把 Key 存放內存,Value 會存放在 swap 區maxmemory <bytes>
18、指定是否在每次更新操作后進行日志記錄,Redis 在默認情況下是異步的把數據寫入磁盤,如果不開啟,可能會在斷電時導致一段時間內的數據丟失。因為 redis 本身同步數據文件是按上面 save 條件來同步的,所以有的數據會在一段時間內只存在于內存中。默認為 noappendonly no
19、指定更新日志文件名,默認為 appendonly.aofappendfilename appendonly.aof
20、指定更新日志條件,共有 3 個可選值:
no:表示等操作系統進行數據緩存同步到磁盤(快)
always:表示每次更新操作后手動調用 fsync() 將數據寫到磁盤(慢,安全)
everysec:表示每秒同步一次(折中,默認值)
appendfsync everysec
21、指定是否啟用虛擬內存機制,默認值為 no,簡單的介紹一下,VM 機制將數據分頁存放,由 Redis 將訪問量較少的頁即冷數據 swap 到磁盤上,訪問多的頁面由磁盤自動換出到內存中(在后面的文章我會仔細分析 Redis 的 VM 機制)vm-enabled no
22、虛擬內存文件路徑,默認值為 /tmp/redis.swap,不可多個 Redis 實例共享vm-swap-file /tmp/redis.swap
23、將所有大于 vm-max-memory 的數據存入虛擬內存,無論 vm-max-memory 設置多小,所有索引數據都是內存存儲的(Redis 的索引數據 就是 keys),也就是說,當 vm-max-memory 設置為 0 的時候,其實是所有 value 都存在于磁盤。默認值為 0vm-max-memory 0
24、Redis swap 文件分成了很多的 page,一個對象可以保存在多個 page 上面,但一個 page 上不能被多個對象共享,vm-page-size 是要根據存儲的 數據大小來設定的,作者建議如果存儲很多小對象,page 大小最好設置為 32 或者 64bytes;如果存儲很大大對象,則可以使用更大的 page,如果不確定,就使用默認值vm-page-size 32
25、設置 swap 文件中的 page 數量,由于頁表(一種表示頁面空閑或使用的 bitmap)是在放在內存中的,,在磁盤上每 8 個 pages 將消耗 1byte 的內存。vm-pages 134217728
26、設置訪問swap文件的線程數,最好不要超過機器的核數,如果設置為0,那么所有對swap文件的操作都是串行的,可能會造成比較長時間的延遲。默認值為4vm-max-threads 4
27、設置在向客戶端應答時,是否把較小的包合并為一個包發送,默認為開啟glueoutputbuf yes
28、指定在超過一定的數量或者最大的元素超過某一臨界值時,采用一種特殊的哈希算法hash-max-zipmap-entries 64hash-max-zipmap-value 512
29、指定是否激活重置哈希,默認為開啟(后面在介紹 Redis 的哈希算法時具體介紹)activerehashing yes
30 指定包含其它的配置文件,可以在同一主機上多個Redis實例之間使用同一份配置文件,而同時各個實例又擁有自己的特定配置文件include /path/to/local.conf
4 Redis持久化【RDB、AOF】
持久化之RDB
RDB是什么?
RDB(Redis DataBase)在指定的時間間隔內將內存中的數據集快照寫入磁盤,也就是行話講的Snapshot快照,它恢復時是將快照文件直接讀到內存里。
過程:
(1)Redis會單獨創建(fork)一個子進程來進行持久化
(2)先將數據寫入到一個臨時文件中,待持久化過程都結束了,再用這個臨時文件替換上次持久化好的文件。
整個過程中,主進程是不進行任何IO操作的,這就確保了極高的性能。RDB配置?【SNAPSHOPPONG】#save 3600 1 # 15分鐘變動1次#save 300 100 # 5分鐘變動100次#save 60 10000 # 1分鐘變動1w次save save時只管保存,其它不管,全部阻塞。bgsave Redis會在后臺異步進行快照操作, 快照同時還可以響應客戶端請求。dbfilename dump.rdb 啟用rdb持久化存儲stop-writes-on-bgsave-error yes 如果配置成no,不在乎數據不一致或者有其他方法控制rdbcompression yes 是否啟動rdb文件壓縮算法rdbchecksum yes 存儲快照后,還可以讓redis使用CRC64算法進行數據校驗,大約會增加10%的性能小號,如果希望得到最優的性能提升,可以關閉該功能如何恢復?將備份文件 (dump.rdb) 移動到 redis 安裝目錄并啟動服務即可RDB優點:適合大規模的數據恢復對數據完整性和一致性要求不高
RDB缺點:Fork的作用是復制一個與當前進程一樣的進程,新進程的所有數據(變量、環境變量、程序計數器等) 數值都和原進程一致,大致2倍的膨脹性需要考慮。在一定間隔時間做一次備份,所以如果redis意外down掉的話,就會丟失最后一次快照后的所有修改總結RDB是一個非常緊湊的文件。RDB在保存RDB文件時父進程唯一需要做的就是fork出一個子進程,接下來的工作全部由子進程來做,父進程不需要再做其他I0操作,所以RDB持久化方式可以最大化redis的性能。與AOF相比,在恢復大的數據集的時候,RDB方式會更快一一些。數據丟失風險大。RDB需要經常fork子進程來保存數據集到硬盤上,當數據集比較大的時候fork的過程是非常耗時的嗎,可能會導致Redis在一些毫秒級不能回應客戶端請求。
持久化之AOF
AOF是什么?AOF(Append Only File)是以日志的形式來記錄每個寫操作,將Redis執行過的所有寫指令記錄下來(讀操作不記錄), 只許追加文件但不可以改寫文件,redis啟動之初會讀取該文件重新構建數據,換言之,redis 重啟的話就根據日志文件的內容將寫指令從前到后執行一次以完成數據的恢復工作。AOF配置【APPEND ONLY MODE】appendonly no # 默認noappendfilename "appendonly.aof" # 文件名appendfsync [always/everysec/no]always 同步持久化,redis每次發生數據改變都會被立即記錄到磁盤,性能較差但數據完整性最好everysec 默認推薦,異步操作,每秒記錄一次,最多損失1s的數據no 不進行持久化no-appendfsync-on-rewrite no 重寫時是否運用appendfsync,默認no即可,保證數據安全性auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mbrewrite
是什么:AOF采用文件追加方式,文件會越來越大。為避免出現此種情況,新增了重寫機制, 當AOF文件的大小超過所設定的閾值時,Redis就會啟動AOF文件的內容壓縮, 只保留可以恢復數據的最小指令集。可以使用命令bgrewriteaof
重寫原理AOF文件持續增長而過大時,會fork出一條新進程來將文件重寫(也是先寫臨時文件最后再rename), 遍歷新進程的內存中數據,每條記錄有一條的Set語句。重寫aof文件的操作,并沒有讀取舊的aof文件, 而是將整個內存中的數據庫內容用命令的方式重寫了一個新的aof文件,這點和快照有點類似.
觸發機制Redis會記錄上次重寫時的AOF大小,默認配置是當AOF文件大小是上次rewrite后大小的一倍且文件大于64M時觸發auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb 【一般3GB起步】AOF優點:每修改同步:appendfsync always 同步持久化 每次發生數據變更會被立即記錄到磁盤 性能較差但數據完整性比較好每秒同步:appendfsync everysec 異步操作,每秒記錄 如果一秒內宕機,有數據丟失不同步:appendfsync no 從不同步
AOF缺點:相同數據集的數據而言aof文件要遠大于rdb文件,恢復速度慢于rdbAof運行效率要慢于rdb,每秒同步策略效率較好,不同步效率和rdb相同總結AOF文件時一個只進行追加的日志文件Redis可以在AOF文件體積變得過大時,自動地在后臺對AOF進行重寫AOF文件有序地保存了對數據庫執行的所有寫入操作,這些寫入操作以Redis協議的格式保存,因此AOF文件的內容非常容易被人讀懂,對文件進行分析也很輕松對于相同的數據集來說,AOF文件的體積通常要大于RDB文件的體積根據所使用的fsync 策略,AOF的速度可能會慢于RDB
如何選擇?
1、RDB持久化方式能夠在指定的時間間隔內對數據進行快照存儲,AOF持久化方式記錄每次對服務器的寫操作,當服務器重啟時會重新執行這些命令來恢復原始數據,Redis還會對AOF文件進行重寫,避免文件體積過大。
2、建議同時開啟RDB、AOF持久化方式:redis會優先載入aof文件來恢復原始數據,因為通常情況下aof文件保存的數據集比rdb文件保存的數據集要完整。但是也不建議只用AOF,因為RDB更適合備份數據庫了,而AOF數據不斷變化,不好備份。
3、只做緩存:可以都不使用RDB、AOF性能建議因為RDB文件只做后備用途,建議只在slave上持久化RDB,而且重要15分鐘備份一次就夠了【只保留 save 900 1】如果啟用AOF,好處是在最壞情況下也只會丟失1s數據,啟動腳本簡單加載自己的aof文件就可以恢復,代價一是帶來了持續的IO,二是rewrite的最后將rewrite過程中產生的新數據寫到新文件會造成不可避免的阻塞,應當盡量減少rewrite的頻率,建議auto-aof-rewrite-min-size 設置為5G,默認超過原來的100%進行重寫。如果不啟用AOF,僅靠master-slave Replication實現高可用也可以,能節省一大筆IO、以及重寫rewrite帶來的系統波動,代價是如果master/slave同時倒掉,會丟失十幾分鐘的數據,啟動腳本也要比較兩個master/slave的RDB文件。
5 Redis事務(Transacttion)
是什么?可以一次執行多個命令,本質是一組命令的集合。一個事務中的所有命令都會序列化,按順序地串行化執行而不會被其它命令插入,不許加塞。能干嘛?一個隊列中,一次性、順序性、排他性的執行一系列命令。常用命令
命令 描述
MULTI 標記一個事務塊的開始。
WATCH key [key …] 監視一個(或多個) key,如果在事務執行之前這個key 被其他命令所改動,那么事務將被打斷。
UNWATCH 取消 WATCH 命令對所有 key 的監視。
EXEC 執行所有事務塊內的命令。
DISCARD 取消事務,放棄執行事務塊內的所有命令。
常見CASE
case5:watch監控
WATCH 使得 EXEC 命令需要有條件地執行: 事務只能在所有被監視鍵都沒有被修改的前提下執行, 如果這個前提不能滿足的話,事務就不會被執行。
Watch指令,類似樂觀鎖,事務提交時,如果Key的值已被別的客戶端改變, 比如某個list已被別的客戶端push/pop過了,整個事務隊列都不會被執行
通過WATCH命令在事務執行之前監控了多個Keys,倘若在WATCH之后有任何Key的值發生了變化, EXEC命令執行的事務都將被放棄,同時返回Nullmulti-bulk應答以通知調用者事務執行失敗。
PS:悲觀鎖/樂觀鎖/CAS(Check And Set)
悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關系型數據庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。【高一致性,低并發】
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。樂觀鎖適用于多讀的應用類型,這樣可以提高吞吐量。樂觀鎖策略:提交版本必須大于記錄當前版本才能執行更新。【高并發,低一致性】
CAS:信用卡可用余額和欠額案例
事務特性單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。沒有隔離級別的概念:隊列中的命令沒有提交之前都不會實際的被執行,因為事務提交前任何指令都不會被實際執行, 也就不存在”事務內的查詢要看到事務里的更新,在事務外查詢不能看到”這個讓人萬分頭痛的問題不保證原子性:redis同一個事務中如果有一條命令執行失敗,其后的命令仍然會被執行,沒有回滾不遵循傳統的ACID中的AI
6 Redis主從復制、讀寫分離
是什么?也就是我們所說的主從復制,主機數據更新后根據配置和策略,自動同步到備機的master/slaver機制,Master以寫為主,Slave以讀為主,主要負責讀寫分離、容災恢復。怎么玩?slaveof 主庫IP 主庫端口 【配從(庫)不配主(庫)】準備工作:啟動多個Redis服務器,部分配置文件參數修改如下:
daemonize yes、pid文件名字、port指定端口、logfile日志名稱、dump.rdb配置文件名字
case1:一主二仆【中心化架構】
常見問題
1、slave1、slave2是從頭開始復制還是從切入點開始復制?比如從k4進來,那之前的123是否也可以復制?
答:從頭開始復制;123也可以復制
2、從機是否可以寫?set可否?
答:從機不可寫,不可set,主機可寫
3、主機shutdown后情況如何?從機是上位還是原地待命
答:從機還是原地待命(咸魚翻身,還是咸魚)
4、主機又回來了后,主機新增記錄,從機還能否順利復制?
答:能
5、其中一臺從機down后情況如何?依照原有它能跟上大部隊嗎?
答:不能跟上,每次與master斷開之后,都需要重新連接,除非你配置進redis.conf文件(具體位置:redis.conf搜尋#### REPLICATION ####)```
case2:薪火相傳【去中心化架構】
上一個Slave可以是下一個slave的Master,Slave同樣可以接收其他 slaves的連接和同步請求,那么該slave作為了鏈條中下一個的master, 可以有效減輕master的寫壓力(奴隸的奴隸還是奴隸),中途變更轉向會清除之前的數據,重新建立拷貝最新的
slaveof 新主庫IP 新主庫端口
case3:反客為主
使當前數據庫停止與其他數據庫的同步,轉成主數據庫,形成一個中心點
SLAVEOF no one
case4:哨兵模式(sentinel)
一組sentinel能同時監控多個master,反客為主的自動版,能夠后臺監控主機是否故障,如果故障了根據投票數自動將從庫轉換為主庫
怎么玩(使用步驟)
1、調整結構,6379帶著6380、6381
2、新建sentinel.conf文件,名字絕不能錯
3、配置哨兵,s填寫內容
sentinel monitor host 127.0.0.1 6379 1
數字1,表示主機掛掉后salve投票看讓誰接替成為主機,得票數多少后成為主機
4、啟動哨兵
redis-sentinel /sentinel.conf(上述目錄依照各自的實際情況配置,可能目錄不同)
5、正常主從演示
6、原有的master掛了
7、投票新選,重新主從繼續開工,info replication查查看問題:如果之前掛了的master重啟回來,會不會雙master沖突?
答: 不會,原master,變成slave