學習Redis(四)

概述

Redis是一個基於key-value鍵值對的持久化數據庫存儲系統。redis支持的數據存儲類型比memcached更豐富,包括strings(字符串),lists(列表),sets(集合)和sorted sets(有序集合)等。php

這些數據類型支持push/pop,add/remove及取交集,並集和差集及更豐富的操做,並且這些操做都是原子性的。在此基礎上,redis支持各類不一樣方式的排序。與memcached緩存服務同樣,爲了保證效率,數據都是緩存在內存中提供服務。和memcached不一樣的是,redis持久化緩存服務還會週期性的把更新的數據寫入到磁盤以及把修改的操做記錄追加到文件裏記錄下來,比memcached更有優點的是,redis還支持master-slave(主從)同步,這點很相似關係型數據庫MySQL主從複製功能前端

Redis是一個開源的使用C語言編寫(3萬多行代碼),支持網絡,可基於內存亦可持久化的日誌型,Key-Value數據庫,並提供多種語言的API。從2010年3月15日起,Redis的開發工做由VMware主持。node

Redis軟件的出現,再必定程度上彌補了memcached這類key-value內存緩存服務的不足,在部分場合能夠對關係數據庫起到很好的補充做用。redis提供了Python,Ruby,Erlang,PHP客戶端,使用起來很方便.python

 redis特色

1.key-value鍵值類型存儲mysql

2.支持數據可靠存儲及落地linux

3.單進程單線程高性能服務器c++

4.crash safe & recovery slowgit

5.單機qps能夠達到10Wgithub

6.適合小數據量高速讀寫訪問web

Redis優勢

1.與memcached不一樣,Redis能夠持久化存儲數據

2.性能很高:Redis能支持超過10W每秒的讀寫頻率。

3.豐富的數據類型:Redis支持二進制的Strings,Lists,Hashes,Sets及sorted Sets等數據類型操做

4.原子:Redis的全部操做都是原子性的,同時Redis還支持對幾個操做全並後的原子性執行

5.豐富的特性:Redis還支持publish/subscribe(發佈/訂閱),通知,key過時等等特性。

6.redis支持異機主從複製。

redis缺陷與陷阱

1.系統運行有毛刺

2.不一樣命令延遲差異極大

3.內存管理開銷大(設置低於物理內存3/5)

4.buffer io形成系統OOM(內存溢出)

 redis的數據類型

做爲Key-value型存儲系統數據庫,Redis提供了鍵(Key)和值(value)映射關係。可是,除了常規的數值或字符串,Redis的鍵值還能夠是如下形式之一,下面爲最爲經常使用的數據類型:

  • String 字符串
  • Hash 哈希表
  • List 列表
  • Set 集合
  • Sorted set 有序集合

redis 持久化

一般,Redis將數據存儲於內存中,或被配置爲使用虛擬內存。經過兩種方式能夠實現數據持久化:

使用快照(snapshot)的方式,將內存中的數據不斷寫入磁盤,或使用相似MySQL的binlog日誌 

aof (但並不用於主從同步)方式,記錄每次更新的日誌。前者性能較高,可是可能會引發必定程度的數據丟失;後者相反。

複製代碼
#Snapshot(快照)
save 900 1 #900秒有1key容量被更新,則觸發快照寫入磁盤
save 300 10
save 60 10000 
#AOF(更新日誌)
appendfsync always #老是記錄更新內容 appendfsync everysec #每秒記錄更新內容 appendfsync no #不記錄更新內容
複製代碼

特別提示:

若是選擇了快照的策略,那麼快照在每次進行保存的時候,都會阻礙執行前端的客戶端請求。 快照會一次性將內存裏的數據全都寫進磁盤。

Redis的生產經驗教訓

1.必定要進行Master-slave主從同步配置,在出現服務故障時能夠切換

2.在master禁用數據持久化,只須要在slave上配置數據持久化

3.物理內存+虛擬內存不足,這個時候dump一直死着,時間久了機器掛掉。這個狀況就是災難!

4.當Redis物理內存使用超過內存總容量的3/5時就會開始比較危險了,就開始作swap,內存碎片大!

5.當達到最大內存時,會清空帶有過時時間的key,即便key未到過時時間。

6.redis與DB同步寫的問題,先寫DB,後寫redis,由於寫內存基本上沒有問題。

Redis的服務器4.0版本源碼編譯安裝

系統:Centos7

版本:redis4.0 

 redis下載地址:https://redis.io/download

 redis源碼編譯

