什麼是單機 MySQL?c++
在90年代,一個網站的訪問量通常都不大,用單個數據庫徹底能夠輕鬆應付。面試
Memcached(緩存)+MySQL+垂直拆分redis
MySQL 主從讀寫分離算法
因爲數據庫的寫入壓力增長,Memcached只能緩解數據庫的讀取壓力。讀寫集中在一個數據庫上讓數據庫不堪重負,大部分網站開始使用主從複製技術來達到讀寫分離,以提升讀寫性能和讀庫的可擴展性。MySQL 的 Master-Slave 模式成爲這個時候的網站標配了。數據庫
分表分庫+水平拆分+MySQL集羣緩存
在 Memcached 的高速緩存,MySQL 的主從複製,讀寫分離的基礎之上,這時 MySQL 主庫的寫壓力開始出現瓶頸,而數據量的持續猛增,因爲 MyISAM 使用表鎖,在高併發下會出現嚴重的鎖問題,大量的高併發 MySQL 應用開始使用 InnoDB 引擎代替MyISAM。安全
同時,開始流行使用分表分庫來緩解寫壓力和數據增加的擴展問題。這個時候,分表分庫成了一個熱門技術,是面試的熱門問題也是業界討論的熱門技術問題。也就在這個時候,MySQL 推出了還不太穩定的表分區,這也給技術實力通常的公司帶來了但願。雖然 MySQL 推出了 MySQL Cluster 集羣,但性能也不能很好知足互聯網的要求,只是在高可靠性上提供了很是大的保證。服務器
MySQL 的擴展問題網絡
MySQL 數據庫也常常存儲一些大文本字段,致使數據庫表很是的大,在作數據庫恢復的時候就致使很是的慢,不容易快速恢復數據庫。好比1000萬 4KB 大小的文本就接近 40GB 的大小,若是能把這些數據從 MySQL 省去,MySQL 將變得很是的小。關係數據庫很強大,可是它並不能很好的應付全部的應用場景。MySQL 的擴展性差(須要複雜的技術來實現),大數據下IO壓力大,表結構更改困難,正是當前使用 MySQL 的開發人員面臨的問題。多線程
泛指非關係數據庫,隨着互聯網 Web2.0 網站的興起,傳統的關係數據庫在應付 Web2.0,特別是超大規模、高併發的 SNS 類型的純動態網站已經力不從心,而非關係數據庫憑藉自身的特色獲得了迅猛的發展。NoSQL 數據庫的產生就是爲了解決大規模數據集合多重數據種類帶來的挑戰,尤爲是大數據應用難題,包括超大規模數據的存儲。
大數據時代的 3V:
海量 Volume
多樣 Variety
實時 Velocity
互聯網需求的 3 高:
高併發
高可擴
高性能
C:強一致性(Consistency)
A:可用性(Availability)
P:分區容錯性(Partition tolerance)
CAP 的理論就是說在分佈式存儲系統中,最多隻能實現上面的兩點,而因爲當前的網絡硬件確定會出現延遲丟包問題,因此分區容忍性是咱們必須實現的。
因此咱們只能從一致性和可用性之間進行權衡,沒有 NoSQL 可以同時保證三點。
CA:傳統 Oracle 數據庫
AP:大多數網站架構的選擇
CP:Redis、Mongodb
基本可用(Basically Available)
軟狀態(Soft state)
最終一致(Eventually consistent)
它的思想是經過讓系統放鬆對某一時刻數據一致性的要求來保證總體伸縮性和性能,緣由就是大型系統每每因爲地域分佈和極高性能的要求,不可能採用分佈式事務來完成這些指標,要想得到這些指標,咱們必須採用一種方式來完成,這裏 BASE 就是解決這個問題的辦法。
由多臺計算機和通訊軟件經過計算機網絡鏈接組成,分佈式系統是創建在網絡之上的軟件系統,正是由於軟件的特性,因此分佈式系統具備高度的內聚性和透明性,所以,網絡和分佈式系統之間的區別更多的在於高層軟件,而不是硬件,分佈式系統能夠應用在不一樣的平臺。
分佈式和集羣的區別:
分佈式:在多臺不一樣的機器上部署不一樣的服務,它們之間使用 Rpc/Rml 之間通訊和調用,對外提供服務和和組內協做。
集羣:在多臺不一樣的機器上部署相同的服務,經過分佈式調用軟件進行統一的調度,對外提供服務和訪問。
開源、底層採用 C語言、遵照 BSD 協議。
高性能 key/value 分佈式內存數據庫,基於內存運行。
支持持久化的 NoSQL 數據庫。
和其餘 NoSQL 相比,Redis 有三個特色:
支持數據的持久化,能夠將內存中的數據持久化到磁盤中,重啓以後能夠再次使用。
不只僅支持 key/value,還提供對 list、set、zset、hash 等數據類型的支持。
支持主從備份。
將 Redis 安裝包移動到 opt 目錄下。
經過 tar -zxvf redis-3.0.4.tar.gz 解壓。
進入解壓後的目錄執行 make,假如沒有安裝 gcc,就執行 yum install gcc-c++ 命令,而後運行 make distclean 以後執行 make。
make install。
Redis 是一個單進程的。
它有16個數據庫,默認爲0號數據庫。
SELECT:切換數據庫。
DBSIZE:查看當前數據庫的 key 的數量。
FLUSHDB:清空當前庫。
FLUSHALL:清空全部庫。
贊成密碼管理,16個庫都是相同密碼。
默認端口是 6379。
keys * 查看當前庫的全部 key
exists key 判斷 key 是否存在
move key db 將當前庫的某個 key 移到其餘庫
expire key 設置 key 的過時時間
ttl key 查看 key 的剩餘使用實現
type key 查看 key 的類型
String 是 Redis 最基本的類型,一個 key 對應一個 vlaue,String 是二進制安全的,因此它能夠包含全部數據,value 最多能夠包含512M數據。
// 設置一個值 SET k1 v1 // 獲取key對應的value GET k1 // 添加一個value APPEND k1 // 查看key對應的value的長度 STRLEN k1 // 每次增長1 INCR k1 // 每次減小1 DECR k1 // 每次增長2 INCRBY k1 2 // 每次減小2 DECRBY k1 2 // 獲取範圍內值 GETRANGE k1 0 2 // 設置鍵存活的時間 SETEX k1 20 v1 // 設置時判斷是否存在key,若是存在就不作改變 SETNX k1 v1 // 同時設置多個值,若是鍵存在,修改值 MSET k1 v1 k2 v2 // 同時獲取多個值 MGET k1 k2 // 同時設置多個值,若是存在鍵,執行失敗 MSETNX k1 v1 k2 v2 // 設置並返回設置的value getset k1 v1
是一個鍵值對集合,相似與 Java 裏的 Map<String, Object>。
KV 模式不變,但 V 是一個鍵值對。
// 設置一個user,user的id屬性是11 HSET user id 1 // 獲取 user 的 id 屬性 HGET user id // 設置一個user的多個值 HMSET user name kernel age 18 // 獲取多個屬性 HMGET user name age // 獲取全部屬性 HGETALL // 刪除user中的name屬性 HDEL user name // 查看user有幾個屬性 HLEN user // 查看user中是否存在name屬性 HEXISTS user name // 查看user的全部key HKEYS user // 查看user的全部value HVALS user // 自增2 HINCRBY user age 2 // 增長小數 HINCRBYFLOAT user score 0。5 // 不存在才能往裏放 HSETNX user email kernel@163。com
簡單的字符串列表,按照插入順序排序,底層是一個鏈表。
單鍵多值。
它是一個字符串鏈表,能夠從左右兩邊添加。
若是鍵不存在,建立鏈表,鍵存在,增長值,彈出全部值,鍵就失效了。
操做頭尾效率高,中間元素效率低。
// 從左邊向key中壓入值 LPUSH list01 1 2 3 4 5 // 從右邊向 key 中壓入值 RPUSH list02 1 2 3 4 5 // 從左邊查看範圍內的值 Lrange list01 0 -1 // 從左邊彈棧 LPOP // 從右邊彈棧 RPOP // 查看指定索引的值 LINDEX list01 2 // 查看指定key的長度 LLEN list01 // 從key中從左邊刪除3個3 LREM list01 3 3 LTRIM list01 0 3 截取0-3賦值給key // 從前面的key右邊彈出一個值賦值給後面key RPOPLPUSH list01 list02
String 類型的無序集合,採用 HashTable 實現的。
單鍵多值。
// 添加多個值,重複值不添加 SADD set01 1 2 3 4 5 1 2 3 4 5 // 查看set01的值 SMEMBERS set01 // 查看set01是否存在5 SISMEMBER set01 5 // 查看set01的元素個數 SCARD set01 // 刪除set01中的3 SREM set01 3 // 從set01中隨機取3個數 SRANDMEMBER set01 3 // 隨機彈棧 SPOP set01 // 將 set01 中的5 移動到 set02 中 SMOVE set01 set02 5 // 差集,在set01不在set02中的值 SDIFF set01 set02 // 交集 SINTER set01 set02 // 並集 SUNION set01 set02
set 和 zset 的異同點:
相同點:String 類型元素的集合,不容許重複的成員。
不一樣點:每一個元素都會關聯一個 double 類型的分數。
// 設置值 ZADD zset01 60 v1 70 v2 80 v3 90 v4 100 v5 // 範圍內取值,withscores表示包含score ZRANGE zset01 0 -1 // 範圍內取值包括score // 區間內取值,(表示不包含,limit 開始下標,走多少步 ZRANGEBYSCORE zset01 60 80 // 刪除某score對應的value ZREM zset01 v4 // 查看zset01的個數 ZCARD zset01 // 查看區間內個數 ZCOUNT zset01 60 90 // 取下標 ZBANK zset01 60 // 取v4對應的值 ZSCORE zset01 v4 // 逆序得到v3對應的下標 ZREVRANK zset01 v3 // 逆序取範圍內的值 ZREVRANGE zset01 0 -1 // 逆序區間內取值 ZREVRANGEBYSCORE zset01 90 60
1k => 1000 bytes
1kb => 1024 bytes
1m => 1000000 bytes
1mb => 10241024 bytes
1g => 1000000000 bytes
1gb => 10241024*1024 bytes
能夠經過 includes 包含,redis.conf 能夠做爲總閘,包含其餘配置。
daemonize:配置做爲守護進程運行。
pidfile:如之後臺進程運行,Redis 將會把 pid 寫入到 /var/run/redis.pid 文件,能夠指定文件。
bind 127.0.0.1:綁定的主機地址,若是想所有訪問不作限制的話,全爲0.0.0.0。
timeout 300:當客戶端閒置多長時間後關閉鏈接,若是指定爲0,表示關閉該功能。
loglevel verbose:日誌等級,有 debug、verbose、notice、warning,默認是 verbose。
logfile "" :日誌文件保存位置,若是配置Redis爲守護進程方式運行,而這裏又配置爲日誌記錄方式爲標準輸出,則日誌將會發送給 /dev/null。
tcp-keepalive:單位爲秒,若是設置爲0,則不會進行 Keepalive 檢測,建議設置成60。
syslog-enabled:是否把日誌輸出到 syslog 中。
syslog-ident:指定 syslog 裏的日誌標誌。
syslog-facility:指定 syslog 設備,值能夠是USER或 LOCAL0-LOCAL7。
Save 默認出廠設置若是1分鐘寫了10000次、5分鐘寫了10次、15分鐘寫了1次都會觸發備份,若是想禁用 RDB 持久化策略,將 save 設爲 save ""。
stop-writes-on-bgsave-error:若是配置成 no,表示你不在意數據不一致或者有其餘的手段發現和控制。
rdbcompression:對於存儲到磁盤中的快照,能夠設置是否進行壓縮存儲。若是是的話,Redis 會採用 LZF 算法進行壓縮。若是你不想消耗 CPU 來進行壓縮的話,能夠設置爲關閉此功能。
rdbchecksum:在存儲快照後,還可讓 Redis 使用 CRC64 算法來進行數據校驗,可是這樣作會增長大約10%的性能消耗,若是但願獲取到最大的性能提高,能夠關閉此功能。
dbfilename
dir
CONFIG SET requirepass 123456 將密碼改成 123456,默認爲空,設置後,執行任何命令以前必須執行 auth 123456。
maxclients 最大鏈接客戶端數量
maxmemory 設置 Redis 可使用的內存量。一旦到達內存使用上限,Redis 將會試圖移除內部數據。
maxmemory-policy :
volatile-lru:使用 LRU 算法移除 key,只對設置了過時時間的鍵。
allkeys-lru:使用 LRU 算法移除 key。
volatile-random:在過時集合中移除隨機的 key,只對設置了過時時間的鍵。
allkeys-random:移除隨機的 key。
volatile-ttl:移除那些 TTL 值最小的 key,即那些最近要過時的 key。
noeviction:不進行移除。針對寫操做,只是返回錯誤信息。
maxmemory-samples:設置樣本數量,LRU 算法和最小 TTL 算法都並不是是精確的算法,而是估算值,因此你能夠設置樣本的大小,Redis 默認會檢查這麼多個 key 並選擇其中 LRU 的那個。
appendonly:配置 AOF 持久化。
appendfilename:持久化文件名。
appendfsync:同步
always:同步持久化 每次發生數據變動會被當即記錄到磁盤 性能較差但數據完整性比較好
everysec:出廠默認推薦,異步操做,每秒記錄 若是一秒內宕機,有數據丟失。
no:從不一樣步。
no-appendfsync-on-rewrite:重寫時是否能夠運用 Appendfsync,用默認 no 便可,保證數據安全性。
auto-aof-rewrite-min-size:設置重寫的基準值。
參數說明
redis.conf 配置項說明以下:
Redis 會單首創建(fork)一個子進程來進行持久化,會先將數據寫入到一個臨時文件中,待持久化過程都結束了,再用這個臨時文件替換上次持久化好的文件。整個過程當中,主進程是不進行任何 IO 操做的,這就確保了極高的性能,若是須要進行大規模數據的恢復,且對於數據恢復的完整性不是很是敏感,那 RDB 方式要比 AOF 方式更加的高效。RDB 的缺點是最後一次持久化後的數據可能丟失。
RDB 保存的是 dump.rdb 文件。
做用是複製一個與當前進程同樣的進程,新進程的全部數據都和原進程同樣,可是是一個新的進程,並做爲原進程的子進程。
在 redis.conf 文件中的 SNAPSHOTTING 下面。
按照配置觸發。
執行 save 或者 bgsave,save 只管保存,其餘所有堵塞,bgsave 是後臺異步進行快照,還能夠接收用戶請求。
執行 flushall 命令也會觸發,可是因爲執行了該命令清空全部庫的數據,全部 dump.rdb 文件中是空的。
適合大規模的數據恢復。
對數據完整性和一致性要求不高。
在必定間隔時間作一次備份,因此若是 Redis 意外 down 掉的話,就會丟失最後一次快照後的全部修改。
fork 的時候,內存中的數據被克隆了一份,大體2倍的膨脹性須要考慮。
動態中止:全部中止 RDB 保存規則的方法:redis-cli config set save ""。
RDB 是一個很是緊湊的文件,在保存 RDB 文件的時候父進程會 fork 出一個子進程,接下來所有工做由子進程負責,父進程不須要作任何 IO 操做,全部 RDB 方式能夠最大化 Redis 的性能,與 AOF 相比,它更適合作大規模的數據回覆,對數據完整性、一致性要求不高,數據丟失風險高,由於該方式 fork 子進程來持久化,當數據量大的時候,fork 的過程很是耗時,可能會致使在毫秒級上 Redis 不能響應客戶端請求。
以日誌的形式來記錄每一個寫操做,將 Redis 執行過的全部寫指令記錄下來(讀操做不記錄),只許追加文件但不能夠改寫文件,Redis 啓動之初會讀取該文件從新構建數據,換言之,Redis 重啓的話就根據日誌文件的內容將寫指令從前到後執行一次以完成數據的恢復工做。
AOF 保存的是 appendonly.aof 文件。
APPEND ONLY MODE,將 appendonly no 改成 yes。
正常恢復:
將有數據的 AOF 文件複製一份保存到對應目錄 (config get dir)。
恢復:重啓 Redis 而後從新加載。
異常恢復:
備份被寫壞的 AOF 文件。
redis-check-aof --fix 文件名 進行修復。
恢復:重啓 Redis 而後從新加載。
AOF 採用文件追加方式,隨着時間的推移文件愈來愈大,爲了不出現這種狀況,新增了重寫機制,當 AOF 文件超過預先設定的閾值時,Redis 就會啓動內容壓縮,只保留能夠恢復數據的最小指令集,可使用命令 bgrewriteaof。
原理:
AOF 文件持續增加而過大時,會 fork 出一條新進程來將文件重寫,遍歷新進程的內存中數據,每條記錄有一條的Set語句。重寫 AOF 文件的操做,並無讀取舊的 AOF 文件,而是將整個內存中的數據庫內容用命令的方式重寫了一個新的 AOF 文件,這點和快照有點相似。
觸發機制:
Redis 會記錄上次重寫時的 AOF 大小,默認配置是當 AOF 文件大小是上次 rewrite 後大小的一倍且文件大於64M 時觸發。
每秒同步:appendfsync always 同步持久化每次發生數據變動會被當即記錄到磁盤,性能較差但數據完整性比較好。
每修改同步:appendfsync everysec 異步操做,每秒記錄,若是一秒內宕機,有數據丟失。
不一樣步:appendfsync no 從不一樣步。
相同數據集的數據而言 AOF 文件要遠大於 RDB 文件,恢復速度慢於 RDB。
AOF 文件是一個只進行追加的日誌文件,Redis 能夠在 AOF 文件體積過大時進行重寫,AOF 文件有序的保存了對數據的寫操做,這些寫操做以 Redis 協議被很好的保存,所以,AOF 文件的內容很是容易被讀懂,對文件的分析也很容易。對於相同的數據集來講,AOF 的體積一般要大於 RDB,根據所使用的 fsync 策略,AOF 的速度要慢於 RDB。
RDB 持久化方式可以在指定的時間間隔能對你的數據進行快照存儲。
AOF 持久化方式記錄每次對服務器寫的操做,當服務器重啓的時候會從新執行這些命令來恢復原始的數據,AOF 命令以 Redis 協議追加保存每次寫的操做到文件末尾。Redis 還能對 AOF 文件進行後臺重寫,使得 AOF 文件的體積不至於過大。
若是你只但願你的數據在服務器運行的時候存在,你也能夠不使用任何持久化方式。
在這種狀況下,當 Redis 重啓的時候會優先載入 AOF 文件來恢復原始的數據,由於在一般狀況下 AOF 文件保存的數據集要比 RDB 文件保存的數據集要完整。
RDB 的數據不實時,同時使用二者時服務器重啓也只會找 AOF 文件。
那要不要只使用 AOF 呢?
建議不要,由於 RDB 更適合用於備份數據庫 (AOF在不斷變化很差備份),快速重啓,並且不會有 AOF 可能潛在的 bug,留着做爲一個萬一的手段。
由於 RDB 文件只用做後備用途,建議只在 Slave 上持久化 RDB 文件,並且只要15分鐘備份一次就夠了,只保留 save 900 1 這條規則。
若是 Enalbe AOF,好處是在最惡劣狀況下也只會丟失不超過兩秒數據,啓動腳本較簡單隻 load 本身的 AOF 文件就能夠了。代價一是帶來了持續的 IO,二是 AOF rewrite 的最後將 rewrite 過程當中產生的新數據寫到新文件形成的阻塞幾乎是不可避免的。只要硬盤許可,應該儘可能減小 AOF rewrite 的頻率,AOF 重寫的基礎大小默認值 64M 過小了,能夠設到 5G 以上。默認超過原大小100%大小時重寫能夠改到適當的數值。
若是不 Enable AOF ,僅靠 Master-Slave Replication 實現高可用性也能夠。能省掉一大筆 IO 也減小了 rewrite 時帶來的系統波動。代價是若是 Master/Slave 同時倒掉,會丟失十幾分鐘的數據,啓動腳本也要比較兩個 Master/Slave中的 RDB 文件,載入較新的那個。新浪微博就選用了這種架構。
悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認爲別人會修改,因此每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會 block 直到它拿到鎖。傳統的關係型數據庫裏邊就用到了不少這種鎖機制,好比行鎖,表鎖等,讀鎖,寫鎖等,都是在作操做以前先上鎖。
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認爲別人不會修改,因此不會上鎖,可是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣能夠提升吞吐量,樂觀鎖策略:提交版本必須大於記錄當前版本才能執行更新。
DISCARD 取消事務,放棄執行事務塊內的全部命令
EXEC 執行全部事務塊內的命令
MULTI 標記一個事務塊的開始
UNWATCH 取消 WATCH 命令對全部 key 的監視
WATCH key [key...] 監視一個或多個 key,若是在事務執行以前這個 key 被其餘命令所改動,那麼事務將被打斷
正常執行:
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> set k2 v22 QUEUED 127.0.0.1:6379> set k3 v33 QUEUED 127.0.0.1:6379> EXEC 1) OK 2) OK
放棄事務:
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> set k3 v3 QUEUED 127.0.0.1:6379> DISCARD OK 127.0.0.1:6379> get k3 "v33"
全體連坐:
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> set k3 v3 QUEUED 127.0.0.1:6379> setget k2 v2 (error) ERR unknown command 'setget' 127.0.0.1:6379> EXEC (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get k3 "v33"
怨頭債主:
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> INCR k2 QUEUED 127.0.0.1:6379> set k3 v3 QUEUED 127.0.0.1:6379> EXEC 1) OK 2) (error) ERR value is not an integer or out of range 3) OK
WATCH 監控:
對某個 key 監控以後,若是有別的客戶端將這個 key 修改,則事務執行失敗。
UNWATCH 的做用是放棄監控。
一旦執行 EXEC 不管成功與否全部監控所都被取消掉了。
WATCH 命令至關於樂觀鎖,事務提交時,若是 key 已經被修改,整個事務隊列將執行失敗,若是監視了多個 key,只要其中有一個 key 被修改,則整個隊列執行失敗,同時返回 Nullmulti-bulk 通知調用者事務執行失敗。
開啓:以MULTI開始一個事務
入隊:將多個命令入隊到事務中,接到這些命令並不會當即執行,而是放到等待執行的事務隊列裏面
執行:由EXEC命令觸發事務
單獨的隔離操做:事務中的全部命令都會序列化、按順序地執行。事務在執行的過程當中,不會被其餘客戶端發送來的命令請求所打斷。
沒有隔離級別的概念:隊列中的命令沒有提交以前都不會實際的被執行,由於事務提交前任何指令都不會被實際執行,也就不存在事務內的查詢要看到事務裏的更新,在事務外查詢不能看到」這個讓人萬分頭痛的問題。
不保證原子性:Redis 同一個事務中若是有一條命令執行失敗,其後的命令仍然會被執行,沒有回滾。
進程間的一種消息通訊模式:發送者(pub)發送消息,訂閱者(sub)接收消息。
首先須要訂閱者訂閱才能夠收到消息,SUBSCRIBE c1 c2 c3。
而後發佈者向頻道發送消息,訂閱者就能夠收到了,好比 PUBLISH c3 word。
訂閱者訂閱頻道時候還可使用通配符,例如 SUBSCRIBE new*。
這樣不管向 new1 頻道仍是 new2 頻道發送消息訂閱者均可以收到。
也就是咱們所說的主從複製,主機數據更新後根據配置和策略,自動同步到備機的 Master/Slaver 機制,Master 以寫爲主,Slave 以讀爲主。
讀寫分離
容災恢復
配從不配主。
從庫配置:slaveof 主庫 IP 主庫端口,沒次與主庫斷開鏈接後,都須要從新鏈接,除非寫入到配置文件中。能夠經過 info replication 查看當前數據庫的配置。
經常使用三種方式:
一主二僕:
一個 Master 配置兩個 Slave。Salve 只能讀,不能夠寫,當 Master 掛掉,Salve 原地等待,Master 恢復後,自動鏈接,若是 Slave 掛掉,須要手動從新鏈接。
薪火相傳:Master 配置一個 Slave,Slave 能夠是下一個 Salve 的 Master,有效減輕 Master 的壓力。
反客爲主:經過 Salve no one 使當前數據庫中止與其餘數據庫的同步,轉成 Master。
Slave 啓動成功鏈接到 Master 後會發送一個 sync 命令。
Master 接到命令啓動後臺的存盤進程,同時收集全部接收到的用於修改數據集命令,在後臺進程執行完畢以後,Master 將傳送整個數據文件到 Slave,以完成一次徹底同步。
全量複製:而 Slave 服務在接收到數據庫文件數據後,將其存盤並加載到內存中。
增量複製:Master 繼續將新的全部收集到的修改命令依次傳給 Slave,完成同步。
可是隻要是從新鏈接 Master,一次徹底同步(全量複製)將被自動執行。
反客爲主的自動版,監控主庫是否掛掉,若是掛掉自動選出一個從庫做爲主庫。
新建 sentinel.conf 文件,配置哨兵, sentinel monitor 被監控數據庫名字 127.0.0.1 6379 1,1表示主機掛掉 Salve 投票看誰能當主機,得票多的當主機。
啓動哨兵,redis-sentinel sentinel.conf 。
若是原有的 Master 掛掉,會自動選舉出一個 Master,當 Master 恢復後,原 Master 做爲 新 Master 的 Salve。
缺點:因爲全部的寫操做都是先在 Master 上操做,而後同步更新到 Slave 上,因此從 Master 同步到 Slave 機器有必定的延遲,當系統很繁忙的時候,延遲問題會更加嚴重,Slave 機器數量的增長也會使這個問題更加嚴重。
開放端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent
配置阿里雲安全組規則
查看開放端口
firewall-cmd --zone=public --list-ports
commons-pool-1.6.jar
jedis-2.1.0.jar
獲取 Jedis 實例須要從 JedisPool 中獲取,用完要返還給 JedisPool,出錯也要返還給 JedisPool。
自定義 JedisPoolUtil
public class JedisPoolUtil { // 保證此變量對全部的線程的可見性,禁止指令重排序優化 private static volatile JedisPool jedisPool = null; // 私有化構造方法 private JedisPoolUtil() { } // 提供池子,採用雙重檢驗鎖機制 public static JedisPool getJedisPool() { if (null == jedisPool) { synchronized (JedisPool.class) { if (null == jedisPool) { JedisPoolConfig poolConfig = new JedisPoolConfig(); // 最大鏈接數 poolConfig.maxActive = 1000; // 最大等待鏈接數 poolConfig.maxIdle = 32; // 最大等待時間 poolConfig.setMaxWait(100 * 1000); // 得到實例時是否檢測可用性 poolConfig.setTestOnBorrow(true); jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379); } } } return jedisPool; } public static void release(JedisPool jedisPool, Jedis jedis) { if (jedis != null) { jedisPool.returnResourceObject(jedis); } } }
雙重檢驗鎖是對同步塊加鎖的方法,爲何教雙重檢驗呢,那是由於有兩次判空操做。
爲什麼在同步塊外面判空?
爲了提升性能,若是去掉同步塊外面判空,只要調用此方法,都會拿到一個靜態內部鎖,下降了效率,因此在外面加判空,下降了同步塊的執行次數。
爲何還在同步塊內判空呢?
可能會有多個線程同時進入同步塊外面的判空,可是有線程先一步拿到了對象,若是再也不內部判空,可能會生成多個實例。
必定要使用 volatile 修飾靜態變量,不然因爲多線程,仍是會建立多個實例。
JedisPool 的配置參數大部分是由 JedisPoolConfig 的對應項來賦值的。
maxActive:控制一個 pool 可分配多少個 jedis 實例,經過 pool.getResource() 來獲取,若是賦值爲-1,則表示不限制;若是 pool 已經分配了 maxActive 個 jedis 實例,則此時 pool 的狀態爲 exhausted。
maxIdle:控制一個 pool 最多有多少個狀態爲 idle(空閒)的 jedis 實例。
whenExhaustedAction:表示當 pool 中的 jedis 實例都被 allocated 完時,pool 要採起的操做,默認有三種:
WHEN_EXHAUSTED_FAIL --> 表示無 jedis 實例時,直接拋出 NoSuchElementException。
WHEN_EXHAUSTED_BLOCK --> 則表示阻塞住,或者達到 maxWait 時拋出 JedisConnectionException。
WHEN_EXHAUSTED_GROW --> 則表示新建一個 jedis 實例,也就說設置的 maxActive 無用。
maxWait:表示當 borrow 一個 jedis 實例時,最大的等待時間,若是超過等待時間,則直接拋 JedisConnectionException。
testOnBorrow:得到一個 jedis 實例的時候是否檢查鏈接可用性(ping());若是爲true,則獲得的 jedis 實例均是可用的。
testOnReturn:return 一個 jedis 實例給 pool 時,是否檢查鏈接可用性(ping())。
testWhileIdle:若是爲 true,表示有一個 idle object evitor 線程對 idle object 進行掃描,若是 validate 失敗,此 object 會被從 pool 中 drop 掉;這一項只有在 timeBetweenEvictionRunsMillis 大於0時纔有意義。
timeBetweenEvictionRunsMillis:表示 idle object evitor 兩次掃描之間要sleep的毫秒數。
numTestsPerEvictionRun:表示 idle object evitor 每次掃描的最多的對象數。
minEvictableIdleTimeMillis:表示一個對象至少停留在 idle 狀態的最短期,而後才能被 idle object evitor 掃描並驅逐;這一項只有在 timeBetweenEvictionRunsMillis 大於0時纔有意義。
softMinEvictableIdleTimeMillis:在 minEvictableIdleTimeMillis 基礎上,加入了至少 minIdle 個對象已經在pool裏面了。若是爲-1,evicted 不會根據 idle time 驅逐任何對象。若是 minEvictableIdleTimeMillis>0,則此項設置無心義,且只有在timeBetweenEvictionRunsMillis 大於0時纔有意義。
lifo:borrowObject 返回對象時,是採用 DEFAULT_LIFO(last in first out,即相似cache的最頻繁使用隊列),若是爲 False,則表示 FIFO 隊列。
其中 JedisPoolConfig 對一些參數的默認設置以下:testWhileIdle=trueminEvictableIdleTimeMills=60000timeBetweenEvictionRunsMillis=30000numTestsPerEvictionRun=-1