Redis

什么是 Redis?

是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、高性能的 Key-Value 数据库,并提供多种语言的 API。

Redis 的存储结构有哪些

String,字符串,是 redis 的最基本的类型,一个 key 对应一个 value。
是二进制安全的,最大能存储 512MB。
Hash,散列,是一个键值(key=>value)对集合。string 类型的 field 和value 的映射表,特别适合用于存储对象。每个 hash 可以存储 232 -1 键值对(40 多亿)List,列表,是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。最多可存储 232 - 1 元素(4294967295, 每个列表可存储 40 多亿)。
Set,集合, 是 string 类型的无序集合,最大的成员数为 232 -1(4294967295, 每个集合可存储 40 多亿个成员)。
Sorted set,有序集合,和 set 一样也是 string 类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。zset 的成员是唯一的,但分数(score)却可以重复。

Redis 的优点

1、纯内存操作。
2、单线程操作,避免了频繁的上下文切换。
3、采用了非阻塞 I/O 多路复用机制。
I/O 多路复用机制
I/O 多路复用就是只有单个线程,通过跟踪每个 I/O 流的状态,来管
理多个 I/O 流。

Redis 的缺点

缓存和数据库双写一致性问题
一致性的问题很常见,因为加入了缓存之后,请求是先从 redis
中查询,如果 redis 中存在数据就不会走数据库了,如果不能保证缓存跟
数据库的一致性就会导致请求获取到的数据不是最新的数据。
解决方案:
1、编写删除缓存的接口,在更新数据库的同时,调用删除缓存
的接口删除缓存中的数据。这么做会有耦合高以及调用接口失败的情况。
2、消息队列:ActiveMQ,消息通知。
缓存的并发竞争问题
并发竞争,指的是同时有多个子系统去 set 同一个 key 值。
解决方案:
1、最简单的方式就是准备一个分布式锁,大家去抢锁,抢到
锁就做 set 操作即可
缓存雪崩问题
缓存雪崩,即缓存同一时间大面积的失效,这个时候又来了一波
请求,结果请求都怼到数据库上,从而导致数据库连接异常。
解决方案:
1、给缓存的失效时间,加上一个随机值,避免集体失效。
2、使用互斥锁,但是该方案吞吐量明显下降了。
3、搭建 redis 集群。

缓存击穿问题

缓存穿透,即黑客故意去请求缓存中不存在的数据,导致所有的
请求都怼到数据库上,从而数据库连接异常。
解决方案:
1、利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,
再去请求数据库。没得到锁,则休眠一段时间重试
2、采用异步更新策略,无论 key 是否取到值,都直接返回,
value 值中维护一个缓存失效时间,缓存如果过期,异步起一个线程
去读数据库,更新缓存。

Redis 的持久化

