redis
redis的意思是Remote Dictionary Server。是一個典型的key-value的數據庫。redis經常會被拿來跟memcached作比較,但是他們之間最大區別就是memcached是內存中的緩存,並不能持久化,而redis可以做持久化的。而且redis性能高
– 能支持超過 100K+ 每秒的讀寫頻率。並且支持的數據類型十分豐富。列表,字典,hash,集合,位圖。
redis的整個運行在內存中,但是會按照約定的方式將內容存進磁盤中。
redis是單進程單線程的。就像是和nginx一樣。
redis有完善的高可用,主從(藉助sentinel)而且3.0後,支持cluster。可實現分佈式解決方案。
redis十分強大,1百萬的小鍵值,大約會使用100M的內存。在常見的服務器上,大體上可承受50w的併發每秒。
數據庫現主要分爲3類:
1.RDBMS關係型數據庫:MySQL,Oracle,MariaDB,SQL Server。
2.NOSQL非關係型數據庫:LevelDB,Memcached,MongoDB(文檔數據),Redis(其實memcached並不能完全稱爲NoSQL,因爲memcached不存到磁盤)
3.NewSQL分佈式數據庫:FoundationDB
在NOSQL中,kv的NoSQL:Redis,Tair
文檔的NoSQL:MongoDB
與memcached的不同
memcached是多線程的,redis是單線程的。
memcached存儲不持久,redis是支持持久存儲。
memcached善用多核CPU,redis不善用
memcached可能有更少的內存分片。
但是二者的性能不相上下。
持久化
剛剛提到了redis的持久化,redis的持久化有兩種方式,分別是snapshotting(快照)、AOF(Append Only File)的方式。
Snapshotting:
數據是異步傳輸從內存到磁盤。
AOF:
將每一次的寫操作寫到現有的文件後面。
Redis的組件
redis-server redis的服務器端
redis-cli redis的客戶端
redis-benchmark redis的壓測工具
redis-check-dump & redis-check-aof 檢測redis的持久化功能的。
安裝Redis
redis的官方站點是redis.io(io好像是英屬印度洋領地)。目前的最新版本是3.2.8,進去直接下載就好了。
點擊Download,下載tar包。
或者執行命令
[root@localhost Downloads]# curl -O http://download.redis.io/releases/redis-3.2.8.tar.gz
解壓,並直接make再make install。redis依賴於一個jemolloc,是一個內存分配器。
tar -xf redis-3.2.8.tar.gz -C /usr/local/
cd /usr/local/redis-3.2.8/
make
make install
/usr/local/redis-3.2.8/utils/install_server.sh
redis的配置文件
[root@localhost redis]# pwd
/etc/redis
[root@localhost redis]# ls
6379.conf
bind 127.0.0.1 ::1 192.168.217.17 #綁定的IP
unixsocket /tmp/redis.sock #unixsock文件的位置
unixsocketperm 700 #unixsock的權限。如果通過unixsock去啓動就不需要網絡端口的那些tcp過程了。
save <seconds> <changes> 快照持久化的方式(snapshoting)
save 900 1 #如果900s內,有1個鍵發生了變化,會趕緊做一次快照。(效率非常低)
save "" #取消snapshoting格式的持久化。
slaveof <masterip> <masterport> 主從複製
slave-read-only yes #slave的只讀
appendonly no #啓用aof持久化功能
appendfilename "appendonly.aof"
redis的客戶端命令
redis-cli
[root@localhost init.d]# redis-cli
127.0.0.1:6379>
幫助信息
127.0.0.1:6379> help
redis-cli 3.2.5
To get help about Redis commands type:
"help @<group>" to get a list of commands in <group>
"help <command>" for help on <command>
"help <tab>" to get a list of possible help topics
"quit" to exit
To set redis-cli perferences:
":set hints" enable online hints
":set nohints" disable online hints
Set your preferences in ~/.redisclirc
使用select 1,去啓用第一個數據庫,而最多是16個。(或者說是名稱空間)
使用 help去獲得set的幫助。
127.0.0.1:6379[1]> help set
SET key value [EX seconds] [PX milliseconds] [NX|XX]
summary: Set the string value of a key
since: 1.0.0
group: string
set去設置一個鍵值對。get去獲取鍵值對。
127.0.0.1:6379> set name redhat
OK
127.0.0.1:6379> get name
"redhat"
127.0.0.1:6379> set name centos
OK
127.0.0.1:6379> get name
"centos"
實現數字的自增和自減。
127.0.0.1:6379> set count 0
OK
127.0.0.1:6379> incr count
(integer) 1
127.0.0.1:6379> incr count
(integer) 2
127.0.0.1:6379> incr count
(integer) 3
127.0.0.1:6379> incr count
(integer) 4
127.0.0.1:6379> incr count
(integer) 5
127.0.0.1:6379> decr count
(integer) 4
127.0.0.1:6379> decr count
(integer) 3
其中set命令中,最後面跟着的nx和xx。
127.0.0.1:6379> set key value [EX seconds] [PX milliseconds] [NX|XX]
nx是鍵不存在,纔對鍵進行設置操作
xx是鍵存在,纔對鍵進行操作設置
ex 加個秒數,是多長時間後這個鍵過期
不僅是string字符串,
還有list,set,sorted set(有序集合),hash。
list的操作。
l開頭代表從左側發起操作,r開頭代表從右側發起操作。如lpush,rpush
lpop 彈出,lindex 獲得key的值
127.0.0.1:6379> lpush list 1
(integer) 1
127.0.0.1:6379> lindex list 0
"1"
set的操作
sadd 添加一個key
scard 獲得key的內容
redis 的認證方法
在redis 的配置文件中的SECURITY段下加上requirepass 密碼。就需要登錄認證了。
在redis 的客戶端去認證。
[root@localhost redis]# redis-cli
127.0.0.1:6379> get 1
(error) NOAUTH Authentication required.
127.0.0.1:6379> AUTH redis
OK
127.0.0.1:6379>
清空數據庫
flushdb 清空庫
flushall 清空所有庫
redis的事務
redis是通過將一個client的所有請求連續的執行,而中間不插入其他的client的命令,來保證事務性的。
僅僅是實現了將多個請求打包成一個,串行執行。
通過multi,exec,watch等命令實現事務性。
演示一下過程。
[root@localhost redis]# redis-cli
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set host1 centos
QUEUED
127.0.0.1:6379> get host1
QUEUED
127.0.0.1:6379> set host2 redhat
QUEUED
127.0.0.1:6379> get host2
QUEUED
127.0.0.1:6379> exec
1) OK
2) "centos"
3) OK
4) "redhat"
其中multi開啓事務,開啓事務後,其中的操作都不能立馬完成,而是放到隊列裏,exec就是提交事務,所有的命令會被立馬執行。
watch:樂觀鎖,在exec命令執行之前,用於監視指定數量鍵,如果監視中的某任意鍵被修改,則服務器拒絕執行事務。
在第一終端打開一個redis客戶端1。
此時的host1是openSUSE
127.0.0.1:6379> get host1
"opensuse"
"opensuse"
監控host1,並開啓事務
127.0.0.1:6379> watch host1
OK
127.0.0.1:6379> multi
OK
OK
127.0.0.1:6379> multi
OK
這時第二個終端打開了,修改了host1
127.0.0.1:6379> set host1 redhat
OK
127.0.0.1:6379> get host1
"redhat"
OK
127.0.0.1:6379> get host1
"redhat"
第一個終端提交事務就是失敗的。
127.0.0.1:6379> watch host1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379>
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379>
這就是事務的監控特性。但是redis不支持回滾操作。
redis 的主從複製
雖然redis的讀取速度是非常快的。但是redis和MySQL一樣是有主從複製的,redis的爲了解決讀壓力,也有主從結構,其中有一主多從,和級聯結構。
複製分爲全量同步和增量同步。
全量同步
1).從服務器連接主服務器,發送SYNC命令
2).主服務器接收到SYNC後,開始執行bgsave命令生成rdb文件並使用緩衝區記錄此後執行的所有寫命令。
3).主服務器bgsave完成,向所有的從服務器發送快照文件,並在發送期間繼續記錄被執行的寫命令。
4).從服務器收到快照文件後丟棄所有的舊數據,載入收到的快照。
5).主服務器快照發送完畢後開始向從服務器發送接收緩衝區的寫命令。
6).從服務器完成對快照的載入,開始接收命令請求,並執行來自主服務器的緩衝區的寫命令。
增量同步
1).主服務器每執行一條寫命令就會向從服務器發送相同的寫命令。從服務器接收命令並且執行。
配置主從複製
node1主服務器 192.168.217.17
node2從服務器 192.168.217.16
從服務器的操作。
[root@node2 ~]# vim /etc/redis/6379.conf
slaveof 192.168.217.17 6379
觀察主服務器的狀態。
[root@node1 ~]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.217.16,port=6379,state=online,offset=71,lag=1
master_repl_offset:71
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:70
127.0.0.1:6379>
觀察從服務器的狀態。[root@node2 ~]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.217.17
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:99
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
127.0.0.1:6379>
健康檢查,slave按照repl-ping-slave-period的間隔(默認是10秒),向master發送ping。
在slave上可以看到,slave在發送PING。
127.0.0.1:6379> MONITOR
OK
1491651464.592468 [0 192.168.217.17:6379] "PING"
1491651474.721863 [0 192.168.217.17:6379] "PING"
1491651485.674035 [0 192.168.217.17:6379] "PING"
redis的HA管理工具。
redis-sentinel能監視同期的狀態,發現master down的時候,會進行failover,劃分slave升級爲master時,啓動後會自動更新sentinel設定的文件。發生failover時。會自動更改sentinel和redis的設定文件。sentinel去監視整個主從複製集羣架構,若發現主節點掛了,sentinel之間會商量確定。並且去挑選新的主節點。實現故障轉移。
(1)服務器自身初始化,運行redis-server的專用於sentinel
配置的環境。
master: 192.168.217.17
slave1: 192.168.217.16
slave2: 192.168.217.15
進入解壓後的源碼包中,複製一個sentinel的模板出來。
[root@node1 redis-3.2.5]# cp sentinel.conf /etc/redis/
[root@node1 redis-3.2.5]# pwd
/usr/local/redis-3.2.5
[root@node1 redis-3.2.5]# pwd
/usr/local/redis-3.2.5
master上的配置。編輯/etc/redis/sentinel.conf
daemmonize yes
sentinel monitor mymaster 192.168.217.17 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
第二行的其中最後一個2 代表的是法定票數,票數達到2,就認爲掛掉這個事件成立。
第三行5s連不上就認爲其離線。
第四行剛設爲新主時,允許幾個人連接
第五行故障轉移的超時時長
概念:
主觀下線:一個sentinel實例判斷出某節點下線
客觀下線:多個sentinel節點協商後判斷出節點下線
啓動sentinel
[root@node1 redis]# redis-sentinel /etc/redis/sentinel.conf --sentinel
連接並觀察
[root@node1 redis]# redis-cli -p 26379
127.0.0.1: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=192.168.217.17:6379,slaves=2,sentinels=1
127.0.0.1:26379>
確認master的信息。sentinel masters
127.0.0.1:26379> sentinel masters
1) 1) "name"
2) "mymaster"
3) "ip"
4) "192.168.217.17"
5) "port"
6) "6379"
7) "runid"
...
確認兩個slave的狀態 sentinel slaves mymasters
127.0.0.1:26379> sentinel slaves mymaster
1) 1) "name"
2) "192.168.217.16:6379"
3) "ip"
4) "192.168.217.16"
...
2) 1) "name"
2) "192.168.217.15:6379"
3) "ip"
4) "192.168.217.15"
...
sentinel哨兵放在主節點上就好,也可以專門是幾臺主機去監控整個集羣。
[root@node2 redis-3.2.5]# redis-server /etc/redis/sentinel.conf --sentinel
查看進程
[root@node3 ~]# ps aux |grep redis
root 1324 0.1 0.4 133524 2352 ? Ssl 01:31 0:02 /usr/local/bin/redis-server *:6379
root 1354 0.3 0.4 133528 2236 ? Ssl 01:57 0:00 redis-server *:26379 [sentinel]
停止master。
127.0.0.1:26379> SHUTDOWN
not connected>
主從切換