概念:key-value 存储系统,是跨平台的非关系型数据库。
特点:
-
Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
-
Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
-
Redis支持数据的备份,即master-slave模式的数据备份。
-
性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
-
丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
-
原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
-
丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
五大数据结构:
String(字符串)
key--valuestring 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
Hash(哈希)
key对应(key-value)集合 key---filed---value
Redis hash 是一个键值(key=>value)对集合。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
每个 hash 可以存储 232 -1 键值对(40多亿)。
List(有序列表) 例如:rpush list 1 2 3 4
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。
Set(无序唯一集合)例如: sadd set1 a b c d
Redis 的 Set 是 string 类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个成员)。
zset(sorted set:有序唯一集合) 例如: zadd zset1 9 a 8 c 10 d 1 e
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。
事务
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做,所有指令要不全部执行要不全部不执行,失败也不会回滚
事务相关的几个命令:
1 | 取消事务,放弃执行事务块内的所有命令。 |
2 | 执行所有事务块内的命令。 |
3 | 标记一个事务块的开始。 |
4 | 取消 WATCH 命令对所有 key 的监视。 |
5 | WATCH key [key ...](实现乐观锁 ) 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。 Redis GEORedis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。 Redis GEO 操作方法有:
Redis 管道技术Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤:
Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。 例: $(echo -en "PING\r\n SET runoobkey redis\r\nGET runoobkey\r\nINCR visitor\r\nINCR visitor\r\nINCR visitor\r\n"; sleep 10) | nc localhost 6379 Redis持久化AOF(append only file) fork子进程,以日志形式记录每次写操作,将redis执行的所有指令记录下来,只许追加文件但不可以改写文件,redis启动时会读取该文件重新构建数据,即重启时候会执行日志中记录的所有写命令,效率低 RDB 生成.rdb结尾文件。redis单独fork一个子进程来持久化---将内存内容写入临时rdb文件----快照完成后替换原来快照文件,子进程退出----生成正式rdb文件。此方式效率高,适合大规模数据恢复。因为需要一定时间间隔操作,所以redis挂掉后最后一次操作数据不会被持久化 fork进程的时候会占用一定内存空间 |
Redis过期策略
定时过期:每秒10次一直扫描key,查看是否过期,消耗CPU,对内存友好
惰性策略:只有访问时候才会检查是否过期,容易造成大量冗余过期数据,对内存不友好
定期过期:定时去检查
Redis内存淘汰策略(缓存回收策略)
内存不足时候,释放空间:设置最大内存,四种淘汰机制:
1、淘汰最少访问的一些key(推荐 allkeys-lru)
2、随机淘汰一些
3、移除快过期的key
4、报错
Redis集群
常见集群分类:主从复制和分片集群
redis集群:主从复制,主从哨兵模式,客户端实现路由索引分片集群,中间件代理层分片集群,redis本身实现的cluster分片集群
主从配置:
配置conf文件
role:
master_host:
master_port:
...
哨兵模式:
原理机制:
三个定时任务
sentinel在内部有3个定时任务
1.每10秒每个sentinel会对master和slave执行info命令
这个任务达到两个目的:发现slave节点--------确认主从关系
2.每2秒每个sentinel通过master节点的channel交换信息(pub/sub)
master节点上有一个发布订阅的频道(__sentinel__:hello)。
sentinel节点通过__sentinel__:hello频道进行信息交换(对节点的"看法"和自身的信息),达成共识。
3.每1秒每个sentinel对其他sentinel和redis节点执行ping操作(相互监控)
这个其实是一个心跳检测,是失败判定的依据。
主观下线和客观下线
在redis-sentinel的conf文件里有这么两个配置:
1.sentinel monitor <masterName> <ip> <port> <quorum>
四个参数含义:
masterName这个是对某个master+slave组合的一个区分标识(一套sentinel是可以监听多套master+slave这样的组合的)。
ip 和 port 就是master节点的 ip 和 端口号。
quorum这个参数是进行客观下线的一个依据,意思是至少有 quorum 个sentinel主观的认为这个master有故障,才会对这个master进行下线以及故障转移。因为有的时候,某个sentinel节点可能因为自身网络原因,导致无法连接master,而此时master并没有出现故障,所以这就需要多个sentinel都一致认为该master有问题,才可以进行下一步操作,这就保证了公平性和高可用。
2.sentinel down-after-milliseconds <masterName> <timeout>
这个配置其实就是进行主观下线的一个依据,masterName这个参数不用说了,timeout是一个毫秒值,表示:如果这台sentinel超过timeout这个时间都无法连通master包括slave(slave不需要客观下线,因为不需要故障转移)的话,就会主观认为该master已经下线(实际下线需要客观下线的判断通过才会下线)
那么,多个sentinel之间是如何达到共识的呢?
这就是依赖于前面说的第二个定时任务,某个sentinel先将master节点进行一个主观下线,然后会将这个判定通过sentinel is-master-down-by-addr这个命令问对应的节点是否也同样认为该addr的master节点要做客观下线。最后当达成这一共识的sentinel个数达到前面说的quorum设置的这个值时,就会对该master节点下线进行故障转移。quorum的值一般设置为sentinel个数的二分之一加1,例如3个sentinel就设置2
领导者选举
为什么要选领导者?因为只能有一个sentinel节点去完成故障转移
sentinel is-master-down-by-addr这个命令有两个作用,一是确认下线判定,二是进行领导者选举。
选举过程:
1.每个做主观下线的sentinel节点向其他sentinel节点发送上面那条命令,要求将它设置为领导者。
2.收到命令的sentinel节点如果还没有同意过其他的sentinel发送的命令(还未投过票),那么就会同意,否则拒绝。
3.如果该sentinel节点发现自己的票数已经过半且达到了quorum的值,就会成为领导者
4.如果这个过程出现多个sentinel成为领导者,则会等待一段时间重新选举。
故障转移
所谓故障转移就是当master宕机,选一个合适的slave来晋升为master的操作,redis-sentinel会自动完成这个,不需要我们手动来实现。
那么,如何选择一个合适的slave呢?顺序如下:
1.选择slave-priority(slave节点优先级配置)最高的slave节点,(默认都是一样的)例如:如果我们有两台slave在两台机器上,一台配置较高,我们希望当master挂掉优先选配置高的,就可以配置该值为slave中最高的。如果存在最高则返回,不存在继续
2.选择复制偏移量最大的节点(复制得最完整,与master节点的数据一致性更高),如果存在则返回,不存在继续
3.如果以上两个条件都不满足,选runId最小的(启动最早的)。
补充一点:还可以向任意sentinel发生sentinel failover <masterName> 进行手动故障转移,这样就不需要经过上述主客观和选举的过程。