您好,登錄后才能下訂單哦!
是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集并集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎上實現了master-slave(主從)同步。
優點:
(1)Redis支持數據的持久化,可以將內存中的數據保持在磁盤中,重啟的時候可以再次加載進行使用
(2)Redis不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲
(3)Redis支持數據的備份,即master-slave模式的數據備份
相關應用:
(1)內存存儲和持久化:redis支持異步將內存中的數據寫到硬盤上,同時不影響繼續服務
(2)取最新N個數據的操作,如:可以將最新的10條評論的ID放在Redis的List集合里面
(3)模擬類似于HttpSession這種需要設定過期時間的功能
(4)發布、訂閱消息系統
(5)定時器、計數器
Redis的安裝
下載
下載[redis-5.0.0][http://download.redis.io/releases/redis-5.0.0.tar.gz]放到centos系統中
安裝
解壓redis壓縮文件,在解壓目錄執行make && make install
安裝目錄查看
查看默認安裝目錄:usr/local/bin
redis-benchmark:性能測試工具
redis-check-aof:修復有問題的AOF文件
redis-check-dump:修復有問題的dump.rdb文件
redis-cli:客戶端,操作入口
redis-sentinel:redis集群使用
redis-server:Redis服務器啟動命令
啟動服務
(1)修改redis.conf文件將里面的daemonize no 改成 yes,讓服務在后臺啟動
(2)將默認的redis.conf拷貝到自己定義好的一個路徑下,比如/myconf
(3)通過命令redis-server /myconf啟動服務
(4)redis-cli 連接測試
服務關閉
單實例關閉:redis-cli shutdown
多實例關閉,指定端口關閉:redis-cli -p 6379 shutdown
Redis服務
服務核心
單進程
單進程模型來處理客戶端的請求。對讀寫等事件的響應是通過對epoll函數的包裝來做到的。Redis的實際處理速度完全依靠主進程的執行效率。
epoll是Linux內核為處理大批量文件描述符而作了改進的epoll,是Linux下多路復用IO接口select/poll的增強版本,它能顯著提高程序在大量并發連接中只有少量活躍的情況下的系統CPU利用率。
服務端操作
默認16個數據庫,類似數組下表從零開始,初始默認使用零號庫。
設置數據庫的數量,默認數據庫為0,可以使用SELECT 命令在連接上指定數據庫id databases 16。
默認端口是6379
數據庫操作
select命令切換數據庫:select [index]
dbsize查看當前數據庫的key的數量
flushdb:清空當前庫
flushall:清空全部庫
統一密碼管理,16個庫都是同樣密碼,要么都OK要么一個也連接不上
Redis索引都是從零開始
更多操作
http://redisdoc.com/
Redis數據類型
Redis的五大數據類型:
(1)string(字符串)
(2)hash(哈希,類似java里的Map)
(3)list(列表)
(4)set(集合)
(5)zset(sorted set:有序集合)
Redis 鍵(key)
key值查看:
(1)keys * 顯示所有的key
(2)exists key 判斷某個key是否存在
(3)move key db 將當前庫的key移至db庫
(4)expire key 秒鐘 為給定的key設置過期時間
(5)ttl key 查看還有多少秒過期,-1表示永不過期,-2表示已過期
(6)type key 查看你的key是什么類型
(7)del key刪除key
更多操作:http://redisdoc.com/database/index.html
Redis字符串(String)
string是redis最基本的類型,一個key對應一個value。
string類型是二進制安全的。意思是redis的string可以包含任何數據。比如jpg圖片或者序列化的對象 。
string類型是Redis最基本的數據類型,一個redis中字符串value最多可以是512M。
相關操作:
set/get/del/append/strlen 設置/獲取/刪除/追加/字符串長度
Incr/decr/incrby/decrby 數字操作,一定要是數字才能進行加減
getrange/setrange 返回指定范圍內的字符串/指定范圍字符串替換
setex(set with expire)鍵秒值/setnx(set if not exist)
mset/mget/msetnx
getset(先get再set)
所有字符串類型操作:http://redisdoc.com/string/index.html
Redis列表(List)
Redis 列表是簡單的字符串列表,按照插入順序排序。可以添加一個元素導列表的頭部(左邊)或者尾部(右邊)。它的底層實際是個鏈表。
相關操作:
lpush/rpush/lrange 插入表頭/插入表尾/區間值返回
lpop/rpop 移除并返回表頭元素/移除并返回表尾元素
lindex 按照索引下標獲得元素(從上到下)
llen 長度獲取
lrem 移除
ltrim key 開始index 結束index,截取指定范圍的值后再賦值給key
rpoplpush 源列表 目的列表
lset key index value
linsert key before/after 值1 值2
所有列表操作:http://redisdoc.com/list/index.html
Redis集合(Set)
Redis的Set是string類型的無序集合。它是通過HashTable實現實現的。
相關操作:
sadd/smembers/sismember
scard,獲取集合里面的元素個數
srem key value 刪除集合中元素
srandmember key 某個整數(隨機出幾個數)
spop key 隨機出棧
smove key1 key2 在key1里某個值 作用是將key1里的某個值賦給key2
差集:sdiff
交集:sinter
并集:sunion
所有Set集合操作:http://redisdoc.com/set/index.html
Redis哈希(Hash)
相關操作:
hset/hget/hmset/hmget/hgetall/hdel
hlen
hexists key 在key里面的某個值的key
hkeys/hvals
hincrby/hincrbyfloat
hsetnx
所有Hash操作:http://redisdoc.com/hash/index.html
Redis有序集合Zset(sorted set)
相關操作:
zadd/zrange
zrangebyscore key 開始score 結束score
zrem key 某score下對應的value值,作用是刪除元素
zcard/zcount key score區間/zrank key values值,作用是獲得下標值/zscore key 對應值,獲得分數
zrevrank key values值,作用是逆序獲得下標值
zrevrange
zrevrangebyscore key 結束score 開始score
所有操作:http://redisdoc.com/sorted_set/index.html
redis配置文件
https://www.cnblogs.com/zhang-ke/p/5981108.html
#配置大小單位,開頭定義了一些基本的度量單位,只支持bytes,不支持bit
#單位大小寫不敏感
###################################GENERAL通用###################################
#包含其它配置文件
include /path/to/local.conf
#是否在后臺執行,yes:后臺運行;no:不是后臺運行
daemonize yes
#redis的進程文件
pidfile /var/run/redis_6379.pid
#指定 redis 只接收來自于該 IP 地址的請求,如果不進行設置,那么將處理所有請求
bind 127.0.0.1
#redis監聽的端口號。
port 6379
# 此參數為設置客戶端空閑超過timeout,服務端會斷開連接,為0則服務端不會主動斷開連接,不能小于0。
timeout 0
#指定了服務端日志的級別。級別包括:debug(很多信息,方便開發、測試),verbose(許多有用的信息,但是沒有debug級別信息多),notice(適當的日志級別,適合生產環境),warn(只有非常重要的信息)
loglevel notice
#指定了記錄日志的文件。空字符串的話,日志會打印到標準輸出設備。后臺運行的redis標準輸出是/dev/null。
logfile /var/log/redis/redis-server.log
#數據庫的數量,默認使用的數據庫是DB 0。可以通過”SELECT “命令選擇一個db
databases 16
#設置tcp的backlog,backlog其實是一個連接隊列,backlog隊列總和=未完成三次握手隊列 + 已經完成三次握手隊列。在高并發環境下你需要一個高backlog值來避免客戶端連接問題。注意Linux內核會將這個值減小到/proc/sys/net/core/somaxconn的值,所以需要確認增大somaxconn和tcp_max_syn_backlog兩個值來達到想要的效果
tcp-backlog 511
#單位為秒,如果設置為0,則不會進行Keepalive檢測,建議設置成60
tcp-keepalive 60
#是否把日志輸出到syslog中
syslog-enabled
#指定syslog里的日志標志
syslog-ident
#指定syslog設備,值可以是USER或LOCAL0-LOCAL7
syslog-facility
###################################SNAPSHOTTING快照###################################
# RDB是整個內存的壓縮過的Snapshot
# 快照配置
# 注釋掉“save”這一行配置項就可以讓保存數據庫功能失效
# 設置sedis進行數據庫鏡像的頻率。
# 900秒(15分鐘)內至少1個key值改變(則進行數據庫保存--持久化)
# 300秒(5分鐘)內至少10個key值改變(則進行數據庫保存--持久化)
# 60秒(1分鐘)內至少10000個key值改變(則進行數據庫保存--持久化)
# 如果想禁用RDB持久化的策略,只要不設置任何save指令,或者給save傳入一個空字符串參數也可以
save 900 1
save 300 10
save 60 10000
#當RDB持久化出現錯誤后,是否依然進行繼續進行工作,yes:不能進行工作,no:可以繼續進行工作,可以通過info中的rdb_last_bgsave_status了解RDB持久化是否有錯誤
stop-writes-on-bgsave-error yes
# 對于存儲到磁盤中的快照,可以設置是否進行壓縮存儲。如果是的話,redis會采用LZF算法進行壓縮。如果你不想消耗CPU來進行壓縮的話,可以設置為關閉此功能
rdbcompression yes
#是否校驗rdb文件。從rdb格式的第五個版本開始,在rdb文件的末尾會帶上CRC64的校驗和。這跟有利于文件的容錯性,但是在保存rdb文件的時候,會有大概10%的性能損耗,所以如果你追求高性能,可以關閉該配置。
rdbchecksum yes
#rdb文件的名稱
dbfilename dump.rdb
#數據目錄,數據庫的寫入會在這個目錄。rdb、aof文件也會寫在這個目錄
dir /var/lib/redis
################################### LIMITS ####################################
# 設置能連上redis的最大客戶端連接數量。默認是10000個客戶端連接。由于redis不區分連接是客戶端連接還是內部打開文件或者和slave連接等,所以maxclients最小建議設置到32。如果超過了maxclients,redis會給新的連接發送’max number of clients reached’,并關閉連接。
# maxclients 10000
#redis配置的最大內存容量。當內存滿了,需要配合maxmemory-policy策略進行處理。注意slave的輸出緩沖區是不計算在maxmemory內的。所以為了防止主機內存使用完,建議設置的maxmemory需要更小一些。
# maxmemory <bytes>
#內存容量超過maxmemory后的處理策略。
#volatile-lru:利用LRU算法移除設置過過期時間的key。
#volatile-random:隨機移除設置過過期時間的key。
#volatile-ttl:移除即將過期的key,根據最近過期時間來刪除(輔以TTL)
#allkeys-lru:利用LRU算法移除任何key。
#allkeys-random:隨機移除任何key。
#noeviction:不移除任何key,只是返回一個寫錯誤。
#上面的這些驅逐策略,如果redis沒有合適的key驅逐,對于寫命令,還是會返回錯誤。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檢測的樣本數。使用lru或者ttl淘汰算法,從需要淘汰的列表中隨機選擇sample個key,選出閑置時間最長的key移除。
# maxmemory-samples 5
############################## APPEND ONLY MODE ###############################
#默認redis使用的是rdb方式持久化,這種方式在許多應用中已經足夠用了。但是redis如果中途宕機,會導致可能有幾分鐘的數據丟失,根據save來策略進行持久化,Append Only File是另一種持久化方式,可以提供更好的持久化特性。Redis會把每次寫入的數據在接收后都寫入 appendonly.aof 文件,每次啟動時Redis都會先把這個文件的數據讀入內存里,先忽略RDB文件。
appendonly yes
#aof文件名
appendfilename "appendonly.aof"
#aof持久化策略的配置
#no表示不執行fsync,由操作系統保證數據同步到磁盤,速度最快。
#always表示每次寫入都執行fsync,以保證數據同步到磁盤。
#everysec表示每秒執行一次fsync,可能會導致丟失這1s數據。
appendfsync everysec
# 重寫時是否可以運用Appendfsync,用默認no即可,保證數據安全性。
no-appendfsync-on-rewrite no
#設置允許重寫的最小aof文件大小,避免了達到約定百分比但尺寸仍然很小的情況還要重寫
auto-aof-rewrite-min-size 64mb
#aof自動重寫配置。當目前aof文件大小超過上一次重寫的aof文件大小的百分之多少進行重寫,即當aof文件增長到一定大小的時候Redis能夠調用bgrewriteaof對日志文件進行重寫。當前AOF文件大小是上次日志重寫得到AOF文件大小的二倍(設置為100)時,自動啟動新的日志重寫過程。
auto-aof-rewrite-percentage 100
redis持久化
RDB
原理
在指定的時間間隔內將內存中的數據集快照寫入磁盤,也就是行話講的Snapshot快照,它恢復時是將快照文件直接讀到內存里。
Redis會單獨創建(fork)一個子進程來進行持久化,會先將數據寫入到一個臨時文件中,待持久化過程都結束了,再用這個臨時文件替換上次持久化好的文件。整個過程中,主進程是不進行任何IO操作的,這就確保了極高的性能如果需要進行大規模數據的恢復,且對于數據恢復的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺點是最后一次持久化后的數據可能丟失。
fork的作用是復制一個與當前進程一樣的進程。新進程的所有數據(變量、環境變量、程序計數器等)數值都和原進程一致,但是是一個全新的進程,并作為原進程的子進程。
保存方案
rdb 保存的是dump.rdb文件。
save命令只管保存,其它不管,全部阻塞。
Redis會在后臺異步進行快照操作,快照同時還可以響應客戶端請求。可以通過lastsave命令獲取最后一次成功執行快照的時間。
RDB持久化恢復方案
將備份文件 (dump.rdb) 移動到 redis 安裝目錄并啟動服務即可,CONFIG GET dir獲取目錄,指定配置文件的dir 路徑,dir默認當前目錄。
優勢與劣勢
優勢:
(1)適合大規模的數據恢復
(2)對數據完整性和一致性要求不高
劣勢:
(1)在一定間隔時間做一次備份,所以如果redis意外down掉的話,就會丟失最后一次快照后的所有修改。
(2)fork的時候,內存中的數據被克隆了一份,大致2倍的膨脹性需要考慮
動態停止保存方法:
動態所有停止RDB保存規則的方法:redis-cli config set save “”
AOF(Append Only File)
原理
以日志的形式來記錄每個寫操作,將Redis執行過的所有寫指令記錄下來(讀操作不記錄),只許追加文件但不可以改寫文件,redis啟動之初會讀取該文件重新構建數據,換言之,redis重啟的話就根據日志文件的內容將寫指令從前到后執行一次以完成數據的恢復工作。
配置文件
Aof保存的是appendonly.aof文件,可以在redis.conf修改文件名。
修改默認的appendonly no,改為yes
appendonly yes
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof"
#always表示每次寫入都執行fsync,以保證數據同步到磁盤。
# appendfsync always
#everysec表示每秒執行一次fsync,可能會導致丟失這1s數據。
appendfsync everysec
#no表示不執行fsync,由操作系統保證數據同步到磁盤,速度最快。
# appendfsync no
AOF啟動/修復/恢復
將有數據的aof文件復制一份保存到對應目錄(config get dir),然后重啟redis進行加載而恢復數據。
如果AOP文件存在數據異常,可以使用redis-check-aof --fix進行修復。
rewrite
AOF采用文件追加方式,文件會越來越大為避免出現此種情況,新增了重寫機制,當AOF文件的大小超過所設定的閾值時,Redis就會啟動AOF文件的內容壓縮,只保留可以恢復數據的最小指令集.可以使用命令bgrewriteaof
重寫原理:
AOF文件持續增長而過大時,會fork出一條新進程來將文件重寫(也是先寫臨時文件最后再rename),遍歷新進程的內存中數據,每條記錄有一條的Set語句。重寫aof文件的操作,并沒有讀取舊的aof文件,而是將整個內存中的數據庫內容用命令的方式重寫了一個新的aof文件,這點和快照有點類似。
觸發機制:
Redis會記錄上次重寫時的AOF大小,默認配置是當AOF文件大小是上次rewrite后大小的一倍且文件大于64M時觸發。
AOP優勢與劣勢
優勢:
(1)每修改同步:appendfsync always 同步持久化 每次發生數據變更會被立即記錄到磁盤 性能較差但數據完整性比較好.
(2)每秒同步:appendfsync everysec 異步操作,每秒記錄 如果一秒內宕機,有數據丟失,但數據丟失小。
(3)不同步:appendfsync no 從不同步,性能好。
劣勢:
(1)相同數據集的數據而言aof文件要遠大于rdb文件,恢復速度慢于rdb
(2)aof運行效率要慢于rdb,每秒同步策略效率較好,不同步效率和rdb相同
持久化方案總結
如果只希望數據在服務器運行的時候存在,可以不使用任何持久化方式.
方案對比:
RDB持久化方式能夠在指定的時間間隔能對你的數據進行快照存儲。
AOF持久化方式記錄每次對服務器寫的操作,當服務器重啟的時候會重新執行這些命令來恢復原始的數據,AOF命令以redis協議追加保存每次寫的操作到文件末尾.Redis還能對AOF文件進行后臺重寫,使得AOF文件的體積不至于過大
同時開啟兩種持久化方式:
在這種情況下,當redis重啟的時候會優先載入AOF文件來恢復原始的數據,因為在通常情況下AOF文件保存的數據集要比RDB文件保存的數據集要完整.
RDB的數據不實時,同時使用兩者時服務器重啟也只會找AOF文件。那要不要只使用AOF呢?
作者建議不要,因為RDB更適合用于備份數據庫(AOF在不斷變化不好備份),快速重啟,而且不會有AOF可能潛在的bug,留著作為一個萬一的手段。
Redis事務
簡介
可以一次執行多個命令,本質是一組命令的集合。一個事務中的所有命令都會序列化,按順序地串行化執行而不會被其它命令插入,不許加塞。一個隊列中,一次性、順序性、排他性的執行一系列命令。
操作流程
(1)開啟:以MULTI開始一個事務
(2)入隊:將多個命令入隊到事務中,接到這些命令并不會立即執行,而是放到等待執行的事務隊列里面
(3)執行:由EXEC命令觸發事務
事務
基本命令
http://redisdoc.com/transaction/index.html
DISCARD:取消事務,放棄執行事務塊內的所有命令。
EXEC:執行所有事務塊內的命令
MULTI :標記一個事務塊的開始。
WATCH :監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那么事務將被打斷。
UNWATCH:取消 WATCH 命令對所有 key 的監視。
執行情況
基本操作
(1)全部正常執行,即事務中的命令全部執行成功
(2)放棄事務,即放棄在事務中的所有操作
(3)全部執行失敗(事務中隊列中的執行操作,有語法錯誤)。
(4)部分執行(若隊列中命令無語法錯誤,則全部執行,執行過程報錯的不影響其它命令,例如:一個字符串k1=“vvsdf”,執行操作 incr k1不會報語法錯誤,但會報執行錯誤)
watch監控
悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關系型數據庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。樂觀鎖適用于多讀的應用類型,這樣可以提高吞吐量,
樂觀鎖策略:提交版本必須大于記錄當前版本才能執行更新。
Watch原理:
Watch指令,類似樂觀鎖,事務提交時,如果Key的值已被別的客戶端改變,比如某個list已被別的客戶端push/pop過了,整個事務隊列都不會被執行。
通過WATCH命令在事務執行之前監控了多個Keys,倘若在WATCH之后有任何Key的值發生了變化,EXEC命令執行的事務都將被放棄,同時返回Nullmulti-bulk應答以通知調用者事務執行失敗。
Watch執行流程:
(1)WATCH 監視一個(或多個) key
(2)MULTI標記一個事務塊的開始
(3)執行操作
(4)情況一:監控了key,如果key被修改了,后面一個事務的執行失效, WATCH 取消對所有 key 的監視
情況二:執行exec 把MULTI隊列中的命令全部執行完成,并且WATCH監控鎖也會被取消掉。
特性
單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。
沒有隔離級別的概念:隊列中的命令沒有提交之前都不會實際的被執行,因為事務提交前任何指令都不會被實際執行,也就不存在”事務內的查詢要看到事務里的更新,在事務外查詢不能看到”這個讓人萬分頭痛的問題。
不保證原子性:redis同一個事務中如果有一條命令執行失敗,其后的命令仍然會被執行,沒有回滾。
Redis的發布訂閱
簡介
進程間的一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息。
Redis 客戶端可以訂閱任意數量的頻道。
訂閱發布消息圖
例:頻道 channel1 , 以及訂閱這個頻道的三個客戶端 —— client2 、 client5 和 client1 之間的關系圖
當有新消息通過 PUBLISH 命令發送給頻道 channel1 時, 這個消息就會被發送給訂閱它的三個客戶端:
操作命令
http://redisdoc.com/pubsub/index.html
PSUBSCRIBE pattern [pattern …] 訂閱一個或多個符合給定模式的頻道。
PUBSUB subcommand [argument [argument …]] 查看訂閱與發布系統狀態。
PUBLISH channel message 將信息發送到指定的頻道。
PUNSUBSCRIBE [pattern [pattern …]] 退訂所有給定模式的頻道。
SUBSCRIBE channel [channel …] 訂閱給定的一個或多個頻道的信息。
UNSUBSCRIBE [channel [channel …]] 指退訂給定的頻道。
操作實例:
在redis客服端創建訂閱頻道channel1:
127.0.0.1:6379[1]> SUBSCRIBE channel1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
1) "message"
2) "channel1"
3) "hello channel1" //收到的第一條消息
1) "message"
2) "channel1"
3) "come here" //收到的第二條消
重新開啟一個redis客服端,然后在同一個頻道 redisChat 發布消息,訂閱者就能接收到消息。
127.0.0.1:6379[1]> PUBLISH channel1 "hello channel1"
(integer) 1
127.0.0.1:6379[1]> PUBLISH channel1 "come here"
(integer) 1
Redis的復制(Master/Slave)
簡介
Redis支持簡單的主從(master-slave)復制功能,當主Redis服務器更新數據時能將數據自動同步到從Redis服務器 ,Master以寫為主,Slave以讀為主。
主要用途
讀寫分離、容災恢復
配置搭建
原則
配從(庫)不配主(庫),從庫是不能進行修改操作的。
模式
http://redisdoc.com/replication/slaveof.html
每次與master斷開之后,都需要重新連接,除非你配置進redis.conf文件
例如有3臺redis服務器,分別是A、B、C。
一主二從
以A為主(master)庫,B、C為從庫。
在B、C上分別執行slaveof 127.0.0.1 6379,然后A庫上所有的更新操作都能在B、C中存在。
A:
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=70,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=70,lag=1
.....
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
...
127.0.0.1:6380> get k1
"v1"
1
C:
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
...
127.0.0.1:6381> get k1
"v1"
上一個Slave可以是下一個slave的Master,Slave同樣可以接收其他slaves的連接和同步請求,那么該slave作為了鏈條中下一個的master,可以有效減輕master的寫壓力。
中途變更轉向:會清除之前的數據,重新建立拷貝最新的。
A(master)為主庫
B作為A庫的slave,作為C庫的master
C為B庫的slave
A:
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=3290,lag=0
127.0.0.1:6379> set k2 v2
OK
B:
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
...
slave0:ip=127.0.0.1,port=6381,state=online,offset=3262,lag=1
127.0.0.1:6380> get k2
"v2
C:
127.0.0.1:6381> slaveof 127.0.0.1 6380
OK
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
...
127.0.0.1:6381> get k2
"v2"
反客為主
使當前數據庫停止與其他數據庫的同步,轉成主數據庫。
SLAVEOF no one
哨兵模式(sentinel)
介紹
反客為主的自動版,能夠后臺監控主機是否故障,如果故障了根據投票數自動將從庫轉換為主庫。
例如:當原有的master掛了,剩下的slave會投票選舉出新的master,如果之前的master庫重新啟動了,則會成為同步新選舉出來的master的slave從庫。
一組sentinel能同時監控多個Master。
步驟
(1)在redis.conf對應目錄下新建sentinel.conf文件。并且配置哨兵:
sentinel monitor 自定義被監控redis庫 127.0.0.1 6379 1
上面最后一個數字1,表示主機掛掉后salve投票看讓誰接替成為主機,得票數多少后成為主機。
例如:監控A庫
sentinel.conf:
sentinel monitor host6379 127.0.0.1 6379 1
1
(2)啟動哨兵
redis-sentinel sentinel.conf
1
復制原理
slave啟動成功連接到master后會發送一個sync命令
Master接到命令啟動后臺的存盤進程,同時收集所有接收到的用于修改數據集命令,
在后臺進程執行完畢之后,master將傳送整個數據文件到slave,以完成一次完全同步
全量復制:而slave服務在接收到數據庫文件數據后,將其存盤并加載到內存中。
增量復制:Master繼續將新的所有收集到的修改命令依次傳給slave,完成同步
但是只要是重新連接master,一次完全同步(全量復制)將被自動執行
例:當slave第一次連上master會全量復制,后面進行的是增量復制
復制缺點
復制延時:
由于所有的寫操作都是先在Master上操作,然后同步更新到Slave上,所以從Master同步到Slave機器有一定的延遲,當系統很繁忙的時候,延遲問題會更加嚴重,Slave機器數量的增加也會使這個問題更加嚴重。
Jedis
基礎
Jedis是 Redis 官方首選的 Java 客戶端開發包。
開發需要的jar包:commons-pool-1.6.jar、jedis-2.1.0.jar
maven:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.6</version>
</dependency>
常用操作
連接測試
Jedis jedis = new Jedis("192.168.10.206",6379);
System.out.println(jedis.ping());
1
2
基本類型操作
Jedis jedis = new Jedis("192.168.10.206",6379);
//獲取 keys * 結果
Set<String> keys = jedis.keys("*");
for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
System.out.println(key);
}
//查看k2是否存在
System.out.println("jedis.exists====>"+jedis.exists("k2"));
//查看k1還有多少秒過期
System.out.println(jedis.ttl("k1"));
//查看k1值
System.out.println(jedis.get("k1"));
//設置k4=k4_redis
jedis.set("k4","k4_redis");
//多個字符串同時設置值
jedis.mset("str1","v1","str2","v2","str3","v3");
//獲取多個字符串值
System.out.println(jedis.mget("str1","str2","str3"));
//list設置值 及獲取
jedis.lpush("mylist","v1","v2","v3","v4","v5");
List<String> list = jedis.lrange("mylist",0,-1);
for (String element : list) {
System.out.println(element);
}
//set設置值 及獲取
jedis.sadd("orders","jd001");
jedis.sadd("orders","jd002");
jedis.sadd("orders","jd003");
Set<String> set1 = jedis.smembers("orders");
for (Iterator iterator = set1.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
System.out.println(string);
}
//set移除值
jedis.srem("orders","jd002");
//hash設值及獲取
jedis.hset("hash2","userName","lisi");
System.out.println(jedis.hget("hash2","userName"));
//zset添加值
jedis.zadd("zset01",90d,"v4");
//zset獲取全部值
Set<String> s1 = jedis.zrange("zset01",0,-1);
for (Iterator iterator = s1.iterator(); iterator.hasNext();) {
String string = (String) iterator.next();
System.out.println(string);
}
事務控制
Jedis jedis = new Jedis("127.0.0.1", 6379);
int balance;// 可用余額
int amtToSubtract = 10;// 實刷額度
//watch監控
jedis.watch("balance");
balance = Integer.parseInt(jedis.get("balance"));
if (balance < amtToSubtract) {
//取消watch監控
jedis.unwatch();
System.out.println("modify");
} else {
//開啟事務
Transaction transaction = jedis.multi();
transaction.decrBy("balance", amtToSubtract);
transaction.incrBy("debt", amtToSubtract);
//執行并提交事務 watch監控也會取消
transaction.exec();
System.out.println("success");
}
主從復制
Jedis jedis_M = new Jedis("127.0.0.1",6379);
Jedis jedis_S = new Jedis("127.0.0.1",6380);
jedis_S.slaveof("127.0.0.1",6379);
1
2
3
Jedis池
獲取Jedis實例需要從JedisPool中獲取,用完Jedis實例需要返還給JedisPool,如果Jedis在使用過程中出錯,則也需要還給JedisPool
public class JedisPoolUtil {
private static volatile JedisPool jedisPool = null;
private JedisPoolUtil(){}
public static JedisPool getJedisPoolInstance(){
if(null == jedisPool){
synchronized (JedisPoolUtil.class){
if(null == jedisPool){
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxActive(1000);
poolConfig.setMaxIdle(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(null != jedis){
jedisPool.returnResourceObject(jedis);
}
}
JedisPoolConfig配置
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=true
minEvictableIdleTimeMills=60000
timeBetweenEvictionRunsMillis=30000
numTestsPerEvictionRun=-1
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。