学习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
相关文章
相关标签/搜索