Redis 提供了两种持久化的方式,分别是 RDB(Redis DataBase)和 AOF
(Append Only File)。
RDB,简而言之,就是在不同的时间点,将 redis 存储的数据生成快照并存储到磁盘等介质上。AOF,则是换了一个角度来实现持久化,那就是将 redis 执行过的所有写指令记录下来,在下次 redis 重新启动时,只要把这些写指令从前到后再重
复执行一遍,就可以实现数据恢复了。RDB 和 AOF 两种方式也可以同时使用,在这种情况下,如果 redis 重启的话,则会优先采用 AOF 方式来进行数据恢复,这是因为 AOF 方式的数据恢复完整度更高。RDB 持久化方式,是将 redis 某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法。
RDB 持久化方式:redis 在进行数据持久化的过程中,会先将数据写入
到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持
久化好的文件。正是这种特性,让我们可以随时来进行备份,因为快照文件总
是完整可用的。
对于 RDB 方式,redis 会单独创建一个子进程来进行持久化,而主进程
是不会进行任何 IO 操作的,这样就确保了 redis 极高的性能。
RDB 优点:如果需要进行大规模数据的恢复,且对于数据恢复的完整
性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。
RDB 缺点:如果你对数据的完整性非常敏感,那么 RDB 方式就不太适
合你,因为即使你每 5 分钟都持久化一次,当 redis 故障时,仍然会有近 5 分
钟的数据丢失。所以,redis 还提供了另一种持久化方式,那就是 AOF。
AOF 方式是将执行过的写指令记录下来,在数据恢复时按照从前到后
的顺序再将指令都执行一遍。
实现方式:我们通过配置 redis.conf 中的 appendonly yes 就可以打开
AOF 功能。如果有写操作(如 SET 等),redis 就会被追加到 AOF 文件的末尾。
AOF 持久化的方式:默认的 AOF 持久化策略是每秒钟 fsync 一次(fsync
是指把缓存中的写指令记录到磁盘中),因为在这种情况下,redis 仍然可以
保持很好的处理性能,即使 redis 故障,也只会丢失最近 1 秒钟的数据。
如果在追加日志时,恰好遇到磁盘空间满或断电等情况导致日志写入
不完整,也没有关系,redis 提供了 redis-check-aof 工具,可以用来进行日志修复。因为采用了追加方式,如果不做任何处理的话,AOF 文件会变得越来越大,为此,redis 提供了 AOF 文件重写(rewrite)机制,即当 AOF 文件的大小超过所设定的阈值时,redis 就会启动 AOF 文件的内容压缩,只保留可以恢
复数据的最小指令集。举个例子或许更形象,假如我们调用了 100 次 INCR 指
令,在 AOF 文件中就要存储 100 条指令,但这明显是很低效的,完全可以把这 100 条指令合并成一条 SET 指令,这就是重写机制的原理。AOF 优点:我们通过一个场景再现来说明。某同学在操作 redis 时,不小心执行了 FLUSHALL,导致 redis 内存中的数据全部被清空了,这是很悲剧的事情。不过这也不是世界末日,只要 redis 配置了 AOF 持久化方式,且 AOF 文件还没有被重写(rewrite),我们就可以用最快的速度暂停 redis 并编辑 AOF文件,将最后一行的 FLUSHALL 命令删除,然后重启 redis,就可以恢复 redis的所有数据到 FLUSHALL 之前的状态了。是不是很神奇,这就是 AOF 持久化方式的好处之一。但是如果 AOF 文件已经被重写了,那就无法通过这种方法来恢复数据了。AOF 缺点:比如在同样数据规模的情况下,AOF 文件要比 RDB 文件的
体积大。而且,AOF 方式的恢复速度也要慢于 RDB 方式。
如果你直接执行 BGREWRITEAOF 命令,那么 redis 会生成一个全新的AOF 文件,其中便包括了可以恢复现有数据的最少的命令集。如果运气比较差,AOF 文件出现了被写坏的情况,也不必过分担忧,
redis 并不会贸然加载这个有问题的 AOF 文件,而是报错退出。这时可以通过
以下步骤来修复出错的文件:
1、备份被写坏的 AOF 文件。
2、运行 redis-check-aof –fix 进行修复。
3、用 diff -u 来看下两个文件的差异,确认问题点。
4、重启 redis,加载修复后的 AOF 文件。

Redis 集群

主从复制
主从复制原理
从服务器连接主服务器,发送 SYNC 命令。
主服务器接收到 SYNC 命名后,开始执行 BGSAVE 命令生成
RDB 文件并使用缓冲区记录此后执行的所有写命令。
主服务器 BGSAVE 执行完后,向所有从服务器发送快照文件,
并在发送期间继续记录被执行的写命令。
从服务器收到快照文件后丢弃所有旧数据,载入收到的快照。
主服务器快照发送完毕后开始向从服务器发送缓冲区中的写
命令。
从服务器完成对快照的载入,开始接收命令请求,并执行来
自主服务器缓冲区的写命令(从服务器初始化完成)。
主服务器每执行一个写命令就会向从服务器发送相同的写命
令,从服务器接收并执行收到的写命令(从服务器初始化完成后的操
作)。
优点
支持主从复制,主机会自动将数据同步到从机,可以进行读
写分离。
为了分载 Master 的读操作压力,Slave 服务器可以为客户端
提供只读操作的服务,写服务仍然必须由 Master 来完成。
Slave 同样可以接受其它 Slaves 的连接和同步请求,这样可以
有效的分载 Master 的同步压力。
Master Server 是以非阻塞的方式为 Slaves 提供服务。所以在
Master-Slave 同步期间,客户端仍然可以提交查询或修改请求。
Slave Server 同样是以非阻塞的方式完成数据同步。在同步期
间,如果有客户端提交查询请求,Redis 则返回同步之前的数据。
缺点
Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致
前端部分读写请求失败,需要等待机器重启或者手动切换前端的 IP
才能恢复。
主机宕机,宕机前有部分数据未能及时同步到从机,切换 IP
后还会引入数据不一致的问题,降低了系统的可用性。
Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会
变得很复杂。

