Redis简述
Redis是一种内存型的非关系型数据库,因为其优秀的性能,经常被用来做缓存(当然也可以作为一种消息队列)。Redis支持丰富的数据类型:String、List、Set、ZSet和Hash。为了节省内存,Redis的每种数据类型都存在不同的存储策略来满足需要。比如Hash,数据量较少时,采用数组紧密存储的结构,会在数据量增加驾到某个临界点时切换到HashMap的方式。
Redis可以抽象理解为一个HashMap,用来存储各种不同的数据。它会把我们的value包装一层编程RedisObject,然后内部通过数据类型、存储地址、编码格式、内存回收策略(上一次被程序访问的时间)、共享对象被引用计数等属性来管理value。
Redis解决高并发是通过将任务加入队列顺序执行的方式来完成的。也就意味着Redis是脆弱的,如果不顾一切的搞它,它会怀孕的(开个玩笑)。为了防止Redis崩溃,或者Redis崩溃以后的恢复,Redis想了很多种方案来解决。要想了解这一切,就需要深入了解Redis了。
Redis内存划分
(1)数据
指的就是我们放到Redis里存储的数据。
(2)进程本身
Redis本身也是个程序,对于操作系统来说,也需要分配内存来执行它。
(3)缓冲内存
1)为了应对客户端大量写入,设置客户端缓冲区;
2)为了满足部分复制功能,设置复制积压缓冲区;
3)为了于在进行AOF重写时,保存最近的写入命令,设置AOF缓冲区。
(4)内存碎片
因为Redis回采取不同的存储策略来应对不同数据量情况下的数据存储,就不可避免的产生了一些内存碎片。
Redis数据存储
(1)内存分配器:
相当于Redis的大脑,负责给每个数据分配相应的内存来存储;
(2)简单动态字符串:
用于存储key;
(3)RedisObject:
用于存储value,任何value 都会被转换为RedisObject进行存储。然后内部通过数据类型、存储地址、编码格式、内存回收策略(上一次被程序访问的时间)、共享对象被引用计数等属性来管理value。
typedef struct redisObject {
unsigned type:4; //数据类型(String、List、Set、ZSet和Hash)
unsigned encoding:4; //内部编码(每种数据类型都有好几种数据存储方式)
unsigned lru:REDIS_LRU_BITS; //上一次被程序访问的时间
int refcount; //共享对象被引用次数计数
void *ptr; //存储地址
}
Redis高可用
广义的高可用指的是一个程序在对长时间内可以正常提供服务。Redis中对广义高可用进行了扩展,除了保证提供正常服务(如主从分离、快速容灾技术),还需要考虑数据容量的扩展、数据安全不会丢失等。 在Redis中,实现高可用的技术主要包括数据持久化到磁盘、主从备份、哨兵和集群。
1. 数据持久化到磁盘
Redis是一个内存型数据库,为了满足重启后数据的恢复,采用了将数据写入磁盘的方式进行持久化,重启时重新载入。Redis采用了两种方案进行持久化:RDB和AOF:
RDB的做法是:每隔一段时间,自动(自动触发最常见的情况是在配置文件中通过save m n,指定当m秒内发生n次变化时,会触发bgsave)或手动的将数据生成数据快照写入磁盘(所以不是实时的,存在丢数据的问题)。
AOF的做法是:实时的将Redis执行的每次写命令记录到单独的日志文件中(有点像MySQL的binlog);当Redis重启时,模拟一个没有网络连接的客户端从磁盘中直接读取并执行AOF文件中的命令来恢复数据。
两者的关系:
当AOF开启,且AOF文件存在时,Redis启动时会优先载入AOF文件来恢复数据;
当AOF开启,但AOF文件不存在时,即使RDB文件存在也不会加载
只有当AOF关闭时,才会载入RDB文件恢复数据。
2. 主从备份
主从备份,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。
3. 哨兵
哨兵的核心功能是主节点的自动故障转移