一、redis介绍:
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)、Hash(哈希类型的映射表)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
二、特性:
- 速度快
- 数据存在内存当中
- c语言编写,5w行代码
- 单线程数据模型
- 持久化
- 多种数据类型
- 支持多种编辑语言
- 功能丰富
- 简单
- 主从复制
三、redis的安装
#解压安装
$ wget http://download.redis.io/releases/redis-5.0.4.tar.gz
$ tar xzf redis-5.0.4.tar.gz
$ cd redis-5.0.4
$ make
#启动
$ ./src/redis-server redis.conf
#试用
$ src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"
安装过程中遇到以下错误说明gcc-c++环境未安装,直接运行yum -y install gcc-c++先安装环境:
[root@localhost redis-5.0.4]# make
cd src && make all
make[1]: 进入目录“/opt/redis-5.0.4/src”
CC adlist.o
/bin/sh: cc: 未找到命令
make[1]: *** [adlist.o] 错误 127
make[1]: 离开目录“/opt/redis-5.0.4/src”
make: *** [all] 错误 2
遇到一下错误运行make distclean
[root@bogon redis-3.2.0]# make
cd src && make all
make[1]: 进入目录“/usr/local/redis-3.2.0/src”
CC adlist.o
In file included from adlist.c:34:0:
zmalloc.h:50:31: 致命错误:jemalloc/jemalloc.h:没有那个文件或目录
#include <jemalloc/jemalloc.h> ^
编译中断。
make[1]: *** [adlist.o] 错误 1
make[1]: 离开目录“/usr/local/redis-3.2.0/src”
make: *** [all] 错误 2
解决“jemalloc/jemalloc.h:没有那个文件或目录“问题,在进行编译(因为上次编译失败,有残留的文件)。直接运行make distclean命令。
客户端
四、redis命令
- http://doc.redisfans.com/
- SCAN 命令用于迭代当前数据库中的数据库键。
- SSCAN 命令用于迭代集合键中的元素。
- HSCAN 命令用于迭代哈希键中的键值对。
- ZSCAN 命令用于迭代有序集合中的元素(包括元素成员和元素分值)。
五、redis单线程
为什么这么快?
- 纯内存操作
- 非阻塞IO
- 避免线程切换和竞态消耗
如何使用?
- 拒绝长(慢)命令
- keys、flushall。。
- 一次只运行一个命令
六、redis存储机制
Redis存储机制分成两种Snapshot和AOF。无论是那种机制,Redis都是将数据存储在内存中。
Snapshot工作原理
是将数据先存储在内存,然后当数据累计达到某些设定的伐值的时候,就会触发一次DUMP操作,将变化的数据一次性写入数据文件(RDB文件)。
AOF 工作原理
是将数据也是先存在内存,但是在存储的时候会使用调用fsync来完成对本次写操作的日志记录,这个日志揭露文件其实是一个基于Redis网络交互协议的文本文件。AOF调用fsync也不是说全部都是无阻塞的,在某些系统上可能出现fsync阻塞进程的情况,对于这种情况可以通过配置修改,但默认情况不要修改。AOF最关键的配置就是关于调用fsync追加日志文件的平率,有两种预设频率,always每次记录进来都添加,everysecond 每秒添加一次。两个配置各有所长后面分析。由于是采用日志追加的方式来持久话数据,所以引出了第二个日志的概念:rewrite. 后面介绍它的由来。
存储模式性能和安全比较
1.性能
Snapshot方式的性能是要明显高于AOF方式的,原因有两点:
采用2进制方式存储数据,数据文件比较小,加载快速。
存储的时候是按照配置中的save策略来存储,每次都是聚合很多数据批量存储,写入的效率很好,而AOF则一般都是工作在实时存储或者准实时模式下。相对来说存储的频率高,效率却偏低。
2.数据安全
AOF数据安全性高于Snapshot存储,原因:
Snapshot存储是基于累计批量的思想,也就是说在允许的情况下,累计的数据越多那么写入效率也就越高,但数据的累计是靠时间的积累完成的,那么如果在长时间数据不写入RDB,但Redis又遇到了崩溃,那么没有写入的数据就无法恢复了,但是AOF方式偏偏相反,根据AOF配置的存储频率的策略可以做到最少的数据丢失和较高的数据恢复能力。
说完了性能和安全,这里不得不提的就是在Redis中的Rewrite的功能,AOF的存储是按照记录日志的方式去工作的,那么成千上万的数据插入必然导致日志文件的扩大,Redis这个时候会根据配置合理触发Rewrite操作,所谓Rewrite就是将日志文件中的所有数据都重新写到另外一个新的日志文件中,但是不同的是,对于老日志文件中对于Key的多次操作,只保留最终的值的那次操作记录到日志文件中,从而缩小日志文件的大小。这里有两个配置需要注意:
auto-aof-rewrite-percentage 100 (当前写入日志文件的大小占到初始日志文件大小的某个百分比时触发Rewrite)
auto-aof-rewrite-min-size 64mb (本次Rewrite最小的写入数据良)
两个条件需要同时满足。
七、redis的数据结构
字符串
缓存、计数器、分布式锁、分布式ID、、
HASH
存储用户信息、用户主页访问量
LIST
微博关注人微博时间轴列表
SET
赞、踩、标签
ZSET
排行榜
八、redis的主从模式
主从配置
主从机器一般是分开的两台机器,这里为了演示方便,使用了一台机器,所以配置文件中,处理端口的区分之外,还需要注意日志文件,数据库文件,pid文件等的区分。
启动redis命令
redis-server redis.conf
直接自定加载的配置文件即可
主机配置
复制一份redis.conf成redis-6379.conf。修改配置:
#演示方便,开放ip连接
bind 0.0.0.0
#后台运行
daemonize yes
#pid文件
pidfile /var/run/redis_6379.pid
dbfilename dump-6379.rdb
#日志文件
logfile "6379.log"
从机配置
复制一份redis.conf成redis-6380.conf。修改配置:
bind 0.0.0.0
port 6380
daemonize yes
pidfile /var/run/redis_6380.pid
dbfilename dump-6380.rdb
logfile "6380.log"
#slaveof表示作为从库的配置
slaveof 127.0.0.1 6379
#从库只能读操作
slave-read-only yes
查看redis的信息
redis-cli -p 6379 info replication
- 其中6379表示指定端口
- replication表示主从的信息
查看主库信息:
[root@izwz95t3hfncu7j54o7zefz src]# ./redis-cli -p 6379 info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=1183,lag=0
master_replid:32125185597f85a2155d187ccd57168cf6681395
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1183
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1183
查看从库信息:
[root@izwz95t3hfncu7j54o7zefz src]# ./redis-cli -p 6380 info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:1239
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:32125185597f85a2155d187ccd57168cf6681395
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1239
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1239
查看配置效果:复制成功!!
[root@izwz95t3hfncu7j54o7zefz src]# ./redis-cli -p 6379 set hello helloworld
OK
[root@izwz95t3hfncu7j54o7zefz src]# ./redis-cli -p 6380 get hello
"helloworld"
redis的高可用
sentinel启动命令
redis-sentinel sentinel.conf
sentinel机制
过程:
- 多个sentinel发现并确认master有问题
- 选举出一个sentinel作为领导
- 选出一个slave作为master
- 通知其余slave成为新的master的slave
- 通知客户端主从变化
- 等待老的master复活成为新的master的slave
创建sentinel.conf配置文件
- port 26379
- daemonize yes
- # sentinel announce-ip <ip>
- # sentinel announce-port <port>
- dir /opt/redis-5.0.4/data
- logfile "26379.log"
- sentinel monitor mymaster 127.0.0.1 6379 2
- # sentinel auth-pass <master-name> <password>
- sentinel down-after-milliseconds mymaster 30000
- sentinel parallel-syncs mymaster 1
- sentinel failover-timeout mymaster 180000
- # sentinel notification-script <master-name> <script-path>
配置文件说明:
1. port :当前Sentinel服务运行的端口
2. dir : Sentinel服务运行时使用的临时文件
3.sentinel monitor master001 192.168.110.101 6379 2:Sentinel去监视一个名为master001的主redis实例,这个主实例的IP地址为本机地址192.168.110.101,端口号为6379,而将这个主实例判断为失效至少需要2个 Sentinel进程的同意,只要同意Sentinel的数量不达标,自动failover就不会执行
4.sentinel down-after-milliseconds master001 30000:指定了Sentinel认为Redis实例已经失效所需的毫秒数。当实例超过该时间没有返回PING,或者直接返回错误,那么Sentinel将这个实例标记为主观下线。只有一个 Sentinel进程将实例标记为主观下线并不一定会引起实例的自动故障迁移:只有在足够数量的Sentinel都将一个实例标记为主观下线之后,实例才会被标记为客观下线,这时自动故障迁移才会执行
5.sentinel parallel-syncs master001 1:指定了在执行故障转移时,最多可以有多少个从Redis实例在同步新的主实例,在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长
6.sentinel failover-timeout master001 180000:如果在该时间(ms)内未能完成failover操作,则认为该failover失败
7.sentinel notification-script <master-name> <script-path>:指定sentinel检测到该监控的redis实例指向的实例异常时,调用的报警脚本。该配置项可选,但是很常用
三个定时任务
(1)每隔10s每个sentinel会对master节点和slave节点执行info命令
作用就是发现slave节点,并且确认主从关系,因为redis-Sentinel节点启动的时候是知道
master节点的,只是没有配置相应的slave节点的信息
(2)每隔两秒,sentinel都会通过master节点内部的channel来交换信息(基于发布订阅)
作用是通过master节点的频道来交互每个Sentinel对master节点的判断信息
(3) 每隔一秒每个sentinel对其他的redis节点(master,slave,sentinel)执行ping操作,对于master来说,若超过30s内没有回复,就对该master进行主观下线并询问其他的Sentinel节点是否可以客观下线
故障转移过程
1. 领导者选举
作用:选举出一个sentenel节点作为领导者去进行故障转移操作。
过程:
1). 每个做主观下线的sentinel节点向其他sentinel节点发送上面那条命令,要求将它设置为领导者。
2). 收到命令的sentinel节点如果还没有同意过其他的sentinel发送的命令(还未投过票),那么就会同意,否则拒绝。
3). 如果该sentinel节点发现自己的票数已经过半且达到了quorum的值,就会成为领导者。
4). 如果这个过程出现多个sentinel成为领导者,则会等待一段时间重新选举。
2. 选出新的master节点
redis sentinel会选一个合适的slave来升级为master,那么,如何选择一个合适的slave呢?顺序如下:
1). 选择slave-priority最高的slave节点(默认是相同)。
2). 选择复制偏移量最大的节点。
3). 如果以上两个条件都不满足,选runId最小的(启动最早的)。
3. 更改slave节点的master节点
当选举出新的master节点后,会将其余的节点变更为新的master节点的slave节点,如果原有的master节点重新上线,成为新的master节点的slave节点。
4. 通知客户端
当所有节点配置结束后,sentinel会通知客户端节点变更信息。
5. 客户端连接新的master节点
客户端收到节点信息后,会连接新的master节点。