Redis与其他key-value缓存产品相比有以下三个特点:
1、Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
2、Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构等存储。
3、Redis支持数据的备份,即master-slave模式的数据备份。
Redis优势
1、性能极高。Redis能读的速度是11w次/s,写的速度是8.1w次/s。
2、丰富的数据类型。Redis支持二进制案例的Strings,Lists,Hashes,Sets及Ordered Sets数据类型操作。
3、原子性。Redis的所有操作都是原子性的,意思就是要么都执行成功,要么失败完全不执行。单个操作是原子性的,多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
4、丰富 的特性。Redis还支持publis/subscribe通知,key过期等特性。
Redis有什么数据类型?分别用于什么场景?
数据类型 | 可以存储的值 | 操作 |
string | 字符串、整数或者浮点数 | 对整个字符串或者字符串的一部分执行操作。 对整数和浮点数进行自增或者自减的操作 |
list
| 列表 | 从两端压入或者弹出元素。 读取单个或者多个元素。 进行修剪,只保留一个范围内的元素。 |
set | 无须集合 | 添加、获取、移除单个元素。 检查一个元素是否存在集合中。 计算交集、并集、差集。 从集合中随机获取元素。 |
zset | 有序集合 | 添加、获取、移除元素。 根据分值范围内或者成员来获取元素。 计算一个键的排名。 |
hash | 包含键值对的无序散列表 | 添加、获取、移除单个键值对。 获取所有键值对。 检查某个键是否存在。 |
Redis的主从复制是如何实现的?
1、从服务器连接主服务器,发送SYNC命令。
2、主服务器接受到SYNC命令后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
3、主服务器BGSAVE执行完成以后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令。
4、从服务器收到快照文件后丢弃所有的旧数据,载入收到的快照;
5、主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
6、从服务器完成快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令。
Redis是如何寻址的
背景:
1、redis中的每一个数据库,都由一个redisDb的结构存储,其中:
(1)、redisDb.id存储着redis数据库以整数表示的号码。
(2)、redisDb.dict存储着该库所有键值对数据。
(3)、redisDb.expires保存着每一个键的过期时间。
2、当redis服务器初始化时,会先分配16个数据库(该数量可以通过配置文件配置),所有数据库保存到redisServer的一个成员redisServer.db数组中。当我们选择数据库select number时,程序直接通过redisServer.db[number]来切换数据库。有时候当程序需要知道自己是在哪个数据库时,直接读取redisDb.id即可。
3、redis的字典使用哈希表作为其底层实现。dict类型使用的两个指向哈希表的指针,其中0号哈希表(ht[0])主要用于存储数据库的所有键值,而1号哈希表主要用于程序对0号哈希表进行rehash时使用,rehash一般时在添加新值时会触发,这里不做过多的赘述。所以redis中查找一个key,其实就是对进行该dict结构中的ht[0]进行查找操作。
4、既然是哈希,那么我们知道就会有哈希碰撞,那么当多个键值哈希之后为同一个值怎么办呢?redis采取链表的方式来存储多个哈希碰撞的键。也就是说,当根据key的哈希值找到该列表后,如果列表的长度大于1,那么我们需要遍历该链表来找到我们所查找的key。当然,一般情况喜爱链表长度都是1,所以时间复杂度可以看为o(1)。
寻址key的步骤
1、当拿到一个key后,redis先判断当前库的0号哈希表是否为空,即:if(dict->ht[0].size==0)。如果为true直接返回null。
2、判断该0号哈希表是否需要rehash,因为如果在进行rehash,那么两个表中则有可能存储该key,如果正在进行rehash,将调用一次_dictrehashstep方法,_dictrehashstep用于对数据库字典、以及哈希键的字典进行被动rehash。
3、计算哈希表,根据当前字典与key进行哈希值的计算。
4、根据哈希值与当前字典计算哈希表的索引值。
5、根据索引值在哈希表中取出链表,遍历该链表找到key的位置。一般情况下,链表长度为1。
6、当ht[0]查找完之后,再进行一次rehash判断,如果未再rehashing,则直接结束,否则对ht[1]重复345步骤。
Redis的集群模式是如何实现的?
Redis Cluster是Redis的分布式解决方案,在Redis3.0版本正式推出的。
Redis Cluster去中心化,每一个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。
Redis Cluster节点分配
特点:
1、所有的redis节点彼此互联(ping-pong机制),内部使用二进制协议优化传输速度和宽带。
2、节点的fail是通过集群中超过半数节点检测失效时才生效。
3、客户端与redis节点直连,不需要中间proxy层。客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
4、redis-cluster把所有的物理节点映射到[0-16383]哈希槽上(不一定是平均分配),cluster负责维护节点、哈希槽以及值。
5、redis集群预分号16383个槽,当需要在redis集群中放置一个key-value时,根据crc16函数计算出该key存放到哪个槽上。
Redis Cluster主从模式
Redis Cluster为了保证数据的高可用性,加入了主从模式。
一个节点对应一个或者多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份。当这个主节点挂掉以后,就会从从节点中选取一个来充当主节点,从而保证集群不会挂掉。所以,载集群建立的时候,一定要为每个主节点添加从节点。
Redis Sentinel
Redis Sentinel用于管理多个Redis服务器,它有三个功能:
1、监控(Monitoring)
Sentinel会不断地检查你的主服务器和从服务器是否正常运作。
2、提醒(Notification)
当被监控的某个redis服务器出现问题的时候,Sentinel可以通过api向管理员或者其他应用程序发送通知。
3、自动故障迁移(Automatic failover)
当一个主服务器不能正常工作时,Sentinel会开始一次自动故障迁移操作,它会将失效主服务器中的一个从服务器升级为主服务器,并让失效主服务器的其他从服务器改为复制心的主服务器,当客户端试图连接失效的主服务器时,集群也会向客户端返回新主服务器的地址,使得集群可以使用新主服务器代替失效服务器。
Redis的持久化方式?有什么优缺点?持久化实现原理
RDB快照(snapshot)
将存在于某一个时刻的所有数据都写入到硬盘中。
快照的原理
在默认的情况下,redis将数据快照保存在名字为dump.rdb的二进制文件中。你可以对redis进行设置,让它在n秒内数据集至少有m个改动,这一条件满足时,自动保存一次数据集。你也可以通过调用SAVE或者BGSAVE,手动让redis进行数据集保存操作。这种持久化方式被称为快照。
当redis需要保存dump.rdb文件时,服务器执行以下操作:
1、redis创建一个子进程。
2、子进程将数据集写入到一个临时快照文件中。
3、当子进程完成对新快照文件的写入时,redis用新快照文件替换原来的快照文件,并删除旧的快照文件。
这种工作方式使得redis可以从写时复制(copy-on-write)机制中获益。
快照的优点
1、它保存了某个时间点的数据集,非常适用于数据集的备份。
2、很方便传送到另外一个远端数据中心或者亚马逊的s3,非常适用于灾难恢复。
3、快照在保存rdb文件时,父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他的io操作,所以快照持久化方式可以最大化redis的性能。
4、与AOF相比,载恢复大的数据集的时候,DB方式会更快一些。
快照的缺点
1、如果你希望载redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么快照不适合你。
2、快照需要经常fork子进程来保存数据集到硬盘上。当数据集比较大的时候,fork的过程是非常耗时的,可能会导致redis在一些毫秒级内不呢罡响应客户端的请求。
AOF
AOF持久化方式记录每次对服务器执行的写操作。当服务器重启的时候会重新执行这些命令来恢复原始的数据。
AOF的原理
1、redis创建一个子进程。
2、子进程开始将新AOF文件的内容写入到临时文件。
3、对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有到AOF文件的末尾,这样即使在重写的中途发生停机,现有的AOF文件也还是安全的。
4、当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新的AOF文件的末尾。
5、redis原子地用新文件替换旧文件,之后的所有命令会直接追加到新的AOF文件的末尾。
AOF的优点
1、使用默认的每秒fsync策略,redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,使用AOF,你最多丢失一秒的数据。
2、AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程宕机等等)未执行完整的写入命令,你也可以使用redis-check-aof工具修复这些问题。
3、redis可以在AOF文件体积变得过大时,自动地在后台对AOF进行重写;重写后的AOF文件包含了恢复当前数据集所需要的最小命令集合。整个重写操作时绝对安全的。
4、AOF文件有序地保存了对数据库执行的所有写入操作,这些写入操作以redis协议的格式保存,因此AOF文件的内容非常容易被人读懂,对文件进行分析也很轻松。
AOF的缺点
1、对于相同的数据集来说,AOF文件的体积通常要大于RDB文件的体积。
2、根据所使用的fsync策略,AOF的速度可能会慢于快照,在一般的情况下,每秒fsync的性能依然非常高,而关闭fsync可以让AOF的速度和快照一样快,即使在高负荷之下也是如此。不过在处理巨大的写入载入时,快照可以提供更有保证的最大延迟时间
Redis的过期策略有哪些
1、noeviction
当内存使用达到阀值当时候,所有引起申请内存的命令都会报错。
2、allkeys-lru
在主键空间中,优先移除最近未使用的key。
3、allkeys-random
在主键空间中,随机移除某个key。
4、volatile-lru
在设置了过期时间的键空间中,优先移除最近未使用的key。
5、volatile-ramdon
在设置了过期时间的键空间中,随机移除某个key
6、volatile-ttl
在设置了过期时间点键空间中,具有更早过期时间点key优先移除
Redis和Memcached有什么区别?
两者都是非关系型内存键值数据库,有以下的主要不同:
数据类型
1、Memcached仅支持字符串类型。
2、Redis支持五种不同类型的数据类型,使得它可以更灵活地解决问题。
数据持久化
1、Memcached不支持持久化。
2、Redis支持两种持久化策略:RDB快照和AOF日志。
分布式
1、Memcached不支持分布式,只能通过在客户端使用像一致性哈希这样的分布式算法来实现分布式存储,这种方法在存储和查询时都需要现在客户端计算一次数据所在的节点。
2、Redis Cluster实现了分布式的支持。
内存管理机制
1、Memcached将内存分割成特定长度的块来存储数据,以完全解决内存碎片的问题,但是这种方式会使得内存的利用率不高。例如块的大小为128bytes,只存储100bytes的数据,那么剩下的28bytes旧浪费掉了。
2、在Redis中,并不是所有的数据都一直存储在内存当中,可以将一些很久没用的value交换到磁盘,而Memcached的数据则会一直在内存中
为什么单线程的Redis性能反而优于多线程的Memcached?
Redis快速的原因:
1、绝大部分请求是纯粹的内存操作(非常快速)
2、采用单线程,避免了不必要的上下文切换和竞争条件
3、非阻塞IO
内部实现采用epoll,采用epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转换成了事件,然后利用epoll多路复用特性,绝不在io上浪费一点时间