哨兵模式

当主服务器中断服务后,可以将一个从服务器升级为主服务器,
以便继续提供服务,但是这个过程需要人工手动来操作。为此,Redis2.8
中提供了哨兵工具来实现自动化的系统监控和故障恢复功能。
哨兵的作用就是监控 Redis 系统的运行状况,它的功能包括以下
两个。
1、监控主服务器和从服务器是否正常运行。
2、主服务器出现故障时自动将从服务器转换为主服务器。
哨兵的工作方式
每个 Sentinel (哨兵)进程以每秒钟一次的频率向整个集群中
的 Master 主服务器,Slave 从服务器以及其他 Sentinel(哨兵)进程
发送一个 PING 命令。
如果一个实例(instance)距离最后一次有效回复 PING 命令
的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例
会被 Sentinel(哨兵)进程标记为主观下线(SDOWN)。
如果一个 Master 主服务器被标记为主观下线(SDOWN),
则正在监视这个 Master 主服务器的所有 Sentinel(哨兵)进程要以
每秒一次的频率确认 Master 主服务器的确进入了主观下线状态。
当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指
定的值)在指定的时间范围内确认 Master 主服务器进入了主观下线
状态(SDOWN),则 Master 主服务器会被标记为客观下线(ODOWN)。
在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一
次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO
命令。
当 Master 主服务器被 Sentinel(哨兵)进程标记为客观下线
(ODOWN)时,Sentinel(哨兵)进程向下线的 Master 主服务器的
所有 Slave 从服务器发送 INFO 命令的频率会从 10 秒一次改为每
秒一次。
若没有足够数量的 Sentinel(哨兵)进程同意 Master 主服务
器下线, Master 主服务器的客观下线状态就会被移除。若 Master
主服务器重新向 Sentinel (哨兵)进程发送 PING 命令返回有效回复,
Master 主服务器的主观下线状态就会被移除。
优点
哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都
具有。
主从可以自动切换,系统更健壮,可用性更高。
缺点
Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会
变得很复杂。
Redis-Cluster 集群
redis 的哨兵模式基本已经可以实现高可用,读写分离,但是在这
种模式下每台 redis 服务器都存储相同的数据,很浪费内存,所以在
redis3.0 上加入了 cluster 模式,实现的 redis 的分布式存储,也就是说每
台 redis 节点上存储不同的内容。
Redis-Cluster 采用无中心结构,它的特点如下:
所有的redis节点彼此互联(PING-PONG机制),内部使用二进制
协议优化传输速度和带宽。
节点的fail是通过集群中超过半数的节点检测失效时才生效。
客户端与 redis 节点直连,不需要中间代理层.客户端不需要连
接集群所有节点,连接集群中任何一个可用节点即可。
工作方式
在 redis 的每一个节点上,都有这么两个东西,一个是插槽
(slot),它的取值范围是:0-16383。还有一个就是 cluster,可以理
解为是一个集群管理的插件。当我们的存取的 key 到达的时候,redis
会根据 crc16 的算法得出一个结果,然后把结果对 16384 求余数,
这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这
个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对
应的节点上进行存取操作。
为了保证高可用,redis-cluster 集群引入了主从模式,一个主
节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节
点。当其它主节点 ping 一个主节点 A 时,如果半数以上的主节点与
A 通信超时,那么认为主节点 A 宕机了。如果主节点 A 和它的从节点
A1 都宕机了,那么该集群就无法再提供服务了。

你可能感兴趣的:(关于面试,redis)