redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。Redis还通过以下方式提供高可用性:Redis Sentinel和Redis Cluster-ennable。
redis有5种数据类型,分别是String、Hash、List、Set、SortedSet。下面以一篇博客为例,介绍一下各个数据结构的应用场景。
String是Redis最常使用的数据类型,就只做简单的
将结构化的数据缓存在 Redis 里,类似于一张mysql表,每次读写缓存的时候,可以就操作 Hash 里的某个字段。其主要用于操作结构化数据,如博客的点赞数、评论数等等。
见名知意,List就是一个有序列表,用来存储一些列表数据,应用场景有很多,比如记录博客文章列表、粉丝列表等。
此外,它还支持从头部插入数据,从尾部取数据,所以也可以用来做消息队列。Irange功能可以轻松实现数据分页。
无序集合,类似于Java里的HashSet。它可以自动去重,可以基于 Set 做交集、并集、差集的操作,比如交集,我们可以把两个人的好友列表整一个交集,看看俩人的共同好友。
Sorted set 是排序的 Set,去重但可以排序,写进去的时候给一个分数,自动根据分数排序。
有序集合的使用场景与集合类似,但是set集合不是自动有序的,而Sorted set可以利用分数进行成员间的排序,而且是插入时就排序好。所以当你需要一个有序且不重复的集合列表时,就可以选择Sorted set数据结构作为选择方案。应用场景就是各种类型的排行榜。
redis提供了RDB和AOF两种持久化机制。下面分别介绍一下这两种持久化机制。
RDB 是把内存中的数据集以快照形式写入磁盘,实际操作是通过 fork 子进程执行,采用二进制压缩存储,这一过程会周期性的进行,当机器宕机重启之后,可以从磁盘之后将RDB文件加载到内存,进行数据恢复。
AOF 机制对每条写入命令作为日志,以 append-only 的模式追加进一个日志文件中,因为这个模式是只追加的方式,所以没有任何磁盘寻址的开销,所以很快,有点像Mysql中的binlog。
先说说RDB的优缺点。
再说说AOF的优缺点。
如何抉择:
业界的一般做法是第一时间用RDB恢复,然后AOF做数据补全。
可以参考我的另一篇博客《一文了解什么是缓存击穿、缓存穿透、缓存雪崩》。这里就不再赘述。
Redis高可用可用分为三种高可用模式,即主从模式、Sentinel(哨兵)模式、和Redis cluster模式。
主从模式是指将集群中的节点划分成一主多从的模式,主节点负责读写,从节点负责数据备份以及提供读服务。在主从关系中,从节点每秒中会向主节点上报信息,维护主从之间的心跳关系。发送的命令为REPLCONF ACK offset,上报自己的信息以及数据的offset。
值得注意的是,当主节点因不明原因而宕机时,此时集群无法提供写服务(即无法实现故障转移),但是可以提供读服务。需要人工修改配置文件才能重新选择主节点。重新上线的主节点会变成从节点,并向当前的主节点发生同步消息进行数据同步。
当集群第一次启动时,主节点会生成一个RDB文件,生成RDB文件的同时,会将这期间生产的操作缓存到内存中,RDB文件发送给从节点后,从节点进行数据的备份,然后向主节点发送同步消息,主节点将缓存在内存中的指令发送给从节点,从而实现了数据的同步。
Sentinel模式是指引入一个Sentinel集群来监控Redis数据集群,Sentinel主要实现了以下几个功能:
集群监控:负责监控 Redis master 和 slave 进程是否正常工作。
消息通知:如果某个 Redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。
配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。
当主节点出现故障时,Redis Sentinel能自动完成故障发现和故障转移,并通知应用方,从而实现真正的高可用。RedisSentine是一个分布式架构,其中包含若干个Sentinel节点和Redis数据节点,每个Sentinel节点会对数据节点和其余Sentinel节点进行监控,当它发现节点不可达时,会对节点做下线标识。如果被标识的是“主节点”,它还会和其他的Sentinel节点进行“协商”,当大多数Sentinel节点都认为主节点不可达时,它们会选举一个Sentinel节点来完成自动故障转移的工作,同时会将这个变化实时通知给Redis应用方。整个过程是自动的,不需要人工干预,解决了Redis的高可用问题。
值得注意的是: Redis 数据节点中 slave 节点仅作为备份节点,不提供服务。
Redis Cluster 是社区版推出的 Redis 分布式集群解决方案,主要解决 Redis 分布式方面的需求,比如,当遇到单机内存,并发和流量等瓶颈的时候,Redis Cluster 能起到很好的负载均衡的目的。Redis Cluster 集群节点最小配置 6 个节点以上(3 主 3 从),其中主节点提供读写操作,从节点作为备用节点,不提供请求,只作为故障转移使用。Redis Cluster 采用虚拟槽分区,所有的键根据哈希函数映射到 0~16383 个整数槽内,每个节点负责维护一部分槽以及槽所印映射的键值数据。
其优点是无中心架构,数据按照 slot 存储分布在多个节点,节点间数据共享,可动态调整数据分布;可扩展性:可线性扩展到 1000 多个节点,节点可动态添加或删除;高可用性:部分节点不可用时,集群仍可用。通过增加 Slave 做 standby 数据副本,能够实现故障自动 failover,节点之间通过 gossip 协议交换状态信息,用投票机制完成 Slave 到 Master 的角色提升;降低运维成本,提高系统的扩展性和可用性。
其缺点是Client 实现复杂,驱动要求实现 Smart Client,缓存 slots mapping 信息并及时更新,提高了开发难度,客户端的不成熟影响业务的稳定性。目前仅 JedisCluster 相对成熟,异常处理部分还不完善,比如常见的“max redirect exception”。数据通过异步复制,不保证数据的强一致性。
参考资料:
Redis 高可用解决方案总结
《吊打面试官》系列-Redis哨兵、持久化、主从、手撕LRU