由於redis速度至關快,因此在一臺比較好的服務器下,一個外部用戶在一秒內能夠進行15W次的密碼嘗試,這意味着須要設定很是強大的密碼來防止暴力破解。html
能夠經過設置密碼以及登陸redis方式來操做,具體參考java
1、Master能夠擁有多個slave。linux
2、多個slave能夠鏈接同一個master外,還能夠鏈接到其餘的slave。nginx
3、主從複製不會阻塞master,在同步數據時,master能夠繼續處理client請求。redis
4、提供系統的伸縮性。數據庫
1、slave與master創建鏈接,發送sync同步命令。vim
2、master會開啓一個後臺進程,將數據庫快照保存到文件中,同時master主進程會開始收集新的寫命令並緩存。緩存
3、master後臺完成保存後,就把文件發送給slave。安全
4、slave將接收到的master文件保存到磁盤上。bash
#如今使用同一臺機器的不一樣配置模擬主從複製場景。 root@redis conf]# pwd /application/redis/conf [root@redis conf]# ls appendonly.aof dump.rdb redis.conf [root@redis conf]# cd .. [root@redis redis]# cp -a conf conf-slave #下述爲從節點 [root@redis redis]# cd conf-slave/ [root@redis conf-slave]# ls appendonly.aof dump.rdb redis.conf #設置從節點端口 port 6380 #設置從節點中的文件名和路徑配置爲XX-slave的形式 logfile /application/redis/logs/redis-slave.log dir /application/redis/conf-slave/ #配置主節點的IP和端口 slaveof 10.0.0.11 6379 #配置主節點的密碼(redis4.0主節點的redis.conf也要配置) masterauth redis #設置防火牆關閉狀態 [root@redis conf-slave]# /etc/init.d/iptables stop [root@redis conf-slave]# /etc/init.d/iptables status iptables: Firewall is not running. #可以使用info查看role角色,便可知道是主服務或從服務。
#主節點 [root@redis ~]# redis-server/application/redis/conf/redis.conf [root@redis ~]# lsof -i:6379 COMMAND PIDUSER FD TYPE DEVICE SIZE/OFF NODE NAME redis-ser 2456 root 4u IPv6 16205 0t0 TCP *:6379 (LISTEN) redis-ser 2456 root 5u IPv4 16207 0t0 TCP *:6379 (LISTEN) [root@redis ~]# cd /application/redis/logs/ [root@redis logs]# ll total 1780 -rw-r--r-- 1 root root 1751493 Dec 8 02:09 redis.log -rw-r--r-- 1 root root 59765 Dec 8 02:09 redis-slave.log [root@redis logs]# tailf redis.log 2456:M 08 Dec 02:08:46.338 - Accepted 10.0.0.11:17586 2456:M 08 Dec 02:08:47.345 - Accepted 10.0.0.11:17587 2456:M 08 Dec 02:08:48.352 - Accepted 10.0.0.11:17588 2456:M 08 Dec 02:08:49.076 - 0 clients connected (0slaves), 758544 bytes in use #從節點 [root@redis ~]# redis-server/application/redis/conf-slave/redis.conf [root@redis ~]# lsof -i:6380 COMMAND PIDUSER FD TYPE DEVICE SIZE/OFF NODE NAME redis-ser 2460 root 4u IPv6 16216 0t0 TCP *:6380 (LISTEN) redis-ser 2460 root 5u IPv4 16218 0t0 TCP *:6380 (LISTEN) [root@redis ~]# cd /application/redis/logs/ [root@redis logs]# ll total 1724 -rw-r--r-- 1 root root 1741206 Dec 8 02:06 redis.log -rw-r--r-- 1 root root 15808 Dec 8 02:06 redis-slave.log #從節點日誌若是出現下述狀況的話,那麼須要把redis.conf文件中的bind 127.0.0.1註釋掉。這種狀況在多臺機器中會出現,如今單臺機器模擬是不會出現的,由於redis採用的安全策略是默認只容許本地訪問,因此如今在同一臺機器中測試就不用註釋掉,redis.conf的具體參數參考「四、三、4redis.conf文件配置說明」。 [root@redis logs]# tailf redis-slave.log 2460:S 08 Dec 02:09:49.164 # Error condition on socketfor SYNC: Broken pipe 2460:S 08 Dec 02:09:50.168 - 0 clients connected (0slaves), 758544 bytes in use 2460:S 08 Dec 02:09:50.180 * Connecting to MASTER10.0.0.11:6379 2460:S 08 Dec 02:09:50.181 * MASTER <-> SLAVE syncstarted 2460:S 08 Dec 02:09:50.181 * Non blocking connect forSYNC fired the event. #能夠發現從節點沒有鏈接成功,那麼須要設置從節點對應的redis.conf文件的bind值。 [root@redis conf-slave]# lsof -i:6380 COMMAND PIDUSER FD TYPE DEVICE SIZE/OFF NODE NAME redis-ser 2460 root 4u IPv6 16216 0t0 TCP *:6380 (LISTEN) redis-ser 2460 root 5u IPv4 16218 0t0 TCP *:6380 (LISTEN) [root@redis conf-slave]# redis-cli -a shutdown -p 6380shutdown [root@redis conf-slave]# lsof -i:6380 [root@redis conf-slave]# pwd /application/redis/conf-slave bind 127.0.0.1 #主節點設置值 [root@redis ~]# redis-cli -a redis -p 6379 127.0.0.1:6379> keys * (empty list or set) 127.0.0.1:6379> set name nameval OK 127.0.0.1:6379> get name "nameval" [root@redis logs]# pwd /application/redis/logs [root@redis logs]# tailf redis.log 2506:M 08 Dec 02:21:33.242 - Accepted 127.0.0.1:36324 2506:M 08 Dec 02:21:33.584 - 1 clients connected (1slaves), 1848864 bytes in use 2506:M 08 Dec 02:21:38.616 - DB 0: 1 keys (0 volatile) in4 slots HT. 127.0.0.1:6379> del name (integer) 1 127.0.0.1:6379> keys * 1) "name2" #從節點獲取值 [root@redis ~]# redis-cli -a redis -p 6380 127.0.0.1:6380> keys * (empty list or set) 127.0.0.1:6380> keys * 1) "name" 127.0.0.1:6380> get name "nameval" 2512:S 08 Dec 02:19:28.089 * Background AOF rewritefinished successfully 2512:S 08 Dec 02:19:28.089 - Background AOF rewritesignal handler took 236us 2512:S 08 Dec 02:19:32.915 - 1 clients connected (0slaves), 779440 bytes in use 2512:S 08 Dec 02:21:38.716 - DB 0: 1 keys (0 volatile) in4 slots HT. 2512:S 08 Dec 02:21:38.717 - 2 clients connected (0slaves), 800536 bytes in use
#注意從節點是沒有寫操做的,只有讀操做
127.0.0.1:6380> del name (error) READONLY You can't write against a read onlyslave. 127.0.0.1:6380> keys * 1) "name2" #經過監控查看 #主節點作監控 [root@redis logs]# redis-cli -a redis -p 6379 monitor OK 127.0.0.1:6379> flushall OK 127.0.0.1:6379> keys * (empty list or set) [root@redis logs]# redis-cli -a redis -p 6379 monitor OK 1481135598.941742 [0 127.0.0.1:36324]"flushall" 1481135634.460910 [0 127.0.0.1:36324]"keys""*" 127.0.0.1:6379> set name nameval OK 127.0.0.1:6379> get name "nameval" [root@redis logs]# redis-cli -a redis -p 6379 monitor OK 1481135697.418957 [0 127.0.0.1:36324]"set""name""nameval" 1481135698.642795 [0 127.0.0.1:36324]"get""name" #從節點作監控 [root@redis conf-slave]# redis-cli -a redis -p 6380monitor OK 127.0.0.1:6380> keys * (empty list or set) [root@redis conf-slave]# redis-cli -a redis -p 6380monitor OK 1481135598.306657 [0 10.0.0.11:6379] "PING" 1481135598.947041 [0 10.0.0.11:6379] "flushall" 1481135608.370998 [0 10.0.0.11:6379] "PING" 1481135618.428639 [0 10.0.0.11:6379] "PING" 1481135628.493744 [0 10.0.0.11:6379] "PING" 1481135638.562807 [0 10.0.0.11:6379] "PING" 1481135648.730527 [0 10.0.0.11:6379] "PING" 1481135658.800544 [0 10.0.0.11:6379] "PING" 1481135663.809136 [0 127.0.0.1:62476]"keys""*" 1481135668.860633 [0 10.0.0.11:6379] "PING" [root@redis conf-slave]# redis-cli -a redis -p 6380monitor OK 1481135688.972458 [0 10.0.0.11:6379] "PING" 1481135697.422176 [0 10.0.0.11:6379]"set""name""nameval" 1481135699.036100 [0 10.0.0.11:6379] "PING" 127.0.0.1:6380> keys * 1) "name" 127.0.0.1:6380> get name "nameval" [root@redis conf-slave]# redis-cli -a redis -p 6380monitor OK 1481135747.385987 [0 127.0.0.1:62476]"keys""*" 1481135749.378369 [0 10.0.0.11:6379] "PING" 1481135750.203089 [0 127.0.0.1:62476]"get""name" 1481135759.444582 [0 10.0.0.11:6379] "PING"
#主節點 127.0.0.1:6379> info Replication # Replication role:master connected_slaves:1 slave0:ip=127.0.0.1,port=6380,state=online,offset=2256,lag=0 master_repl_offset:2256 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:2255 # Replication是經過info查看節點信息中的一部分 #從節點 127.0.0.1:6380> info Replication # Replication role:slave master_host:10.0.0.11 master_port:6379 master_link_status:up master_last_io_seconds_ago:6 master_sync_in_progress:0 slave_repl_offset:2326 slave_priority:100 slave_read_only:1 connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0
有了主從複製之後,若是想對主從複製服務器進行監控,那麼在redis2.6之後提供了一個「哨兵」的機制,在2.6版本中的哨兵爲1.0版本並不穩定,會出現各類各類的問題,在redis2.8版本之後的哨兵功能才穩定起來。
顧名思義,哨兵的含義就是監控redis系統的運行情況,其功能主要有兩點:
監控主數據庫和從數據庫是否正常運行。
2、主數據庫出現故障時,能夠自動將從數據庫轉換爲主數據庫,實現自動切換。
一個節點能夠被多個哨兵去監控。哨兵跟全部redis節點是沒有直接關係的,哨兵只是一個監控程序而已。
(可使用keepalived(配合nginx使用)代替哨兵,實現高可用。)
#(只配主節點便可)
#配置sentinel.conf
[root@redis redis-3.2.5]# pwd /home/lly/tools/redis-3.2.5 #拷貝到從節點目錄下 [root@redis redis-3.2.5]# cp sentinel.conf/application/redis/conf-slave/ [root@redis redis-3.2.5]# cp /application/redis/conf-slave/sentinel.conf/application/redis/conf-slave/sentinel.conf.ori [root@redis redis-3.2.5]# vim/application/redis/conf-slave/sentinel.conf sentinel monitor mymaster 127.0.0.1 6379 1 #名稱,IP,端口,投票選舉次數建議爲1,多臺機器記得設置master的內網IP(內部系統交互用內網IP,外部訪問提供外網IP)。 sentinel down-after-milliseconds mymaster 5000 #設置5000毫秒檢測一次,默認1秒 sentinel failover-timeout mymaster 900000 sentinel parallel-syncs mymaster 2 sentinel auth-pass mymaster redis #主節點密碼(節點redis.conf中未配置密碼,那麼此步省略)
#測試第一步
#啓動哨兵模式,注意下面的命令中不要加-a redis –p 6380 [root@redis conf-slave]# redis-server sentinel.conf--sentinel & [root@redis ~]# lsof -i:26379 COMMAND PIDUSER FD TYPE DEVICE SIZE/OFF NODE NAME redis-ser 2650 root 4u IPv6 19430 0t0 TCP *:26379 (LISTEN) redis-ser 2650 root 5u IPv4 19432 0t0 TCP *:26379 (LISTEN) #查看哨兵相關信息 [root@redis ~]# redis-cli -p 26379 info Sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=1,sentinels=1 #主節點日誌 [root@redis ~]# tailf /application/redis/logs/redis.log 1481137928.553897 [0 127.0.0.1:36329] "PING" 1481137929.589836 [0 127.0.0.1:36329] "PING" 1481137929.763963 [0 127.0.0.1:36329]"PUBLISH""__sentinel__:hello""127.0.0.1,26379,a14563baa663afc1c2e06ee3cb07f222c220fd7b,0,mymaster,127.0.0.1,6379,0"
#測試第二步
#關閉主節點 [root@redis ~]# redis-cli -a redis -p 6379 shutdown #從節點日誌 [root@redis conf-slave]# tailf/application/redis/logs/redis-slave.log 2574:S 08 Dec 03:15:16.629 * MASTER <-> SLAVE syncstarted 2574:S 08 Dec 03:15:16.629 # Error condition on socketfor SYNC: Connection refused 2574:M 08 Dec 03:15:17.016 * Discarding previously cachedmaster state. 2574:M 08 Dec 03:15:17.016 * MASTER MODE enabled (userrequest from 'id=5 addr=127.0.0.1:62481 fd=7 name=sentinel-a14563ba-cmd age=320idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=0 qbuf-free=32768 obl=36 oll=0omem=0 events=r cmd=exec') 2574:M 08 Dec 03:15:17.020 # CONFIG REWRITE executed withsuccess. 2574:M 08 Dec 03:15:17.048 * 1 changes in 900 seconds.Saving... 2574:M 08 Dec 03:15:17.050 * Background saving started bypid 2712 2712:C 08 Dec 03:15:17.067 * DB saved on disk 2712:C 08 Dec 03:15:17.068 * RDB: 6 MB of memory used bycopy-on-write 2574:M 08 Dec 03:15:17.150 * Background saving terminatedwith success 2574:M 08 Dec 03:15:17.980 - Client closed connection 2574:M 08 Dec 03:15:17.981 - Client closed connection 2574:M 08 Dec 03:15:18.069 - Accepted 127.0.0.1:62499 2574:M 08 Dec 03:15:18.070 - Accepted 127.0.0.1:62500 2574:M 08 Dec 03:15:20.671 - DB 0: 1 keys (0 volatile) in4 slots HT. 2574:M 08 Dec 03:15:20.672 - 2 clients connected (0slaves), 800816 bytes in use 2574:M 08 Dec 03:15:25.705 - DB 0: 1 keys (0 volatile) in4 slots HT. 2574:M 08 Dec 03:15:25.705 - 2 clients connected (0slaves), 800800 bytes in use #查看此時的哨兵信息 [root@redis ~]# redis-cli -p 26379 info Sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6380,slaves=1,sentinels=1 #原從節點info信息(如今是主節點) 127.0.0.1:6380> info Replication # Replication role:master connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 #原主節點info信息(如今是從節點) 127.0.0.1:6379> info Replication Could not connect to Redis at 127.0.0.1:6379: Connectionrefused not connected>
#測試第三步
#啓動原主節點(如今是從節點) [root@redis ~]# redis-server/application/redis/conf/redis.conf #查看哨兵切換日誌,從節點切換到了原主節點6379 [root@redis conf-slave]# redis-server sentinel.conf--sentinel & 2650:X 08 Dec 03:15:17.980 #+failover-end master mymaster 127.0.0.1 6379 2650:X 08 Dec 03:15:17.980 #+switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380 2650:X 08 Dec 03:15:17.981 *+slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380 2650:X 08 Dec 03:18:07.759 *+convert-to-slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380 #原主節點日誌(如今是從節點) [root@redis ~]# tailf /application/redis/logs/redis.log 2574:M 08 Dec 03:18:08.674 * Background saving terminatedwith success 2574:M 08 Dec 03:18:08.679 * Synchronization with slave127.0.0.1:6379 succeeded 2574:M 08 Dec 03:18:11.903 - DB 0: 1 keys (0 volatile) in4 slots HT. 2574:M 08 Dec 03:18:11.903 - 3 clients connected (1slaves), 1891152 bytes in use 2574:M 08 Dec 03:18:16.932 - DB 0: 1 keys (0 volatile) in4 slots HT. 2574:M 08 Dec 03:18:16.932 - 3 clients connected (1slaves), 1891136 bytes in use #原主節點info信息(如今是從節點)變成從節點信息 not connected> info Replication # Replication role:slave master_host:127.0.0.1 master_port:6380 master_link_status:up master_last_io_seconds_ago:0 master_sync_in_progress:0 slave_repl_offset:2061 slave_priority:100 slave_read_only:1 connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 #原從節點info信息(現主節點),變成了主節點信息 127.0.0.1:6380> info Replication # Replication role:master connected_slaves:1 slave0:ip=127.0.0.1,port=6379,state=online,offset=5736,lag=0 master_repl_offset:5736 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:5735
首先是使用multi打開事務,而後進行設置,這時設置的數據都會放入隊列裏進行保存,最後使用exec執行,把數據依次存儲到redis中,可使用discard方法取消事務。
#multi 標記一個事務塊的開始。隨後的指令將在執行EXEC時做爲一個原子執行。 返回值 simple-string-reply: 始終爲OK #exec 執行事務中全部在排隊等待的指令並將連接狀態恢復到正常當使用WATCH 時,只有當被監視的鍵沒有被修改,且容許檢查設定機制時,EXEC會被執行 返回值 multi-bulk-reply: 每一個元素與原子事務中的指令一一對應當使用WATCH時,若是被終止,EXEC 則返回一個空的應答集合 #discard 刷新一個事務中全部在排隊等待的指令,而且將鏈接狀態恢復到正常。 若是已使用WATCH,DISCARD將釋放全部被WATCH的key。 返回值 status-reply:全部返回都是 OK #watch(鎖定key,直到執行了multi/exec命令) 標記全部指定的key 被監視起來,在事務中有條件的執行(樂觀鎖)。 返回值 simple-string-reply: 老是 OK。 #unwatch(取消事務命令) 刷新一個事務中已被監視的全部key。 若是執行EXEC 或者DISCARD, 則不須要手動執行UNWATCH 。 返回值 simple-string-reply: 老是 OK。 127.0.0.1:6379> keys * 1) "age" 127.0.0.1:6379> get age "11" 127.0.0.1:6379> multi OK 127.0.0.1:6379> incr age QUEUED 127.0.0.1:6379> exec 1) (integer) 12 127.0.0.1:6379> get age "12" 127.0.0.1:6379> multi OK 127.0.0.1:6379> incr age QUEUED 127.0.0.1:6379> discard OK 127.0.0.1:6379> get age "12" 127.0.0.1:6379> keys * 1) "age" 127.0.0.1:6379> get age "13" 127.0.0.1:6379> multi OK 127.0.0.1:6379> incr age QUEUED 127.0.0.1:6379> get age QUEUED 127.0.0.1:6379> exec 1) (integer) 14 2) "14" 127.0.0.1:6379> unwatch OK 127.0.0.1:6379> get age "14" 127.0.0.1:6379> get age "14" 127.0.0.1:6379> multi OK 127.0.0.1:6379> incr age QUEUED 127.0.0.1:6379> unwatch QUEUED 127.0.0.1:6379> get age QUEUED 127.0.0.1:6379> exec 1) (integer) 15 2) OK 3) "15" 127.0.0.1:6379> watch age OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> incr age QUEUED 127.0.0.1:6379> unwatch QUEUED 127.0.0.1:6379> discard OK 127.0.0.1:6379> get age "15"
Redis的事務不能保證同時成功或失敗進行提交或回滾,因此redis的事務目前仍是比較簡單的(程序中通常是不會使用redis事務的)。
127.0.0.1:6379> keys * 1) "age" 127.0.0.1:6379> get age "15" 127.0.0.1:6379> set name nameval OK 127.0.0.1:6379> multi OK 127.0.0.1:6379> incr age QUEUED #注意incr name並沒報錯,是在執行exec命令時報錯,這個incr命令在java中調用是報錯的。 127.0.0.1:6379> incr name QUEUED #下述雖然報錯,可是事務已提交,name沒有改變。若是下述執行discard命令中斷事務的話,對全部的值都不會有影響。 127.0.0.1:6379> exec 1) (integer) 16 2) (error) ERR value is not an integer or out of range 127.0.0.1:6379> get age "16" 127.0.0.1:6379> get name "nameval"
Redis是一個支持持久化的內存數據庫,也就是說redis須要常常將內存中的數據同步到硬盤來保證持久化。Redis持久化的方式有如下兩種。
snapshotting(快照)默認方式,將內存中以快照的方式寫入到二進制文件中,默認爲dump.rdb,能夠經過配置設置自動作快照持久化的方式,咱們能夠配置redis在N秒內若是超過M個key修改,那麼就自動作快照。
快照設置:
save 900 1 #900秒內若是超過1個key被修改,則發起快照保存。下述同理。
save 300 10
save 60 10000
append-only file(縮寫aof)的方式(有點相似於oracle日誌),因爲快照方式是在必定時間間隔作一次,因此可能發生redis意外down的清苦康就會丟失最後一次快照後的全部修改的數據,aof比快照方式有更好的持久化性,是因爲在使用aof時,redis會將每個收到的寫命令都經過write函數追加到命令中,當redis重啓啓動時會從新執行文件中保存的寫命令來在內存中重建這個數據庫的內容。Aof文件不是當即寫到磁盤上,能夠經過配置文件修改強制寫到硬盤中。
aof設置:
# appendonly yes //啓動aof持久化方式有三種修改方式。
# appendfsync always //受到寫命令就當即寫入到磁盤中,效率最慢,可是保證徹底的持久化。(好比頁面寫入慢,可能就是這種形成的,可加服務器處理)
# appendfsync everysec //每秒鐘寫入磁盤一次,在性能和持久化方面作了很好的折中。
# appendfsync no //徹底依賴操做系統,性能最好,不進行同步,系統去操做,持久化沒保證。
RDB文件和AOF文件只開其中一種便可
上述內容都是在redis.conf文件中配置的,redis.conf的參數解釋詳情參考「四、三、4redis.conf配置文件說明」。
Redis提供了簡單的發佈訂閱功能。
使用subscribe [頻道] 進行訂閱監聽。
使用publish [頻道] [發佈內容] 進行發佈消息廣播。
爲了解耦發佈者(publisher)和訂閱者(subscribe)之間的關係,redis使用了channel(頻道)做爲二者的中介,發佈者將信息直接發佈給channel,而channel負責將信息發送給適當的訂閱者,發佈者和訂閱者直接沒有相互關係,也不知道對方的存在。
參考網站(包括場景和源碼分析):
「http://blog.csdn.net/clh604/article/details/19754939」
「http://www.cnblogs.com/huangxincheng/p/5002794.html」
#開啓兩個窗口,一個作發佈,一個作監聽。
#注意事項:發佈窗口的publish後面的名稱channel1必定要跟監聽窗口中subscribe後面的名稱channel1保持一致,否則不能監聽到消息。
#發佈窗口 [root@redis logs]# redis-cli 127.0.0.1:6379> publish channel1 testmessage1 (integer) 1#接收到發佈信息的監聽個數 127.0.0.1:6379> publish channel1 testmessage2 (integer) 1 127.0.0.1:6379> publish channeltest testmessage (integer) 0 #監聽窗口 127.0.0.1:6379> subscribe channel1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel1" 3) (integer) 1 #注意監聽的信息是3個一組 1) "message" 2) "channel1" 3) "testmessage1" #注意監聽的信息是3個一組 1) "message" 2) "channel1" 3) "testmessage2"
#發佈部分 [root@redis logs]# redis-cli 127.0.0.1:6379> publish channel1 message1 (integer) 2 127.0.0.1:6379> publish channel1 message2 (integer) 2 #監聽部分 [root@redis ~]# redis-cli 127.0.0.1:6379> subscribe channel1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel1" 3) (integer) 1 1) "message" 2) "channel1" 3) "message1" 1) "message" 2) "channel1" 3) "message2" [root@redis conf]# redis-cli 127.0.0.1:6379> subscribe channel1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel1" 3) (integer) 1 1) "message" 2) "channel1" 3) "message1" 1) "message" 2) "channel1" 3) "message2"
#發佈部分 [root@redis logs]# redis-cli 127.0.0.1:6379> publish channel1 message11 (integer) 2 127.0.0.1:6379> publish channel1 message12 (integer) 2 [root@redis ~]# redis-cli 127.0.0.1:6379> publish channel2 message21 (integer) 2 127.0.0.1:6379> publish channel2 message22 (integer) 2 #監聽部分 [root@redis ~]# redis-cli 127.0.0.1:6379> subscribe channel1 channel2 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel1" 3) (integer) 1 1) "subscribe" 2) "channel2" 3) (integer) 2 1) "message" 2) "channel1" 3) "message11" 1) "message" 2) "channel2" 3) "message21" 1) "message" 2) "channel1" 3) "message12" 1) "message" 2) "channel2" 3) "message22" [root@redis conf]# redis-cli 127.0.0.1:6379> subscribe channel1 channel2 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel1" 3) (integer) 1 1) "subscribe" 2) "channel2" 3) (integer) 2 1) "message" 2) "channel1" 3) "message11" 1) "message" 2) "channel2" 3) "message21" 1) "message" 2) "channel1" 3) "message12" 1) "message" 2) "channel2" 3) "message22"
下述內容參考文檔
「http://ifeve.com/redis-mem/」
「http://blog.csdn.net/xinguimeng/article/details/43884893」
「http://www.cnblogs.com/stephen-liu74/archive/2012/04/04/2366803.html」
和大多數NoSql數據庫同樣,redis一樣遵循了key/values數據存儲模型。在有些狀況下,redis會將key/values保存在內存中以提升數據查詢和數據修改的效率,然而這樣的作法並不是老是很好的選擇。鑑於此,咱們能夠將之進一步優化,即儘可能在內存中只保留keys的數據,這樣能夠保證數據檢索的效率,而values數據在不多使用的時候能夠被換出到磁盤。
redis未使用linux的虛擬內存機制,而是實現了本身的虛擬內存機制,主要緣由有如下兩點:
1、linux虛擬內存粒度過大,在linux中使用4KB的頁面,對於redis來講太大了,而redis中的絕大多數對象都遠遠小於這個數值。
2、redis能夠把數據交換到磁盤上的時候進行適當的操做,好比壓縮,一般保存到磁盤上的對象能夠去除指針和對象元數據信息,通常壓縮後的對象能夠比內存中的對象小10倍,這樣能夠節省不少的IO操做。
在實際應用中,若是內存中有一個10W條記錄的key數據集,而只有10%被常用,那麼開啓虛擬內存的redis將把與較少使用的key相對應的value轉移到磁盤上。當客戶端請求獲取這些value時,他們將被從swap文件中讀回,並載入到內存中。也就是說,若是你的數據庫中有大量的keys,其中每一個key僅僅關聯很小的value,那麼這種場景就不是很是適合使用虛擬內存。若是數據庫中只是包含不多的keys,而每個key所關聯的value確很是大,那麼這種場景就適合使用虛擬內存。
1、在配置文件中添加如下配置項,以使當前Redis服務器在啓動時打開虛存功能。
vm-enabled yes
2、在配置文件中設定Redis最大可用的虛存字節數。若是內存中的數據大於該值,則有部分對象被換出到磁盤中,其中被換出對象所佔用內存將被釋放,直到已用內存小於該值時才中止換出。
vm-max-memory (bytes)
Redis的交換規則是儘可能考慮"最老"的數據,即最長時間沒有使用的數據將被換出。若是兩個對象的age相同,那麼Value較大的數據將先被換出。須要注意的是,Redis不會將Keys交換到磁盤,所以若是僅僅keys的數據就已經填滿了整個虛存,那麼這種數據模型將不適合使用虛存機制,或者是將該值設置的更大,以容納整個Keys的數據。在實際的應用,若是考慮使用Redis虛擬內存,咱們應儘量的分配更多的內存交給Redis使用,以免頻繁的換入換出。
3、在配置文件中設定頁的數量及每一頁所佔用的字節數。爲了將內存中的數據傳送到磁盤上,咱們須要使用交換文件。這些文件與數據持久性無關,Redis會在退出前會將它們所有刪除。因爲對交換文件的訪問方式大多爲隨機訪問,所以建議將交換文件存儲在固態磁盤上,這樣能夠大大提升系統的運行效率。
vm-pages 134217728
vm-page-size 32
在上面的配置中,Redis將交換文件劃分爲vm-pages個頁,其中每一個頁所佔用的字節爲vm-page-size,那麼Redis最終可用的交換文件大小爲:vm-pages * vm-page-size。因爲一個value能夠存放在一個或多個頁上,可是一個頁不能持有多個value,鑑於此,咱們在設置vm-page-size時須要充分考慮Redis的該特徵。
4、在Redis的配置文件中有一個很是重要的配置參數,即:
vm-max-threads 4
該參數表示Redis在對交換文件執行IO操做時所應用的最大線程數量。一般而言,咱們推薦該值等於主機的CPU cores。若是將該值設置爲0,那麼Redis在與交換文件進行IO交互時,將以同步的方式執行此操做。
對於Redis而言,若是操做交換文件是以同步的方式進行,那麼當某一客戶端正在訪問交換文件中的數據時,其它客戶端若是再試圖訪問交換文件中的數據,該客戶端的請求就將被掛起,直到以前的操做結束爲止。特別是在相對較慢或較忙的磁盤上讀取較大的數據值時,這種阻塞所帶來的影響就更爲突兀了。然而同步操做也並不是一無可取,事實上,從全局執行效率視角來看,同步方式要好於異步方式,畢竟同步方式節省了線程切換、線程間同步,以及線程拉起等操做產生的額外開銷。特別是當大部分頻繁使用的數據均可以直接從主內存中讀取時,同步方式的表現將更爲優異。
若是你的現實應用偏偏相反,即有大量的換入換出操做,同時你的系統又有不少的cores,有鑑於此,你又不但願客戶端在訪問交換文件以前不得不阻塞一小段時間,若是確實是這樣,我想異步方式可能更適合於你的系統。
至於最終選用哪一種配置方式,最好的答案未來自於不斷的實驗和調優。