複製代碼
yum -y install wget gcc gcc-c++ make tar openssl-devel cmake
tar xf redis-4.0.10.tar.gz -C /usr/src/
cd /usr/src/redis-4.0.10/
make;make MALLOC=jemalloc;make PREFIX=/usr/local/redis install
mkdir -p /usr/local/redis/conf
cp /usr/src/redis-4.0.10/redis.conf /usr/local/redis/conf/
cp /usr/src/redis-4.0.10/sentinel.conf /usr/local/redis/conf/
ln -s /usr/local/redis/bin/* /usr/local/bin/

redis-server --version     #服務端鏈接命令 Redis server v=4.0.10 sha=00000000:0 malloc=jemalloc-4.0.3 bits=64 build=d2228e273f4aff2f
redis-cli --version     #客戶端鏈接命令 redis-cli 4.0.10    
複製代碼

編譯安裝命令執行完成以後,會在/usr/local/redis/bin/目錄下生成5個可執行文件,分別是:

複製代碼
redis-server      #Redis服務器的daemon啓動程序
redis-cli         #Redis命令操做工具。固然,你也能夠用telnet根據其純文本協議來操做
redis-benchmark   #Redis性能測試工具,測試Redis在你的系統及你的配置下的讀寫性能。
redis-check-aof   #對更新日誌appendonly.aof檢查,是否可用,相似檢查mysql binlog的工具
redis-check-dump    #用於本地數據庫rdb文件的檢查
複製代碼

 

Redis的服務器啓動和系統參數調整

簡化redis配置文件

cp /usr/local/redis/conf/redis.conf{,.bak}               #備份配租文件 egrep -v "^$|^#" /usr/local/redis/conf/redis.conf.bak > /usr/local/redis/conf/redis.conf           #簡化配置文件 mkdir -p /data/redis/        #建立redis數據目錄

更改redis配置文件/usr/local/redis/conf/redis.conf

複製代碼
#修改redis配置文件如下參數
cat -n conf/redis.conf | sed -n '1p;3p;4p;7p;9p;11p;21p'
     1  bind 127.0.0.1
     3  port 6379
     4  tcp-backlog 511
     7  daemonize no
     9  pidfile /var/run/redis_6379.pid
    11  logfile ""
    21  dir ./
#修改爲如下設置
cat -n conf/redis.conf | sed -n '1p;3p;4p;7p;9p;11p'
     1  bind 0.0.0.0            #監聽地址
     3  port 6379               #監聽端口
     4  tcp-backlog 1024        #tcp鏈接數
     7  daemonize yes           #是否後臺啓動 9  pidfile /data/redis/redis.pid   #pid存放目錄 11  logfile "/data/redis/redis.log" #日誌存放目錄
    21  dir /data/redis/                #工做目錄
複製代碼

 redis服務器啓動和關閉

複製代碼
#啓動redis服務器
redis-server /usr/local/redis/conf/redis.conf
netstat -antup | grep redis
#關閉redis服務器
redis-cli shutdown
netstat -antup | grep redis
#鏈接redis服務器
redis-server /usr/local/redis/conf/redis.conf
redis-cli -h 127.0.0.1
複製代碼

系統參數優化調整

複製代碼
#啓動redis之後,咱們查看系統日誌
cat /data/redis/redis.log 
cat /data/redis/redis.log 
7702:C 20 Aug 04:09:02.029 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
7702:C 20 Aug 04:09:02.029 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=7702, just started
7702:C 20 Aug 04:09:02.029 # Configuration loaded
7703:M 20 Aug 04:09:02.033 * Increased maximum number of open files to 10032 (it was originally set to 1024).
                 #警告提示1:系統文件描述符設置的過小了,才1024,咱們最好設置到10032 _._ _.
-``__ ''-._ _.-`` `. `_. ''-._ Redis 4.0.10 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 7703 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 7703:M 20 Aug 04:09:02.035 # WARNING: The TCP backlog setting of 1024 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.                 #因爲/proc/sys/net/core/somaxconn設置爲較低的128,所以沒法強制設置1024的TCP backlog。
7703:M 20 Aug 04:09:02.035 # Server initialized 7703:M 20 Aug 04:09:02.035 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
                7703:M 20 Aug 04:09:02.035 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
7703:M 20 Aug 04:09:02.035 * Ready to accept connections#警告提示3:overcommit_memory=0爲不容許超額搶佔內存,可是,rdb保存可能會失敗。建議將vm.overcommit_memory = 1進行修改
                #警告提示4:你的內核中啓用了巨大內存頁的支持,這將與redis的延遲內存使用衝突。
複製代碼

(1)調整系統文件描述符

echo "* - nofile 10240" >> /etc/security/limits.conf 
bash        #刷新下即生效
ulimit -n
10240

(2)調整系統的TCP鏈接數

複製代碼
 sysctl -a | grep soma
sysctl: reading key "net.ipv6.conf.all.stable_secret"
sysctl: reading key "net.ipv6.conf.default.stable_secret"
sysctl: reading key "net.ipv6.conf.eth0.stable_secret"
sysctl: reading key "net.ipv6.conf.lo.stable_secret"
net.core.somaxconn = 128

echo "net.core.somaxconn = 10240" >> /etc/sysctl.conf

sysctl -p
net.core.somaxconn = 10240
複製代碼

(3)調整系統內存分配策略

echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf 
sysctl -p
net.core.somaxconn = 10240
vm.overcommit_memory = 1

vm.overcommit_memory參數說明: 
根據內核文檔,該參數有三個值,分別是: 
0:當用戶空間請求更多的內存時,內核嘗試估算出剩餘可用的內存。 
1:當設這個參數值爲1時,內核容許超量使用內存直到用完爲止,主要用於科學計算 
2:當設這個參數值爲2時,內核會使用一個毫不過量使用內存的算法,即系統整個內存地址空間不能超過swap+50%的RAM值,50%參數的設定是在overcommit_ratio中設定。

(4)關閉系統內核的巨大內存頁支持

複製代碼
echo never > /sys/kernel/mm/transparent_hugepage/enabled 
echo never > /sys/kernel/mm/transparent_hugepage/defrag 
#添加到/etc/rc.local
echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local
echo 'echo never > /sys/kernel/mm/transparent_hugepage/defrag' >> /etc/rc.local
複製代碼

(5)重啓redis的服務器驗證修改

複製代碼
redis-cli shutdown        #關閉redis > /data/redis/redis.log      #清空redis日誌
 redis-server /usr/local/redis/conf/redis.conf        #啓動redis

cat /data/redis/redis.log           #查看redis日誌 8064:C 20 Aug 04:22:42.049 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 8064:C 20 Aug 04:22:42.050 # Redis version=4.0.10, bits=64, commit=00000000, modified=0, pid=8064, just started 8064:C 20 Aug 04:22:42.050 # Configuration loaded _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 4.0.10 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 8065 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 8065:M 20 Aug 04:22:42.055 # Server initialized 8065:M 20 Aug 04:22:42.055 * DB loaded from disk: 0.000 seconds 8065:M 20 Aug 04:22:42.055 * Ready to accept connections


複製代碼

 爲php安裝redis客戶端擴展

(1)獲取源碼包

wget https://github.com/phpredis/phpredis/archive/2.2.4.tar.gz

(2)安裝

unzip phpredis-master.zip       #解壓
cd /usr/src/phpredis-master/
/usr/local/php/bin/phpize

若是出現如下報錯

複製代碼
Configuring for:
PHP Api Version:         20090626
Zend Module Api No:      20090626
Zend Extension Api No:   220090626
Cannot find autoconf. Please check your autoconf installation and the
$PHP_AUTOCONF environment variable. Then, rerun this script.
複製代碼
yum install m4 autoconf         #安裝這些解決 /usr/local/php/bin/phpize       #再次執行
./configure --with-php-config=/usr/local/php/bin/php-config
#編譯安裝 make; make install        

(3)修改php.ini設置,重啓php

echo "extension = redis.so" >> /usr/local/php/lib/php.ini
#將php.ini配置文件中的extension_dir修改爲以下:
extension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/"

安裝Python redis客戶端操做redis

wget https://pypi.python.org/packages/source/r/redis/redis-2.10.1.tar.gz
tar xf redis-2.10.1.tar.gz
cd redis-2.10.1
python setup.py install

開發python程序操做redis

複製代碼
python
import redis        #引用redis支持庫
 r = redis.Redis(host='192.168.50.157',port='6379',password='') #創建redis數據庫的鏈接對象(面向對象方式)
r.set('name','wk')   #操做對象調用set方法寫入數據
True
r.get('name')           #操做對象調用get方式讀取數據
'wk'
複製代碼

############################################################################################################

redis-server命令

redis-server /usr/local/redis/conf/redis.conf    #加配置文件絕對路徑啓動redis服務 redis-server /usr/local/redis/conf/redis.conf &  #若是配置文件daemonize yes後臺啓動沒有開啓則在結尾&在後臺啓動

redis-cli命令

redis-cli           #經過客戶端鏈接本地redis 
redis-cli shutdown     #關閉redis服務

-p指定端口

?
1
redis-cli -p 6379 

-h指定要鏈接的reids服務端的IP

redis-cli -h 192.168.50.167

結尾跟內部命令可在外部執行

redis-cli -h 10.0.0.135 -p 6379 set aaa 111
OK

-a指定密碼(會有警告密碼暴露外邊,因此通常不用)

redis-cli -a 123456

--raw  顯示中文字符

redis-cli --raw

經過客戶端操做redis數據庫

複製代碼
set id 1      #寫入一條數據key(id),value(1
get id          #取值key(id  
del id          #刪除key(id    
incr id      #自增1 id變爲2
incrby id 5   #自增指定數值5 id變爲7  
decr id      #自減1 id變爲6
decrby id5    #自減指定數值5 id變爲1
getset id 6   #設置新數據並顯示原數據
mset name zhangsan age 44    #批量寫操做 key爲name值爲zhangsan key爲age值爲44
mget name age   #批量讀操做 一次行查看name和age的值
append name feng  #追加字符串 結果爲zhangsanfeng
exists
id #驗證key是否存在 keys * #查看redis裏全部的key 不建議使用,上千萬的key會使redis服務器堵塞 select 1 #切換到表1模式 redis總共有默認16個表
randomkey    #隨機返回一個key
scan 0      #分頁查看key
select 0     #表示切換到0庫 默認16個庫

複製代碼
#經過help命令來查找命令
#輸入help 屢次<Tab>鍵來切換全部命令
help @hash
info           #查看各項信息
info cpu        #查看CPU信息
info memory #查看內存信息
info clients #查看客戶端信息
info replication #查看同步信息

批量往redis server上插入數據

for line in `seq -w 50`;do redis-cli set name_${line} value_${line};done

給redis增長密碼的兩種方式

vim /usr/local/redis/conf/redis.conf    #修改配置文件設置密碼
requirepass "123456"              #設置密碼
複製代碼
#交互式登錄redis設置密碼
redis-cli 

config get requirepass        #獲取redis配置的密碼信息 1) "requirepass"
2) ""        #此時密碼空

config set requirepass 123456 #給redis設置密碼密碼即時生效
OK

auth 123456     #進行密碼驗證

config get requirepass       #查看密碼配置信息 1) "requirepass"
2) "123456"          #有密碼了
  
config rewrite                 #將配置重寫進行保存
OK

#查看redis配置文件最後兩行 tail -2 /usr/local/redis/conf/redis.conf
# Generated by CONFIG REWRITE
requirepass "yunjisuan"         #增長了密碼配置
複製代碼

 

解讀配置文件

基本設置

複製代碼
#redis支持include功能
include /path/to/local.conf
include /path/to/other.conf

#redis是否後臺運行
daemonize no   

#pid號保存文件的位置
pidfile /var/run/redis.pid
 #redis默認監聽端口
port 6379 #調整tcp監聽隊列
tcp-backlog 511 #調整redis的監聽地址
bind 192.168.1.100 10.0.0.1
bind 127.0.0.1 #調整客戶端超時時間
timeout 0 #調整tcp的會話保持時間
tcp-keepalive 0 #調整日誌級別
loglevel notice

#是否啓用syslog來接收日誌(好比日誌集中收集)
syslog-facility local0

#設置數據庫的數量,若是缺省,默認爲0(select0...select 15
databases 16 #若是bgsave出錯是否中止寫入
stop-writes-on-bgsave-error yes

#redis將數據存儲在磁盤的什麼位置
dbfilename dump.rdb

#指定redis配置文件當前工做的路徑(指定dbfilename的當前路徑位置) dir ./ #給redis設定密碼
requirepass 123456 #修改redis操做命令的名稱
rename-command CONFIG ""
rename-command set ""
rename=command get wk

#設定redis內存限制(可是內存用完後,redis就會開始刪除key)
maxmemory <bytes> #設定redis內存清理的算法
# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key accordingly to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operation
maxmemory-policy volatile-lru
複製代碼

rdb快照設置  (快照及流模式只能用在從不能用在主 主壓力太大)

複製代碼
################################ SNAPSHOTTING  ################################
#
# Save the DB on disk:
#
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving at all commenting all the "save" lines.
#
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#
#   save "" #若是不想保存在磁盤,就如此設置 等於關閉快照

save 900 1 #900秒內至少1key數據變化,但會阻塞用戶請求,高併發時不用
save 300 10 #300秒內至少10key數據變化,但會阻塞用戶請求,高併發時不用
save 60 10000   #60秒內至少10000key數據變化,但會阻塞用戶請求,高併發時不用
複製代碼

AOF流模式設置

複製代碼
############################## APPEND ONLY MODE ###############################

# By default Redis asynchronously dumps the dataset on disk. This mode is
# good enough in many applications, but an issue with the Redis process or
# a power outage may result into a few minutes of writes lost (depending on
# the configured save points).
#
# The Append Only File is an alternative persistence mode that provides
# much better durability. For instance using the default data fsync policy
# (see later in the config file) Redis can lose just one second of writes in a
# dramatic event like a server power outage, or a single write if something
# wrong with the Redis process itself happens, but the operating system is
# still running correctly.
#
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
#
# Please check http://redis.io/topics/persistence for more information.
#是否啓用AOF存儲模式
appendonly no
#設定AOF文件的存儲位置
appendfilename "appendonly.aof" #並不用於主從同步,只是redis在啓動時,讀取此文件用於恢復數據
#設定AOF同步存儲的時間週期
appendfsync everysec    #每秒或不用
複製代碼

 ########################################################################################

Redis數據類型詳解

Redis鍵/值介紹

Redis key值是二進制安全的,這意味着能夠用任何二進制序列做爲key值,從形如「foo」的簡單字符串到一個JPG文件的內容均可以。空字符串也是有效key值。

key規則:

  • 太長的鍵值不是個好主意,例如1024字節的鍵值就不是個好主意,不只由於消耗內存,並且在數據中查找這類鍵值的計算成本很高。
  • 過短的鍵值一般也不是好主意,若是你要用「u:1000:pwd」來代替
  • 最好堅持一種模式。例如:"object-type:id:field"就是個不錯的注意,像這樣「user:1000:password」。或者一個鍵值對的字段名中加上一個點,就想這樣「comment:1234:reply.to」。

數據類型:

String字符串類型

List列表數據類型

 集合(Sets)類型

有序集合(Sorted Sets)類型

Hash類型

 

1.String字符串類型

這是Redis最簡單的數據類型之一。若是隻使用這種數據類型,那麼redis就是一個持久化的memcached服務器固然redis對string類型的功能比memcached仍是多不少的

常規的String字符串類型(key value):

127.0.0.1:6379> set wk >.>haoshuai      #存入數據 key爲wk 數據爲>.>haoshuai
OK
127.0.0.1:6379> get wk             #查數據,get+key值查看 ">.>haoshuai"

value值能夠是任何類型的字符串(包括二進制數據),例如你能夠在一個鍵下保存一個jpg圖片。但值的長度不能超過1GB

String類型也能夠用來存儲數字,並支持對數字的加減操做:

set id 1 #設置鍵爲id 值爲1
incr id      #自增1 id變爲2
incrby id 5   #自增指定數值5 id變爲7  
decr id      #自減1 id變爲6
decrby id5    #自減指定數值5 id變爲1   

爲key設置新值而且返回原值

複製代碼
127.0.0.1:6379> set user01 zhangsan   #設置新key-value
OK
127.0.0.1:6379> get user01      
"zhangsan"
127.0.0.1:6379> getset user01 wangwu #設置新數據並返回舊數據 "zhangsan"
127.0.0.1:6379> getset user01 liliu     #設置新數據並返回舊數據 "wangwu"
127.0.0.1:6379> getset user01 gongli    #設置新數據並返回舊數據 "liliu"
127.0.0.1:6379> get user01      
"gongli"
複製代碼

String類型還支持批量讀寫操做

127.0.0.1:6379> mset name zhangsan age 44
OK
127.0.0.1:6379> mget name age
1) "zhangsan"
2) "44"

string類型還支持對其部分的修改和獲取操做

127.0.0.1:6379> set images flower
127.0.0.1:6379> append images .jpg  #追加字符串 127.0.0.1:6379> get images
"flower.jpg"

2.List列表類型

列表list的用途:

list可被用來實現聊天系統。還能夠做爲不一樣進程間傳遞消息的隊列。關鍵是,你能夠每次都以原先添加的順序訪問數據。這不須要任何SQLORDER操做,將會很是快,也會很容易擴展到百萬級別的規模。

在評級系統中,好比社會化新聞網站reddit.com,你能夠把每一個新提交的連接添加到一個list,用LRANGE可簡單的對結果分頁。

在博客引擎實現中,你可爲每篇日誌設置一個list,在該list中推入進博客評論,等等

向Redis list壓入ID而不是實際的數據

複製代碼
127.0.0.1:6379> lpush students "zhangsan"   #將元素「zhangsan」放在students列表的最左邊
127.0.0.1:6379> lpush students "wangwu"   #將元素「wangwu」插入列表的最左邊
127.0.0.1:6379> lpush students "liliu"    #將元素「liliu」插入列表的最左邊
lrange students 0 2               #查看序列是0到2的元素 1) "liliu"
2) "wangwu"
3) "zhangsan"
rpush students "wangyue"              #將元素wangyue插入列表的最右邊
lrange students 0 3                 #查看序列是0到3的元素 1) "liliu"
2) "wangwu"
3) "zhangsan"
4) "wangyue"
llen students  #查看列表元素的個數
lpop students   #移除最左邊的元素值
rpop students   #移除最右邊的元素值 127.0.0.1:6379> rpush students zhangsan
127.0.0.1:6379> rpush students zhangsan
127.0.0.1:6379> lrange students 0 3
1) "wangwu"
2) "zhangsan"
3) "zhangsan"
4) "zhangsan"
127.0.0.1:6379> lrem students 2 "zhangsan"  #刪除列表裏是「zhangsan」的元素,刪除兩次(從左向右刪)
127.0.0.1:6379> lrange students 0 3
1) "wangwu"
2) "zhangsan"
127.0.0.1:6379> lrem students 1 "zhangsan"  #刪除列表裏的元素zhangsan一次
127.0.0.1:6379> lrem students 0 "zhangsan"  #清空列表全部的zhangsan元素
複製代碼
複製代碼
127.0.0.1:6379> lpush students a b c d  #左插入元素abcd 127.0.0.1:6379> lrange students 0 4
1) "d"
2) "c"
3) "b"
4) "a"
127.0.0.1:6379> linsert students before b xxxx  #在元素b的前邊插入元素xxxx 127.0.0.1:6379> lrange students 0 9
1) "d"
2) "c"
3) "xxxx"
4) "b"
5) "a"
127.0.0.1:6379> linsert students after b xxxx  #在元素b的後邊插入元素xxxx 127.0.0.1:6379> lrange students 0 9
1) "d"
2) "c"
3) "xxxx"
4) "b"
5) "xxxx"
6) "a"
複製代碼

3.集合(Sets)類型

Redis集合是未排序的集合,其元素是二進制安全的字符串。SADD命令能夠向集合添加一個新元素。和sets相關的操做也有許多,好比檢測某個元素是否存在,以及實現交集,並集,差集等等。

edis可以將一系列不重複的值存儲成一個集合

複製代碼
127.0.0.1:6379> sadd users laoda    #向集合users裏添加一個元素「laoda」 127.0.0.1:6379> sadd users laoer laosan #向結合users裏添加兩個元素laoer,laosan 127.0.0.1:6379> smembers users  #查看集合裏的全部元素 1) "laosan"         #能夠看到集合裏的元素是無序的
2) "laoda"
3) "laoer"
#咱們向集合中添加了三個元素,並讓Redis返回全部元素。如今讓咱們看一下某個元素是否存在於集合中
127.0.0.1:6379> sismember users laoda   #查看元素laoda是否存在於集合users中
(integer) 1 #存在
127.0.0.1:6379> sismember users laoer   #查看元素laoer是否存在於集合users中
(integer) 1 #存在
127.0.0.1:6379> sismember users laosan  #查看元素laosan是否存在於集合users中
(integer) 1 #存在
127.0.0.1:6379> sismember users laosi   #查看元素laosi是否存在於集合users中
(integer) 0 #不存在
複製代碼

「laoda」是這個集合的成員,而「laosi」不是。集合特別適合表現對象之間的關係。例如用Redis集合能夠很容易實現標籤功能。

下面是一個簡單的方案:對每一個想加標籤的對象,用一個標籤ID集合與之關聯,而且對每一個已有的標籤,一組對象ID與之關聯。

例如,假設咱們的新聞ID1000被加了三個標籤tag1,2,5和77,就能夠設置下面兩個集合:

複製代碼
sadd news:1000:tags 1
sadd news:1000:tags 2
sadd news:1000:tags 5
sadd news:1000:tags 77
sadd tag:1:objects 1000
sadd tag:2:objects 1000
sadd tag:5:objects 1000
sadd tag:27:objects 1000 #要獲取一個對象的全部標籤,咱們只須要:
#獲取ID號爲1000的全部新聞的題目
smembers news:1000:tags      #獲取集合爲news:1000:tags的全部元素
1) "1"      #新聞標題
2) "2"      #新聞標題
3) "5"      #新聞標題
4) "77"     #新聞標題
#查詢某個標籤的具體內容,咱們只須要:
#獲取某個新聞標題的具體內容
smembers tag:5:objects       #獲取集合爲tag:5:objects的全部元素
1) "1000"       #新聞內容
複製代碼

而有些看上去並不簡單的操做仍然能使用相應的Redis命令輕鬆實現。例如咱們也許想得到一份同時擁有標籤1,2,10和27的對象列表。則能夠用SINTER命令來作,他能夠在不一樣集合之間取出交集。所以爲達目的咱們只需:

複製代碼
sadd tag:1:objects 500       #向集合tag:1:objects裏添加元素「500
smembers tag:1:objects   #查看集合tag:1:objects裏的全部元素
1) "500"
2) "1000"
smembers tag:2:objects   #查看集合tag:2:objects裏的全部元素
1) "1000"
sinter tag:1:objects tag:2:objects tag:5:objects tag:27:objects    #求集合tag:1:objects ...tag:27:objects裏的全部元素的交集
1) "1000"
複製代碼

 

4 有序集合(Sorted Sets)類型

Sorted Sets和Sets結構類似,不一樣的是存在Sorted Sets中的數據會有一個score屬性,並會在寫入時就按這個score拍好序。

複製代碼
#向一個有序集合裏添加元素
127.0.0.1:6379> ZADD days 0 mon #days是有序集合名,0是序號,mon是值
(integer) 1
127.0.0.1:6379> ZADD days 1 tue
(integer) 1
127.0.0.1:6379> ZADD days 2 web
(integer) 1
127.0.0.1:6379> ZADD days 3 thu
(integer) 1
127.0.0.1:6379> ZADD days 4 fri
(integer) 1
127.0.0.1:6379> ZADD days 5 sat
(integer) 1
127.0.0.1:6379> ZADD days 6 sun
(integer) 1
127.0.0.1:6379> zrange days 0 6 #查看集合索引0到6的元素
1) "mon"
2) "tue"
3) "web"
4) "thu"
5) "fri"
6) "sat"
7) "sun"
#從上面咱們能夠看出,ZADD建立的集合是有序集合。
#查看有序集合days的具體值的排序
127.0.0.1:6379> zscore days mon
"0"
127.0.0.1:6379> zscore days web 
"2"
127.0.0.1:6379> zscore days fri
"4"
root@redis-master ~]# redis-cli -a yunjisuan
127.0.0.1:6379> zscore days mon
"0"
127.0.0.1:6379> zscore days web
"2"
127.0.0.1:6379> zscore days fri
"4"
127.0.0.1:6379> zcount days 3 6
(integer) 4
127.0.0.1:6379> ZRANGEBYSCORE days 3 6
1) "thu"
2) "fri"
3) "sat"
4) "sun"
複製代碼
  • 集合是使用頻率很高的數據類型,可是...對許多問題來講他們也有點太不講順序了;所以Redis1.2引入了有序集合。它和集合很是類似,也是二進制安全的字符串集合,可是此次帶有關聯的score,以及一個相似LRANGE的操做能夠返回有序元素,此操做只能做用於有序集合,它就是,ZRANGE命令。
  • 基本上有序集合從某種程度上說是SQL世界的索引在Redis中的等價物。例如在上面提到的reddit.com例子中,並無提到如何根據用戶投票和時間因素將新聞組合生成首頁。咱們將看到有序集合如何解決這個問題,但最好先從更簡單的事情開始,闡明這個高級數據類型是如何工做的。讓咱們添加幾個黑客,並將他們的生日做爲「score」。
複製代碼
127.0.0.1:6379> zadd hackers 1940 "1940-Alan Kay"
(integer) 1
127.0.0.1:6379> zadd hackers 1953 "1953-Richard Stallman"
(integer) 1
127.0.0.1:6379> zadd hackers 1965 "1965-Yukihiro Matsumoto"
(integer) 1
127.0.0.1:6379> zadd hackers 1916 "1916-Claude Shannon"
(integer) 1
127.0.0.1:6379> zadd hackers 1969 "1969-Linus Torvalds"
(integer) 1
127.0.0.1:6379> zadd hackers 1912 "1912-Alan Turing"
(integer) 1
複製代碼

對有序集合來講,按生日排序返回這些黑客易如反掌,由於他們已是有序的。有序集合是經過一個dual-ported數據結構實現的,它包含一個精簡的有序列表和一個hash table,所以添加一個元素的時間複雜度是O(log(N))。這還行,但當咱們須要訪問有序的元素時,Redis沒必要再作任何事情,它已是有序的了:

複製代碼
127.0.0.1:6379> zadd hackers 1940 "1940-Alan Kay"
(integer) 1
127.0.0.1:6379> zadd hackers 1953 "1953-Richard Stallman"
(integer) 1
127.0.0.1:6379> zadd hackers 1965 "1965-Yukihiro Matsumoto"
(integer) 1
127.0.0.1:6379> zadd hackers 1916 "1916-Claude Shannon"
(integer) 1
127.0.0.1:6379> zadd hackers 1969 "1969-Linus Torvalds"
(integer) 1
127.0.0.1:6379> zadd hackers 1912 "1912-Alan Turing"
(integer) 1
#利用zrange進行排序查詢
127.0.0.1:6379> zrange hackers 0 6
1) "1912-Alan Turing"
2) "1916-Claude Shannon"
3) "1940-Alan Kay"
4) "1953-Richard Stallman"
5) "1965-Yukihiro Matsumoto"
6) "1969-Linus Torvalds"
#利用zrevrange進行反向查詢
127.0.0.1:6379> zrevrange hackers 0 -1
1) "1969-Linus Torvalds"
2) "1965-Yukihiro Matsumoto"
3) "1953-Richard Stallman"
4) "1940-Alan Kay"
5) "1916-Claude Shannon"
6) "1912-Alan Turing"
複製代碼

5 Hash類型

Redis可以存儲key對多個屬性的數據(好比user1,uname user1.passwd)

複製代碼
#存儲一個hash類型test,他的屬性是name,屬性數據是yunjisuan
127.0.0.1:6379> hset test name yunjisuan
(integer) 1
#存儲一個hash類型test,他的屬性是age,屬性數據是35
127.0.0.1:6379> hset test age 35
(integer) 1
#存儲一個hash類型test,他的屬性是sex,屬性數據是non
127.0.0.1:6379> hset test sex nan
(integer) 1
#查看hash類型test的全部屬性的值
127.0.0.1:6379> hvals test
1) "yunjisuan"
2) "35"
3) "nan"
#查看hash類型test的全部屬性及屬性所對應的值
127.0.0.1:6379> hgetall test
1) "name"
2) "yunjisuan"
3) "age"
4) "35"
5) "sex"
6) "nan"
複製代碼

開啓redis的訂閱功能

複製代碼
#開啓redis的訂閱功能
redis-cli
127.0.0.1:6379> subscribe yunjisuan #開啓頻道名:yunjisuan的訂閱功能,可開啓多個窗口進行訂閱

#對頻道進行內容推送 只要在推送端推送,訂閱端就能看到
redis-cli
127.0.0.1:6379> publish yunjisuan 'welcome' #向頻道yunjisuan推送welcome
(integer) 2     #推送成功的人數
127.0.0.1:6379> publish yunjisuan '很高興'
(integer) 2
127.0.0.1:6379> publish yunjisuan 'welcome'
(integer) 3
複製代碼

 #####################################################################################

redis多實例

建立redis的存儲目錄

複製代碼
vim /usr/local/redis/conf/redis.conf    #修改redis的配置文件
dir /data/redis/                  #將存儲路徑配置修改成/data/redis/
  
mkdir -p /data/redis              #建立存儲目錄 redis-server /usr/local/redis/conf/redis.conf      #啓動redis redis-cli -a 123456        #登陸redis 127.0.0.1:6379> set name2 xixi    #插入數據 OK 127.0.0.1:6379> save #保存數據 [3456] 08 Oct 04:39:05.169 * DB saved on disk OK 127.0.0.1:6379> quit    #退出redis

ls /data/redis/      #查看保存的文件
dump.rdb redis.log     #rdb快照及日誌
複製代碼

建立redis多實例的存儲目錄及文件

複製代碼
#建立redis多實例存儲目錄
mkdir -p /data/6380/data
mkdir -p /data/6381/data
#建立redis多實例配置文件
cp /usr/local/redis/conf/redis.conf /data/6380/
cp /usr/local/redis/conf/redis.conf /data/6381/ #修改多實例配置文件的數據存儲路 徑佔用端口 pid文件位置
vim /data/6380/redis.conf 
dir /data/6380/data
port 6380
pidfile /data/6380/redis_6380.pid
appendonly yes

vim /data/6381/redis.conf 
dir /data/6381/data
port 6381
pidfile /data/3381/redis_6381.pid
appendonly yes
複製代碼

啓動redis多實例進程

複製代碼
redis-server /usr/local/redis/conf/redis.conf
redis-server /data/6380/redis.conf redis-server /data/6381/redis.conf
netstat -anpt|grep redis
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 1544/redis-server 0
tcp 0 0 0.0.0.0:6380 0.0.0.0:* LISTEN 1508/redis-server 0
tcp 0 0 0.0.0.0:6381 0.0.0.0:* LISTEN 1513/redis-server 0
複製代碼

查看多實例文件夾目錄樹一覽

複製代碼
tree /data/
/data/
├── 6380 #redis實例6380啓動目錄
│   ├── data        #redis實例6380數據目錄
│   │   └── appendonly.aof          #redis實例6380的數據持久化日誌(記錄了數據庫的修改,相似binlog)
│   ├── redis_6380.pid       #redispid文件
│   └── redis.conf       #redis實例6380數據存儲文件 ├── 6381
│   ├── data
│   │   └── appendonly.aof
│   └── redis.conf
└── redis
    ├── dump.rdb
    ├── redis_6379.pid
    └── redis.log
複製代碼

appendonly.aof實際上裏面記錄的是咱們對redis數據庫的修改記錄,這點相似於MySQL的binlog日誌。

Redis主從同步

 Redis主從同步特色

  1. 一個master能夠擁有多個slave
  2. 多個slave能夠鏈接同一個master,還能夠鏈接到其餘slave
  3. 主從複製不會阻塞master,在同步數據時,master能夠繼續處理client請求。
  4. 提升系統的伸縮性

Redis主從同步的過程

  1. 配置好slave服務器鏈接master後,slave會創建和master的鏈接,而後發送sync命令。
  2. 不管是第一次同步創建的鏈接仍是鏈接斷開後的從新鏈接,master都會啓動一個後臺進程,將數據庫快照保存到磁盤文件中,同時master主進程會開始收集新的寫命令並緩存起來。
  3. 當後臺進程完成寫磁盤文件後,master就將快照文件發送給slave,slave將文件保存到磁盤上,而後加載到內存將數據庫快照恢復到slave上。
  4. slave完成快照文件的恢復後,master就會把緩存的命令都轉發給slave,slave更新內存數據庫。
  5. 後續master收到的寫命令都會經過開始創建的鏈接發送給slave。從master到slave的同步數據的命令和從client到master發送的命令使用相同的協議格式。當master和slave的鏈接斷開時,slave能夠自動從新創建鏈接。若是master同時收到多個slave發來的同步鏈接命令,只會使用啓動一個進程來寫數據庫鏡像,而後發送給全部slave。

Redis的主從同步具備明顯的分佈式緩存特色:

(1)一個master能夠有多個slave,一個slave下面還能夠有多個slave 
(2)slave不只能夠鏈接到master,slave也能夠鏈接其餘slave造成樹狀。 
(3)主從同步不會阻塞master,可是會阻塞slave。也就是說當一個或多個slave與master進行初次同步數據時,master能夠繼續處理client發來的請求。相反slave在初次同步數據時則會阻塞不能處理client的請求。 
(4)主從同步能夠用來提升系統的可伸縮性,咱們能夠用多個slave專門處理client端的讀請求,也能夠用來作簡單的數據冗餘或者只在slave上進行持久化從而提高集羣的總體性能。 
(5)對於老版本的redis,每次重連都會從新發送全部數據。

 Redis主動同步設置方法

 有兩種方式能夠用來完成進行主從Redis服務器的同步設置。都須要在slave服務器上進行,指定slave須要鏈接的Redis服務器(多是master,也多是slave)。

redis的主從同步,不用修改master任何配置 只須要在redis-slave上指定master的IP地址便可

1在redis.conf配置文件中設置

經過簡單的配置slave(master端無需配置),用戶就能使用redis的主從複製 
咱們讓端口6379的redis作master;端口6380的redis作slave

#修改/data/6380/redis.conf的配置文件
slaveof 192.168.50.167 6379 #指定主master的IP和端口
masterauth 123456                 #在此處添加本行內容,指定驗證的密碼
#重啓服務

當再次啓動從庫時日誌文件出現以下信息:

複製代碼
Server initialized                    #服務器初始化
 DB loaded from append only file: 0.000 seconds   #數據從磁盤加載0秒
 Ready to accept connections              #準備接受鏈接
 Connecting to MASTER 192.168.50.167:6379       #鏈接到master 192.168.200.165:6379
 MASTER <-> SLAVE sync started              #開始主從同步
 Non blocking connect for SYNC fired the event.      #這是一個不阻塞事件
 Master replied to PING, replication can continue... #master答應了ping 同步開始
 Partial resynchronization not possible (no cached master) #部分同步不可能(master沒有緩存主文件)
 Full resync from master: 42a28d64ff5c8cb992b3139a98463ec37151accc:140   #從master同步所有數據
 MASTER <-> SLAVE sync: receiving 304 bytes from master    #從master接收到304字節數據
 MASTER <-> SLAVE sync: Flushing old data           #刷新舊數據
 MASTER <-> SLAVE sync: Loading DB in memory               #加載數據到內存 
 MASTER <-> SLAVE sync: Finished with success               #同步完成 
 Background append only file rewriting started by pid 1957  #AOF重寫
 AOF rewrite child asks to stop sending diffs. 
 Parent agreed to stop sending diffs. Finalizing AOF...
 Concatenating 0.00 MB of AOF diff received from parent.
 SYNC append only file rewrite performed 
 AOF rewrite: 0 MB of memory used by copy-on-write
 Background AOF rewrite terminated with success               #AOF重寫成功
 Residual parent diff successfully flushed to the rewritten AOF (0.00 MB) 
 Background AOF rewrite finished successfully                 #AOF重寫完畢
複製代碼
複製代碼
主庫log日誌信息

#從192.168.50.167:6380請求同步
26003:M 11 Aug 14:14:55.342 * Slave 192.168.50.167:6380 asks for synchronization #從192.168.50.167:6380請求完整的從新同步 26003:M 11 Aug 14:14:55.342 * Full resync requested by slave 192.168.50.167:6380 #master啓動bgsave與目標的磁盤進行同步 26003:M 11 Aug 14:14:55.342 * Starting BGSAVE for SYNC with target: disk #後臺保存rdb的進程的pid號爲26128 26003:M 11 Aug 14:14:55.342 * Background saving started by pid 26128 #rdb文件已經保存到了磁盤 26128:C 11 Aug 14:14:55.344 * DB saved on disk #rdb寫時複製使用了0MB的內存 26128:C 11 Aug 14:14:55.344 * RDB: 0 MB of memory used by copy-on-write #後臺保存成功 26003:M 11 Aug 14:14:55.414 * Background saving terminated with success #與從192.168.50.167:6380同步成功 26003:M 11 Aug 14:14:55.415 * Synchronization with slave 192.168.50.167:6380 succeeded
複製代碼
redis-cli slaveof no one              #中止主從同步
redis-cli slaveof 192.168.50.167 6379    #啓動主從同步

 redis主從同步相關配置參數解釋

複製代碼
slaveof 192.168.0.135 6379 #用於標識master的鏈接IP及端口號
masterauth 123456                      #若是master設置了鏈接密碼,這裏要寫上
slave-serve-stale-data yes              #若是設置yes,那麼一旦從庫鏈接不上主庫,從庫繼續響應客戶端發來的請求並回復,可是回覆的內容有多是過時的。若是no,那麼slave會應答一個錯誤提示,就不提供訪問了。
slave-read-only yes                    #yes:從庫被設置爲只能讀
repl-backlog-size 1mb                   #用於同步的backlog大小,用於從庫增量同步
slave-priority 100                      #slave的優先級
複製代碼

查看redis各項參數的方法

複製代碼
info           #查看各項信息 info cpu            #查看CPU信息 info memory         #查看內存信息 info memory         #查看內存信息 
info replication #查看同步信息
role:master #本redis是主
  slave0:ip=192.168.0.135,port=6380,state=online,offset=11972,lag=1 #主庫ip,端口,狀態,偏移量等
複製代碼

redis的高級特性

1.redis數據過時設置及過時機制

Redis支持按key設置過時時間,過時後值將被刪除(在客戶端看來是被刪除了的) 
用TTL命令能夠獲取某個key值的過時時間(-1表示永久不過時)

127.0.0.1:6379> TTL name    #查看key過時時間(-1爲永久不過時,-2爲已通過期)
(integer) -1

給key值設置6秒過時時間

複製代碼
127.0.0.1:6379> expire wk 6     #設置key值wk6秒過時時間
(integer) 1
127.0.0.1:6379> TTL wk
(integer) 2
127.0.0.1:6379> TTL wk
(integer) 1
127.0.0.1:6379> TTL wk
(integer) 0
127.0.0.1:6379> TTL wk        #已過時 過時的key是沒法獲取value的
(integer)
-2
複製代碼

2.redis持久化

Redis的全部數據都存儲在內存中,可是他也提供對這些數據的持久化

redis是一個支持持久化的內存數據庫,也就是說redis須要常常將內存中的數據同步到磁盤來保證持久化。redis支持兩種持久化方式,一種是Snapshotting(快照)也是默認方式,另外一種是Append-only file(縮寫aof)的方式。

①數據快照

複製代碼
#與rdb相關的配置文件信息
dir /data/redis/ #dir爲rdb存儲的路徑 dbfilename dump.rdb #rdb存儲文件的名字
save 900 1      #900 秒內若是超過1個key被修改,則發起快照保存
save 300 10     #300 秒內若是超過10個key被修改,則發起快照保存
save 60  10000  #60 秒內若是超過10000個key被修改,則發起快照保存
rdbcompression no   #rdb壓縮最好關閉,影響cpu
複製代碼

介紹詳細的快照保存過程:

redis調用fork,如今有了子進程和父進程. 

父進程繼續處理client請求,子進程負責將內存內容寫入到臨時文件。因爲Linux的寫時複製機制(copy on write)父子進程會共享相同的物理頁面,當父進程處理寫請求時Linux會爲父進程要修改的頁面建立副本,而不是寫共享的頁面。因此子進程地址空間內的數據是fork時的整個數據庫的一個快照。

當子進程將快照寫入臨時文件完畢後,用臨時文件替換原來的快照文件,而後子進程退出。client也可使用save或者bgsave命令通知redis作一次快照持久化。save操做是在主線程中保存快照的,因爲redis是用一個主線程來處理全部client的請求,這種方式會阻塞全部client請求。因此不推薦使用,bgsave開啓一個子進程所以不會阻塞。另外一點須要注意的是,每次快照持久化都是將內存數據完整寫入到磁盤一次,並非增量的只同步變動數據。若是數據量大的話,並且寫操做比較多,必然會引發大量的磁盤io操做,可能會嚴重影響性能.

數據快照的原理是將整個Redis中存的全部數據一遍一遍的存到一個擴展名爲rdb的數據文件中。經過SAVE命令能夠調用這個過程。

redis關閉時,redis自動進行RDB文件的保存 啓動時會讀取RDB文件.若是沒有找到RDB文件則數據丟失.

 

設置開啓或者關閉rdb存儲

複製代碼
方法一:
vim /usr/local/redis/conf/redis.conf
save "" #關閉rdb
save 60 10000           #開啓rdb
save 300 10          
save 900 1 

方法二:
redis-cli config set save "" #關閉rdb存儲
redis-cli config rewrite      #配置保存
redis-cli config set save "180 1 120 10 60 10000" #開啓rdb
redis-cli config rewrite      #配置保存    
複製代碼

 

②Append-Only File(追加式的操做日誌)

redis的appendonly(aof)持久化存儲會把用戶每次的操做都記錄到文件中(相似mysqlbinlog)

因爲快照方式是在必定間隔時間作一次的,因此若是redis意外down掉的話,就會丟失最後一次快照後的全部修改。若是應用要求不能丟失任何修改的話,能夠採用aof持久化方式。

aof比快照方式有更好的持久化性,是因爲在使用aof持久化方式時,redis會將每個收到的寫命令都經過write函數追加到文件中(默認是appendonly.aof)。當redis重啓時會經過從新執行文件中保存的寫命令來在內存中重建整個數據庫的內容.固然因爲os會在內核中緩存write作的修改,因此可能不是當即寫到磁盤上。這樣aof方式的持久化也仍是有可能會丟失部分修改。不過咱們能夠經過配置文件告訴redis咱們想要經過fsync函數強制os寫入到磁盤的時機。有三種方式以下(默認是:每秒fsync一次)

appendonly yes      #啓用aof持久化方式 no關閉
appendfsync always   #收到寫命令就當即寫入磁盤,最慢,可是保證徹底的持久化
appendfsync everysec  #每秒鐘寫入磁盤一次,在性能和持久化方面作了很好的折中
appendfsync no     #徹底依賴os,性能最好,持久化沒保證

aof引起的問題:

aof的方式也同時帶來了另外一個問題。持久化文件會變得愈來愈大.例如咱們調用incr test命令100次,文件中必須保存所有的100條命令,其實有99條都是多餘的。由於要恢復數據庫的狀態其實文件中保存一條set test 100 就夠了。爲了壓縮aof的持久化文件。redis提供了bgrewriteaof命令。收到此命令redis將使用與快照相似的方式將內存中的數據以命令的方式保存到臨時文件中,最後替換原來的文件。

過程:

  1. redis調用fork,如今有父子兩個進程
  2. 子進程根據內存中的數據庫快照,往臨時文件中寫入重建數據庫狀態的命令。
  3. 父進程繼續處理client請求,除了把寫命令寫入到原來的aof文件中。同時把收到的寫命令緩存起來.這樣就能保證若是子進程重寫失敗的話並不會出問題。
  4. 當子進程把快照內容寫入已命令方式寫到臨時文件中後,子進程發信號通知父進程。而後父進程把緩存的寫命令也寫入到臨時文件。
  5. 如今父進程可使用臨時文件替換老的aof文件,並重命令名,後面收到的寫命令也開始往新的aof文件中追加。
vim /data/6380/redis.conf 
appendonly yes
auto-aof-rewrite-percentage 100 #當100%達到最小大小的時候纔會執行重寫
auto-aof-rewrite-min-size 64mb  #自動重寫aof文件的最小大小

 ##########################################################################################

  Redis的服務器信息狀態信息查看

Redis的提供了一個信息命令查看Redis的服務器的信息,相似的Linux提供一個頂級命令查看系統的信息

redis-cli info
複製代碼
# Server                             #服務器的信息
redis_version:4.0.10    #redis服務器版本
redis_git_sha1:00000000      #Git SHA1
redis_git_dirty:0 #Git dirty flag
redis_build_id:d2228e273f4aff2f       #redis build id
redis_mode:standalone                 #運行模式,單機或集羣 
os:Linux 3.10.0-862.el7.x86_64 x86_64 #redis服務器宿主機操做系統
arch_bits:64        #架構64位
multiplexing_api:epoll               #redis所使用的事件處理模型
atomicvar_api:atomic-builtin        
gcc_version:4.8.5 #編譯redis時gcc版本 process_id:6816 #redis服務器進程的pid
run_id:3f3ec65cf6ce6c4307d23f8ce5e1c437c31cde58 #redis服務器的隨機標識符(sentinel和集羣)
tcp_port:6379                    #redis服務器監聽端口
uptime_in_seconds:7437 #redis服務器啓動總時間,單位秒
uptime_in_days:0 #redis服務器啓動總時間,單位天
hz:10                               #redis內部調度頻率(關閉timeout客戶端,刪除過時key)
lru_clock:8197344       #自增時間,用於LRU管理
executable:/root/redis-server
config_file:/usr/local/redis/conf/redis.conf       #配置文件路徑

# Clients                         #已鏈接客戶端信息
connected_clients:1 #已經鏈接客戶端數量(不包括slave鏈接的客戶端)
client_longest_output_list:0 #當前鏈接的客戶端當中,最長的輸出列表  
client_biggest_input_buf:0 #當前客戶端當中,最大輸入緩存。
blocked_clients:0                    #正在等待阻塞命令的客戶端數量


# Memory                          #內存信息
used_memory:2995728 #由redis分配器分配的內存總量,單位字節
used_memory_human:2.86M #以可讀方式返回redis已分配的內存總量
used_memory_rss:4636672              #從操做系統角度,返回redis已分配內存總量
used_memory_rss_human:4.42M #以可讀方式返回redis已分配的內存總量
used_memory_peak:15517016 #redis的內存消耗峯值(以字節爲單位)
used_memory_peak_human:14.80M #以可讀方式返回redis內存消耗峯值
used_memory_peak_perc:19.31%
used_memory_overhead:1934516
used_memory_startup:786608
used_memory_dataset:1061212
used_memory_dataset_perc:48.04%
total_system_memory:2229866496
total_system_memory_human:2.08G
used_memory_lua:37888 #lua引擎所使用的內存大小(單位字節)
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.55 #used_memory_rss和used_memory比率,小於1表示使用了swap,大於1表示碎片多,redis進行增長刪除的動做,會引發內存碎片化
mem_allocator:jemalloc-4.0.3         #編譯時指定的redis的內存分配器。越好的分配器內存碎片化率越低,低版本建議升級
active_defrag_running:0
lazyfree_pending_objects:0

# Persistence                     #rdb和aof的持久化相關信息              
loading:0   #服務器是否正在載入持久化文件
rdb_changes_since_last_save:0 #有多少個已經寫入的命令還未被持久化
rdb_bgsave_in_progress:0 #服務器是否正在建立rdb文件
rdb_last_save_time:1534918159 #已經有多長時間沒有進行持久化了
rdb_last_bgsave_status:ok            #最後一次的rdb持久化是否成功
rdb_last_bgsave_time_sec:0 #最後一次生成rdb文件耗時秒數
rdb_current_bgsave_time_sec:-1 #若是服務器正在建立rdb文件,那麼當前這個記錄就是建立操做耗時秒數
rdb_last_cow_size:438272
aof_enabled:1                       #是否開啓了aof
aof_rewrite_in_progress:0          #標識aof的rewrite操做是否進行中
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok         #上次bgrewriteaof操做的狀態
aof_last_write_status:ok            #上一次aof寫入狀態
aof_last_cow_size:581632
aof_current_size:2634673
aof_base_size:2473591
aof_pending_rewrite:0
aof_buffer_length:0
aof_rewrite_buffer_length:0
aof_pending_bio_fsync:0
aof_delayed_fsync:0
  
# Stats                          #通常統計信息
total_connections_received:220209 #新建立的連接個數,若是過多,會影響性能
total_commands_processed:447805 #redis處理的命令數
instantaneous_ops_per_sec:0         #redis當前的qps,redis內部較實時的每秒執行命令數
total_net_input_bytes:13682780 #redis網絡入口流量字節數
total_net_output_bytes:10737650 #redis網絡出口流量字節數
instantaneous_input_kbps:0.02 #redis網絡入口kps
instantaneous_output_kbps:0.00 #redis網絡出口kps
rejected_connections:0 #拒絕的鏈接個數,redis鏈接個數已經達到maxclients限制。
sync_full:1 #主從徹底同步成功次數
sync_partial_ok:0                 #主從部分同步成功次數
sync_partial_err:1                  #主從部分同步失敗次數
expired_keys:0                    #運行以來過時的key的數量
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0 #運行以來剔除(超過maxmemory)的key的數量
keyspace_hits:0                     #命中次數
keyspace_misses:0 #沒命中次數
pubsub_channels:0 #當前使用中的頻道數量
pubsub_patterns:0 #當前使用的模式數量
latest_fork_usec:401
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Replication                #主從信息
role:master
connected_slaves:1
slave0:ip=192.168.50.167,port=6380,state=online,offset=7672755,lag=0
master_replid:2757c33a80f71d262335ecb6ce2c6fdca96ee09e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:7672755 #主從同步偏移量(經過主從對比判斷主從同步是否一致)
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:6624180
repl_backlog_histlen:1048576

# CPU
used_cpu_sys:23.63
used_cpu_user:13.16
used_cpu_sys_children:0.31
used_cpu_user_children:0.14

# Cluster              #集羣相關信息
cluster_enabled:0

# Keyspace           #數據庫相關信息
db0:keys=1,expires=0,avg_ttl=0         #db0的key數量以及帶有生存週期的key的個數,平均存活時間
                 
複製代碼

 ################################################################################################3

自動故障轉移機制

  • redis目前只支持主從複製備份(不支持主主複製),當主redis掛了,從redis只能提供讀服務,沒法提供寫服務。因此,還得想辦法,當主redis掛了,讓從redis升級成爲主redis。
  • 這就須要自動故障轉移,redis sentinel帶有這個功能,當一個主redis不能提供服務時,redis sentinel能夠將一個從redis升級爲主redis,並對其餘從redis進行配置,讓他們使用新的主redis進行復製備份。
  • Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案,當用Redis作Master-slave的高可用方案時,假如master宕機了,Redis自己(包括它的不少客戶端)都沒有實現自動進行主備切換,而Redis-sentinel自己也是一個獨立運行的進程,它能監控多個master-slave集羣,發現master宕機後能進行自動切換。它的主要功能有如下幾點
  • 實時地監控redis是否按照預期良好地運行;
  • 若是發現某個redis節點運行出現情況,可以通知另一個進程(例如它的客戶端);
  • 可以進行自動切換。當一個master節點不可用時,可以選舉出master的多個slave(若是有超過一個slave的話)中的一個來做爲新的master,其餘的slave節點會將它所追隨的master的地址改成被提高爲master的slave的新地址。

 

sentinel 互相監控架構                        redis一主兩從架構  

redis的主從複製部署

這裏使用三臺服務器,每臺服務器上開啓一個redis-server和redis-sentinel服務,redis-server端口爲8000,redis-sentinel的端口爲7000,修改默認端口是安全的第一步。

redis-server 說明 redis-sentinel
192.168.50.168: 8000 redis-master 192.168.50.168:7000
192.168.50.166: 8000 redis-slave1 192.168.50.166:7000
192.168.50.169 :8000 redis-slave2 192.168.50.168:7000

redis.conf配置文件修改

#redis-master 配置文件:
port 8000            #設置端口號 daemonize yes         #是否後臺運行 bind 0.0.0.0          #容許訪問IP pidfile /var/run/redis-8000.pid    #PID文件存放位置 logfile /var/log/redis/redis-8000.log    #log日誌存放位置
複製代碼
#redis-slave 配置文件:
port 8000
daemonize yes
bind 0.0.0.0
pidfile /var/run/redis-8000.pid
logfile /var/log/redis/redis-8000.log
slaveof 192.168.200.132 8000 #比redis主多這行 指定主masterIP及端口
masterauth 123456        #驗證master端的redis密碼
複製代碼

啓動三臺redis

redis-server /usr/local/redis/conf/redis.conf

redis的高可用部署(redis-sentinel)

修改sentinel.conf配置文件  三個服務端配置文件同樣,啓服務後每一個配置文件都有變更,會生成惟一的內容

複製代碼
vim /usr/local/redis/conf/sentinel.conf
21   port 7000      #sentinel端口              
69   sentinel monitor master7000 192.168.50.168 8000 2
98   sentinel down-after-milliseconds master7000 5000
106 sentinel parallel-syncs master7000 1
131 sentinel failover-timeout master7000 15000
複製代碼

配置文件說明

    • sentinel monitor master8000 192.168.200.132 8000 2 
      • master8000:監控的主節點名字(隨便寫)
      • 192.168.200.132 8000 :主節點的IP和端口
      • 2:一共有兩臺Sentinel發現有問題就會發生故障轉移
    • sentinel down-after-milliseconds master8000 5000(5秒) 
      • 當master8000節點宕機後多久進行檢查
    • sentinel parallel-syncs master8000 1 
      • 設定sentinel併發仍是串行,1表明每次只能複製一個,能夠減輕master壓力
    • sentinel failover-timeout master8000 15000(15秒) 
      • 表示故障轉移的超時時間

啓動redis-sentinel

複製代碼
#三臺都啓動
redis-sentinel /usr/local/redis/conf/sentinel.conf & #啓動之後,查看sentinel信息
redis-cli -p 7000 info sentinel                #sentinel的端口號啓動
# Sentinel 
sentinel_masters:1 #1個master
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=master7000,status=ok,address=192.168.50.168:8000,slaves=2,sentinels=3             
#master ip 端口 2個slaves   3個sentinel
複製代碼

redis-sentinel的VIP漂移

咱們可使用redis sentinel的一個參數client-reconfig-script,這個參數配置執行腳本,sentinel在作failover的時候會執行這個腳本,而且傳遞6個參數<master-name>,<role>,<state>,<from-ip>,<from-port>,<to-ip>,<to-port>,其中`<to-ip>是新主redis的IP地址,能夠在這個腳本里作VIP漂移操做.

複製代碼
#在sentinel.conf裏增長一句話
[root@localhost ~]# sed -n '170,175p' /usr/local/redis/conf/sentinel.conf
# CLIENTS RECONFIGURATION SCRIPT
#
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script master7000 /usr/local/redis/notify_master6800.sh
#指定漂移腳本的位置
# When the master changed because of a failover a script can be called
in #寫一個漂移腳本 vim /usr/local/redis/notify_master6800.sh #!/bin/bash MASTER_IP=$6       #第六個參數就是sentinel傳入進行來的新master的IP LOCAL_IP="192.168.50.168"        #本地IP VIP="192.168.50.244"      `    #VIP NETMASK="24"               #子網掩碼 INTERFACE="eth0"             #網卡名 if [[ "${MASTER_IP}" == "${LOCAL_IP}" ]];then /usr/sbin/ip addr add ${VIP}/${NETMASK} dev ${INTERFACE} /usr/sbin/arping -q -c 3 -A ${VIP} -I ${INTERFACE} exit 0 else /usr/sbin/ip addr del ${VIP}/${NETMASK} dev ${INTERFACE} exit 0 fi exit 1
複製代碼
複製代碼
#給腳本加x權限
chmod +x /usr/local/redis/notify_master6800.sh 
#從新啓動全部的redis-sentinel進程
pkill redis-sentinel
redis-sentinel /usr/local/redis/conf/sentinel.conf
#第一次時手動給master添加VIP
ip addr add 192.168.50.244/24 dev eth0
#讓ip地址即刻生效
arping -q -c 3 -A 192.168.50.244 -I eth0
複製代碼

 ####################################################################################

master禁用數據持久化,只在slave上配置數據持久化

 

物理內存+虛擬內存不足,這個時候dump一直死着,時間久了機器掛掉

當Redis物理內存使用超過內存總容量的3/5時就會開始比較危險了,就開始作swap,內存碎片大
當達到最大內存時,會清空帶有過時時間的key,即便key未到過時時間。

redis優化

1.redis安全

①爲redis客戶端設置外部連接密碼

警告: 
由於redis速度至關快,因此在一臺比較好的服務器下,一個外部的用戶能夠在1秒內進行上萬次的密碼嘗試,這意味着你須要指定很是很是強大的密碼來防止暴力破解。

複製代碼
方法一:
vim /usr/local/redis/conf/redis.conf                 #修改redis配置文件,添加密碼
requirepass 123456 #重啓redis
redis-cli shutdown
redis-server /usr/local/redis/conf/redis.conf
方法二:
#交互式登錄redis設置密碼
redis-cli                        #登陸redis
config set requirepass 123456 #設置密碼 
config rewrite              #將配置重寫進行保存

特別提示: redis沒有用戶的概念,只能設置鏈接密碼,而且redis的鏈接速度很是快。所以密碼須要設置的很複雜才安全。
複製代碼

②將危險的命令更名  Redis禁用屏蔽危險命令

FLUSHALL和FLUSHDB會清除redis的數據,比較危險 
KEYS在鍵過多的時候使用會阻塞業務請求

複製代碼
#修改配置文件
vim /usr/local/redis/conf/redis.conf
rename-command set "sset"        #將set修改成sset    
rename-command keys ""          #屏蔽掉keys命令不使用
rename-command FLUSHALL ""        #將命令更名成空
rename-command FLUSHDB ""         #將命令更名成空

 

 
複製代碼

系統參數優化調整 

(1)調整系統文件描述符

echo "* - nofile 10240" >> /etc/security/limits.conf    #設置系統文件描述符
bash          #刷新                                     ulimit
-n        #查看系統文件描述符

(2)調整系統的TCP鏈接數

echo "net.core.somaxconn = 10240" >> /etc/sysctl.conf   #修改配置文件設置TCP鏈接數
sysctl -p          #查看tcp鏈接數
net.core.somaxconn = 10240

(3)調整系統內存分配策略

echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf     #調整內存分配策略當redis定義內存將要滿時,搶佔系統內存
sysctl -p

(4)關閉系統內核的巨大內存頁支持

複製代碼
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local     #設爲開機自啓動
echo 'echo never > /sys/kernel/mm/transparent_hugepage/defrag' >> /etc/rc.local      
複製代碼

Redis最大內存設置和刪除算法

#默認對內存無限制
set maxmemory 1M       #限制1M get maxmemory          #查看

可選擇的刪除算法

複製代碼
volatile-lru: 
使用LRU算法刪除鍵(key須要設置過時時間)
volatile-random: 
隨機刪除鍵(key須要設置過時時間)
volatile-ttl: 
刪除ttl最小的鍵(key須要設置過時時間)
allkeys-lru: 
使用LRU算法刪除鍵(全部key)
allkeys-random: 
隨機刪除鍵(全部key)
noeviction: 
不進行任何的操做,只返回錯誤,默認
複製代碼
redis-cli config get maxmemory-policy     #查看內存清理算法 1) "maxmemory-policy"
2) "noeviction"                     #默認noeviction

 #############################################################################################

Redis集羣

 Redis集羣是一個能夠在多個Redis節點之間進行數據共享的設施( installation )。

Redis集羣不支持那些須要同時處理多個鍵的Redis命令,由於執行這些命令須要在多個Redis節點之間移動數據,而且在高負載的狀況下,這些命令將下降Redis集羣的性能,並致使不可預測的行爲。

Redis集羣經過分區( partition )來提供必定程度的可用性( availability ) : 即便集羣中有一部分節點失效或者沒法進行通信,集羣也能夠繼續處理命令請求。

將數據自動切分( split) 到多個節點的能力。

當集羣中的一部分節點失效或者沒法進行通信時,仍然能夠繼續處理命令請求的能力。

Redis集羣數據共享

Redis集羣使用數據分片( sharding )而非一致性哈希(consistency hashing )來實現:一個Redis集羣包含16384個哈希槽( hash slot ), 數據庫中的每一個鍵都屬於這16384個哈希槽的其中一個, 集羣使用公式CRC16(key) % 16384來計算鍵key屬於哪一個槽,其中CRC16(key)語句用於計算鍵key的CRC16校驗和。
節點A負責處理0號至5500號哈希槽。
節點B負責處理5501號至11000號哈希槽。
節點C負責處理11001號至16384號哈希槽。

集羣的複製

爲了使得集羣在一部分節點下線或者沒法與集羣的大多數( majority )節點進行通信的狀況下,仍然能夠正常運做 ,Redis 集羣對節點使用了主從複製功能:集羣中的每一個節點都有1個至N個複製品( replica ),其中一個復 製品爲主節點( master ), 而其他的N-1個複製品爲從節點( slave)
在以前列舉的節點A、B、C的例子中,若是節點B下線了,那麼集羣將沒法正常運行, 由於集羣找不到節點來處理5501號至11000號的哈希槽。
假如在建立集羣的時候(或者至少在節點B下線以前),咱們爲主節點B添加了從節點B1, 那麼當主節點B下線的時候,集羣就會將 B1設置爲新的主節點,並讓它代替下線的主節點B,繼續處理5501號至11000號的哈希槽這樣集羣就不會由於主節點B的下線而沒法正常運做了。
不過若是節點B和B1都下線的話,Redis集羣仍是會中止運做。

 

運行機制

全部的redis節點彼此互聯(PINGPONG機制),內部使用二進制協議優化傳輸速度和帶寬.
節點的fail(失效)是經過集羣中超過半數的master節點檢測失效時才生效
客戶端與redis節點直連,不須要中間proxy層.客戶端不須要鏈接集羣全部節點,鏈接集羣中任何一個可用節點便可
把全部的物理節點映射到[0-16383]slot.上,cluster負責維護node<>slot<.>key

 

Redis集羣特性

redis cluster集羣方式支持主從自動切換 
redis cluster集羣只有一個庫,單例或者主從的話有多個庫 
redis cluster集羣去中心化,只要經過其中一個端口鏈接便可 
redis cluster集羣,只有一個db庫,不支持多庫

單實例的併發QBS每秒11萬次請求 讀寫差距不大 大約1W左右
單實例QBS不要超過5W 超過五萬擴容集羣 通常3W左右 7W是極限

redis自帶集羣搭建,通常使用三主三歷來構建(最少六臺機器)。

主機名 IP 端口 用途
redis-master 192.168.50.167 7000 redis-master01
    7001  redis-master02
    7002 redis-master03
redis-slave 192.168.50.168 8000 redis-slave01
    8001 redis-slave02
    8002 redis-slave03

實驗初始環境要求

systemctl stop firewalld    #關防火牆和selinux
systemctl disable firewalld
setenforce 0
sestatus

redis的基礎編譯部署和調優

複製代碼
yum -y install wget gcc gcc-c++ make tar openssl openssl-devel cmake
tar xf redis-4.0.10.tar.gz -C /usr/src/
cd /usr/src/redis-4.0.10/
make
make MALLOC=jemalloc
make PREFIX=/usr/local/redis install
cd /usr/local/redis/
mkdir -p /usr/local/redis/conf
cp /usr/src/redis-4.0.10/redis.conf /usr/local/redis/conf/    #redis配置文件
cp /usr/src/redis-4.0.10/sentinel.conf /usr/local/redis/conf/ #redis哨兵配置文件
cp /usr/src/redis-4.0.10/src/redis-trib.rb /usr/local/redis/bin/   #redis-cluster的集羣建立工具
ln -s /usr/local/redis/bin/* /usr/local/bin/
cp conf/redis.conf{,.bak} egrep -v "^$|^#" conf/redis.conf.bak > conf/redis.conf echo "* - nofile 10240" >> /etc/security/limits.conf echo "net.core.somaxconn = 10240" >> /etc/sysctl.conf echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf sysctl -p echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local echo 'echo never > /sys/kernel/mm/transparent_hugepage/defrag' >> /etc/rc.local
複製代碼

 redis主從集羣多實例配置

複製代碼
#在redis-master上操做
mkdir -p /data/redis-cluster
cd /data/redis-cluster
mkdir -p 7000 7001 7002
#在redis-slave上操做
mkdir -p /data/redis-cluster
cd /data/redis-cluster
mkdir -p 8000 8001 8002
複製代碼

修改redis-master的redis.conf配置文件,模板以下所示:

複製代碼
#redis-master不開任何持久化配置

vim
/data/redis-cluster/7000/redis.conf
bind
0.0.0.0        #鏈接爲全部 protected-mode yes
port
7000          #端口7000 tcp-backlog 1024 timeout 0 tcp-keepalive 0 daemonize yes        #開啓後端運行 supervised no pidfile /data/redis-cluster/7000/redis.pid      #PID文件存放位置 loglevel notice logfile "/data/redis-cluster/7000/redis.log"     #日誌文件存放位置 databases 16 always-show-logo yes
#save 900 1          #關閉rdb快照
#save 300 10
#save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /data/redis-cluster/7000/               #文件存放地址
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
appendonly no                    #關閉aof持久化
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble no
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
cluster-enabled yes              #開啓reids-cluster
cluster-config-file nodes.cong
cluster-node-timeout 5000


#潔淨板: bind 0.0.0.0 protected-mode yes port 7000 tcp-backlog 1024 timeout 0 tcp-keepalive 0 daemonize yes supervised no pidfile /data/redis-cluster/7000/redis.pid loglevel notice logfile "/data/redis-cluster/7000/redis.log" databases 16 always-show-logo yes stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir /data/redis-cluster/7000/ slave-serve-stale-data yes slave-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-disable-tcp-nodelay no slave-priority 100 lazyfree-lazy-eviction no lazyfree-lazy-expire no lazyfree-lazy-server-del no slave-lazy-flush no appendonly no appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes aof-use-rdb-preamble no lua-time-limit 5000 slowlog-log-slower-than 10000 slowlog-max-len 128 latency-monitor-threshold 0 notify-keyspace-events "" hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 aof-rewrite-incremental-fsync yes cluster-enabled yes cluster-config-file nodes.cong cluster-node-timeout 5000
複製代碼

#master2和3配置文件 只修改端口號 :%s#7000#7001#g   %s#7000#7002#g

cp /data/redis-cluster/7000/redis.conf /data/redis-cluster/7001/
cp /data/redis-cluster/7000/redis.conf /data/redis-cluster/7002/

從的配置文件也用這些,若是須要開啓主從複製

複製代碼
scp /data/redis-cluster/7000/redis.conf 192.168.50.168:/data/redis-cluster/8000/
scp /data/redis-cluster/7000/redis.conf 192.168.50.168:/data/redis-cluster/8001/
scp /data/redis-cluster/7000/redis.conf 192.168.50.168:/data/redis-cluster/8002/
#修改端口號  
複製代碼

啓動redis-master多實例

redis-server /data/redis-cluster/7001/redis.conf 
redis-server /data/redis-cluster/7002/redis.conf 
redis-server /data/redis-cluster/7000/redis.conf 

編譯安裝高ruby版本,Ruby版本須要大於等於2.2.2(yum安裝的不符合)

複製代碼
#redis-master和redis-slave都進行以下操做
wget --no-check-certificate 'https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.7.tar.gz'
tar xf ruby-2.2.7.tar.gz -C /usr/src/
cd /usr/src/ruby-2.2.7/
./configure && make && make install

ruby
--version ruby 2.2.7p470 (2017-03-28 revision 58194) [x86_64-linux] #在線安裝ruby的redis擴展 /usr/local/bin/gem install redis
Fetching: redis
-4.0.1.gem (100%) Successfully installed redis-4.0.1 Parsing documentation for redis-4.0.1 Installing ri documentation for redis-4.0.1 Done installing documentation for redis after 0 seconds 1 gem installed
複製代碼

使用redis自帶redis-trib.rb工具建立集羣

複製代碼
#在redis-master上操做
redis-trib.rb create 192.168.50.167:7000 192.168.50.167:7001 192.168.50.167:7002

>>> Creating cluster >>> Performing hash slots allocation on 3 nodes... Using 3 masters: 192.168.50.167:7000 192.168.50.167:7001 192.168.50.167:7002 M: 3f5ff40741abf362e2dad0b26c1ef817e98b3428 192.168.50.167:7000 slots:0-5460 (5461 slots) master M: 625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 192.168.50.167:7001 slots:5461-10922 (5462 slots) master M: 7a5ed824f23ca900917bec79c14507377c61506e 192.168.50.167:7002 slots:10923-16383 (5461 slots) master Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join.. >>> Performing Cluster Check (using node 192.168.50.167:7000) M: 3f5ff40741abf362e2dad0b26c1ef817e98b3428 192.168.50.167:7000 slots:0-5460 (5461 slots) master 0 additional replica(s) M: 7a5ed824f23ca900917bec79c14507377c61506e 192.168.50.167:7002 slots:10923-16383 (5461 slots) master 0 additional replica(s) M: 625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 192.168.50.167:7001 slots:5461-10922 (5462 slots) master 0 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. #兩個OK表示成功
複製代碼

查看集羣的信息

複製代碼
redis-cli -p 7000 cluster nodes
625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 192.168.50.167:7001@17001 master - 0 1535108491650 2 connected 5461-10922
3f5ff40741abf362e2dad0b26c1ef817e98b3428 192.168.50.167:7000@17000 myself,master - 0 1535108491000 5 connected 0-5460
7a5ed824f23ca900917bec79c14507377c61506e 192.168.50.167:7002@17002 master - 0 1535108490543 3 connected 10923-16383

ls /data/redis-cluster/7000/          

dump.rdb  nodes.cong  redis.conf  redis.log  redis.pid

cat /data/redis-cluster/7000/
nodes.cong          #信息保存在nodes.cong裏
625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 192.168.50.167:7001@17001 master - 0 1535108491650 2 connected 5461-10922

3f5ff40741abf362e2dad0b26c1ef817e98b3428 192.168.50.167:7000@17000 myself,master - 0 1535108491000 5 connected 0-5460
7a5ed824f23ca900917bec79c14507377c61506e 192.168.50.167:7002@17002 master - 0 1535108490543 3 connected 10923-16383
複製代碼

使用redis-cli去操做集羣,須要加入-c參數

redis-cli -c -p 7000        #隨便進入一個redis端口就可操做整個redis

 cluster集羣的重建

複製代碼
#刪除cluster集羣配置文件
rm -rf /data/redis-cluster/7000/nodes.cong
rm -rf /data/redis-cluster/7001/nodes.cong
rm -rf /data/redis-cluster/7002/nodes.cong

#刪除cluster集羣配置文件 redis
-cli -p 7000 shutdown redis-cli -p 7001 shutdown redis-cli -p 7002 shutdown
#啓動redis
-server redis-server /data/redis-cluster/7000/redis.conf redis-server /data/redis-cluster/7001/redis.conf redis-server /data/redis-cluster/7002/redis.conf
#從新建立redis
-cluster集羣
redis-trib.rb create 192.168.50.167:7000 192.168.50.167:7001 192.168.50.167:7002

 

複製代碼
複製代碼
ps -ef | grep cluster | grep -v grep
root      31952      1  0 22:32 ?        00:00:00 redis-server 0.0.0.0:7000 [cluster]
root      31957      1  0 22:32 ?        00:00:00 redis-server 0.0.0.0:7001 [cluster]
root      31962      1  0 22:32 ?        00:00:00 redis-server 0.0.0.0:7002 [cluster]
複製代碼

Redis Cluster集羣的故障自動切換

啓動redis-slave上全部的從庫

複製代碼
redis-server /data/redis-cluster/8000/redis.conf 
redis-server /data/redis-cluster/8001/redis.conf 
redis-server /data/redis-cluster/8002/redis.conf 

netstat
-antup | grep redis tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 51680/redis-server tcp 0 0 0.0.0.0:8001 0.0.0.0:* LISTEN 51685/redis-server tcp 0 0 0.0.0.0:8002 0.0.0.0:* LISTEN 51690/redis-server tcp 0 0 0.0.0.0:18000 0.0.0.0:* LISTEN 51680/redis-server tcp 0 0 0.0.0.0:18001 0.0.0.0:* LISTEN 51685/redis-server tcp 0 0 0.0.0.0:18002 0.0.0.0:* LISTEN 51690/redis-server
複製代碼

 redis-cluster集羣從庫的添加

複製代碼
redis-trib.rb add-node --slave 192.168.50.168:8000 192.168.50.167:7000          #添加第一個從8000對應的主爲7000
>>> Adding node 192.168.50.168:8000 to cluster 192.168.50.167:7000
>>> Performing Cluster Check (using node 192.168.50.167:7000)
M: 3f5ff40741abf362e2dad0b26c1ef817e98b3428 192.168.50.167:7000
   slots:0-5460 (5461 slots) master
   0 additional replica(s)
M: 7a5ed824f23ca900917bec79c14507377c61506e 192.168.50.167:7002
   slots:10923-16383 (5461 slots) master
   0 additional replica(s)
M: 625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 192.168.50.167:7001
   slots:5461-10922 (5462 slots) master
   0 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
Automatically selected master 192.168.50.167:7000
>>> Send CLUSTER MEET to node 192.168.50.168:8000 to make it join the cluster.
Waiting for the cluster to join....
>>> Configure node as replica of 192.168.50.167:7000.
[OK] New node added correctly.

redis-trib.rb add-node --slave 192.168.50.168:8001 192.168.50.167:7001            #添加第二個從8001對應的7001
>>> Adding node 192.168.50.168:8001 to cluster 192.168.50.167:7001
>>> Performing Cluster Check (using node 192.168.50.167:7001)
M: 625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 192.168.50.167:7001
   slots:5461-10922 (5462 slots) master
   0 additional replica(s)
S: 7a0f3052b2474b9080f0df1a3df562461ac94d30 192.168.50.168:8000
   slots: (0 slots) slave
   replicates 3f5ff40741abf362e2dad0b26c1ef817e98b3428
M: 7a5ed824f23ca900917bec79c14507377c61506e 192.168.50.167:7002
   slots:10923-16383 (5461 slots) master
   0 additional replica(s)
M: 3f5ff40741abf362e2dad0b26c1ef817e98b3428 192.168.50.167:7000
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
Automatically selected master 192.168.50.167:7001
>>> Send CLUSTER MEET to node 192.168.50.168:8001 to make it join the cluster.
Waiting for the cluster to join.
>>> Configure node as replica of 192.168.50.167:7001.
[OK] New node added correctly.

redis-trib.rb add-node --slave 192.168.50.168:8002 192.168.50.167:7002                #第三個添加的從8002對應的主7002
>>> Adding node 192.168.50.168:8002 to cluster 192.168.50.167:7002
>>> Performing Cluster Check (using node 192.168.50.167:7002)
M: 7a5ed824f23ca900917bec79c14507377c61506e 192.168.50.167:7002
   slots:10923-16383 (5461 slots) master
   0 additional replica(s)
S: 45f40c58756d690a6a687dca283a0274e4d1d0f3 192.168.50.168:8001
   slots: (0 slots) slave
   replicates 625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb
M: 3f5ff40741abf362e2dad0b26c1ef817e98b3428 192.168.50.167:7000
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
M: 625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 192.168.50.167:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 7a0f3052b2474b9080f0df1a3df562461ac94d30 192.168.50.168:8000
   slots: (0 slots) slave
   replicates 3f5ff40741abf362e2dad0b26c1ef817e98b3428
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
Automatically selected master 192.168.50.167:7002
>>> Send CLUSTER MEET to node 192.168.50.168:8002 to make it join the cluster.
Waiting for the cluster to join.
>>> Configure node as replica of 192.168.50.167:7002.
[OK] New node added correctly.
複製代碼

查看集羣全部節點的信息

複製代碼
redis-cli -p 7000 cluster nodes
45f40c58756d690a6a687dca283a0274e4d1d0f3 192.168.50.168:8001@18001 slave 625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 0 1535109423735 2 connected
625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 192.168.50.167:7001@17001 master - 0 1535109423535 2 connected 5461-10922
3f5ff40741abf362e2dad0b26c1ef817e98b3428 192.168.50.167:7000@17000 myself,master - 0 1535109424000 5 connected 0-5460
eaa15a35898137b02087581f2e910d18e0d7cecf 192.168.50.168:8002@18002 slave 7a5ed824f23ca900917bec79c14507377c61506e 0 1535109424747 3 connected
7a5ed824f23ca900917bec79c14507377c61506e 192.168.50.167:7002@17002 master - 0 1535109424239 3 connected 10923-16383
7a0f3052b2474b9080f0df1a3df562461ac94d30 192.168.50.168:8000@18000 slave 3f5ff40741abf362e2dad0b26c1ef817e98b3428 0 1535109422730 5 connected
複製代碼

redis的cluster集羣,不管是主庫仍是從庫均可以進行set和get。所以,在使用中咱們就不必都去主庫了。

查看主從cluster集羣key的分佈狀況

redis-cli -h 192.168.50.168 -c -p 8002 info Keyspace
# Keyspace
db0:keys=6,expires=0,avg_ttl=0

redis集羣的主從自動切換,主庫掛掉後,從自動變爲主

手動切換主從命令cluster failover

複製代碼
redis-cli -p 7000 shutdown      #手動宕掉主1
redis-cli -p 7001 cluster nodes    #查看狀態
eaa15a35898137b02087581f2e910d18e0d7cecf 192.168.50.168:8002@18002 slave 7a5ed824f23ca900917bec79c14507377c61506e 0 1535102657000 3 connected
45f40c58756d690a6a687dca283a0274e4d1d0f3 192.168.50.168:8001@18001 slave 625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 0 1535102656525 2 connected
3f5ff40741abf362e2dad0b26c1ef817e98b3428 192.168.50.167:7000@17000 master,fail - 1535102650269 1535102648861 1 disconnected    #7000掛掉了
7a5ed824f23ca900917bec79c14507377c61506e 192.168.50.167:7002@17002 master - 0 1535102656000 3 connected 10923-16383
625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 192.168.50.167:7001@17001 myself,master - 0 1535102656000 2 connected 5461-10922
7a0f3052b2474b9080f0df1a3df562461ac94d30 192.168.50.168:8000@18000 master - 0 1535102657000 4 connected 0-5460      #8000成爲了master #從新啓動7000端口的server,再次查看
redis-server /data/redis-cluster/7000/redis.conf
redis-cli -p 7001 cluster nodes
eaa15a35898137b02087581f2e910d18e0d7cecf 192.168.50.168:8002@18002 slave 7a5ed824f23ca900917bec79c14507377c61506e 0 1535102793234 3 connected
45f40c58756d690a6a687dca283a0274e4d1d0f3 192.168.50.168:8001@18001 slave 625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 0 1535102792225 2 connected
3f5ff40741abf362e2dad0b26c1ef817e98b3428 192.168.50.167:7000@17000 slave 7a0f3052b2474b9080f0df1a3df562461ac94d30 0 1535102791718 4 connected
7a5ed824f23ca900917bec79c14507377c61506e 192.168.50.167:7002@17002 master - 0 1535102792728 3 connected 10923-16383
625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 192.168.50.167:7001@17001 myself,master - 0 1535102792000 2 connected 5461-10922
7a0f3052b2474b9080f0df1a3df562461ac94d30 192.168.50.168:8000@18000 master - 0 1535102792000 4 connected 0-5460
#手動將redis-server 7000端口從新切換成主庫
redis-cli -p 7000 cluster failover
redis-cli -p 7001 cluster nodes
eaa15a35898137b02087581f2e910d18e0d7cecf 192.168.50.168:8002@18002 slave 7a5ed824f23ca900917bec79c14507377c61506e 0 1535102934425 3 connected
45f40c58756d690a6a687dca283a0274e4d1d0f3 192.168.50.168:8001@18001 slave 625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 0 1535102934526 2 connected
3f5ff40741abf362e2dad0b26c1ef817e98b3428 192.168.50.167:7000@17000 master - 0 1535102934000 5 connected 0-5460
7a5ed824f23ca900917bec79c14507377c61506e 192.168.50.167:7002@17002 master - 0 1535102933418 3 connected 10923-16383
625e0520c9dd87f0eaf28549daa0ee3f8f39ecbb 192.168.50.167:7001@17001 myself,master - 0 1535102934000 2 connected 5461-10922
7a0f3052b2474b9080f0df1a3df562461ac94d30 192.168.50.168:8000@18000 slave 3f5ff40741abf362e2dad0b26c1ef817e98b3428 0 1535102933000 5 connected
複製代碼

使用Python操做Redis Cluster集羣

 

複製代碼
yum -y install epel-release
yum -y install python2-pip
pip install redis-py-cluster
操做集羣的代碼
pwd
/server/scripts
cat redis_cluster.py 
# -*- coding:utf-8 -*-
from rediscluster import StrictRedisCluster
redis_nodes = [
        {'host':'192.168.200.231','port':7000},
        {'host':'192.168.200.231','port':7001},
        {'host':'192.168.200.231','port':7002},
        {'host':'192.168.200.232','port':8000},
        {'host':'192.168.200.232','port':8001},
        {'host':'192.168.200.232','port':8002}
        ]
redis_conn = StrictRedisCluster(startup_nodes=redis_nodes)
redis_conn.set('key_test','values_test')
print(redis_conn.get('key_test'))
[root@redis-master scripts]# python redis_cluster.py 
values_test
[root@redis-master scripts]# redis-cli -c -p 7002 get key_test
"values_test"
特別提示: 
若其中一個節點掛了,不影響功能的使用
複製代碼

分析Redis的全部key和key的大小

pip安裝rdbtools分析工具

[root@redis-master ~]# pip install rdbtools
[root@redis-master ~]# which rdb
/usr/bin/rdb

分析key及key的大小

運維需求,根據dump.rdb文件分析key和key的大小
rdb -c memory /data/redis-cluster/7000/dump.rdb > /root/memory.csv
cat /root/memory.csv | head
相關文章
相關標籤/搜索