1.Redis的简介
Redis(Remote Dictionary Server)是用 C 语言开发的一个开源的基于内存的高性能键值对(key-value)缓存和存储系统。
特征:
- 高性能。
内存存储,不走磁盘IO,在大数据量下也可以高性能运行。
官方提供测试数据,50个并发执行100000个请求,读110000 次/s,写81000次/s - 数据结构丰富
支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。 - 原子性
核心读写部分是单线程的,排队执行,对应的操作便具有了原子性,避免了多线程操作带来的复杂性和不安全因素。 - 易拓展。
关系型数据库中记录、表关系复杂,扩容难度高;NoSQL中数据无关系,Redis3.0开始支持集群,扩容简单。 - 高可用。
Redis3.0开始支持集群,可以多主多从,当某个节点发生异常时,可以由其他对应节点顶替,保持整个集群的高可用。 - 可持久化
支持把数据持久化存储到磁盘中,以便下次启动或遇到故障时,从磁盘加载恢复数据。
2.Redis有哪些数据类型,特性和使用场景
(1)String
这是最简单的类型,就是普通的 set 和 get,做简单的 KV 缓存。
应用:
- 缓存功能:String字符串是最常用的数据类型,不仅仅是Redis,各个语言都是最基本类型,因此,利用Redis作为缓存,配合其它数据库作为存储层,利用Redis支持高并发的特点,可以大大加快系统的读写速度、以及降低后端数据库的压力。
- 计数器:许多系统都会使用Redis作为系统的实时计数器,可以快速实现计数和查询的功能。而且最终的数据结果可以按照特定的时间落地到数据库或者其它存储介质当中进行永久保存。
- 共享用户Session:分布式系统中,做session共享
(2)Hash
(3)List
- 消息队列:Redis的链表结构,可以轻松实现阻塞队列,可以使用左进右出的命令组成来完成队列的设计。比如:数据的生产者可以通过Lpush命令从左边插入数据,多个数据消费者,可以使用BRpop命令阻塞的“抢”列表尾部的数据。
- 文章列表或者数据分页展示的应用。
比如可以通过 lrange 命令,读取某个闭区间内的元素,可以基于 List 实现分页查询,这个是很棒的一个功能,基于 Redis 实现简单的高性能分页,可以做类似微博那种下拉不断分页的东西,性能高,就一页一页走。
(4)Set
Set 是无序集合,会自动去重的那种。
(5)Sorted Set
Sorted set 是排序的 Set,去重但可以排序,写进去的时候给一个分数,自动根据分数排序。
3.缓存击穿、穿透、雪崩的场景和预防
(1)缓存击穿
- 场景: 某个key高热过期。就会有大量的请求在redis中命中失败,请求压力直接压到了MySQL上面。
- 解决方案:热点key长期有效,或者加互斥锁
(2)缓存穿透
- 场景:缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,我们数据库的 id 都是1开始自增上去的,如发起为id值为 -1 的数据或 id 为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大,严重会击垮数据库。
- 解决方案:做用户鉴权,接口层增加参数校验,不合法的参数直接代码Return,比如:id 做基础校验,id <=0的直接拦截等。
从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击。
(3)缓存雪崩
- 场景:举个简单的例子:如果所有首页的Key失效时间都是12小时,中午12点刷新的,我零点有个秒杀活动大量用户涌入,假设当时每秒 6000 个请求,本来缓存在可以扛住每秒 5000 个请求,但是缓存当时所有的Key都失效了。此时 1 秒 6000 个请求全部落数据库,数据库必然扛不住,它会报一下警,真实情况可能DBA都没反应过来就直接挂了。此时,如果没用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。这就是我理解的缓存雪崩。
- 解决方案:1. 在批量往Redis存数据的时候,把每个Key的失效时间都加个随机值就好了。2. 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。3. 设置热点数据永远不过期。
4.Redis的持久化
因为Redis数据在内存的特性,持久化必须得有,持久化有两种方式,RDB、AOF。
- RDB:RDB 持久化机制,是对 Redis 中的数据执行周期性的持久化。
- AOF:AOF 机制对每条写入命令作为日志,以 append-only 的模式写入一个日志文件中,因为这个模式是只追加的方式,所以没有任何磁盘寻址的开销,所以很快,有点像Mysql中的binlog。
两种方式都可以把Redis内存中的数据持久化到磁盘上,然后再将这些数据备份到别的地方去,RDB更适合做冷备,AOF更适合做热备,比如我杭州的某电商公司有这两个数据,我备份一份到我杭州的节点,再备份一个到上海的,就算发生无法避免的自然灾害,也不会两个地方都一起挂吧,这灾备也就是异地容灾,地球毁灭他没办法。
tip:两种机制全部开启的时候,Redis在重启的时候会默认使用AOF去重新构建数据,因为AOF的数据是比RDB更完整的
。
(1)RDB
- 优点:RDB对Redis的性能影响非常小,是因为在同步数据的时候他只是fork了一个子进程去做持久化的,而且他在数据恢复的时候速度比AOF来的快。
- 缺点:RDB都是快照文件,都是默认五分钟甚至更久的时间才会生成一次,这意味着你这次同步到下次同步这中间五分钟的数据都很可能全部丢失掉。AOF则最多丢一秒的数据,数据完整性上高下立判。
(2)AOF
- 优点:RDB五分钟一次生成快照,但是AOF是一秒一次去通过一个后台的线程fsync操作,那最多丢这一秒的数据。数据更完整。
- 缺点:一样的数据,AOF文件比RDB还要大。AOF开启后,Redis支持写的QPS会比RDB支持写的要低,他不是每秒都要去异步刷新一次日志嘛fsync,当然即使这样性能还是很高。
5.Redis和Memcache
(1)关系型数据库和redis的本质区别
(2)为什么选用Redis作缓存
Redis 支持复杂的数据结构:
Redis 相比 Memcached 来说,拥有更多的数据结构,能支持更丰富的数据操作。如果需要缓存能够支持更复杂的结构和操作, Redis 会是不错的选择。
Redis 原生支持集群模式:
在 redis3.x 版本中,便能支持 Cluster 模式,而 Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据。
性能对比:
由于 Redis 只使用单核,而 Memcached 可以使用多核,所以平均每一个核上 Redis 在存储小数据时比 Memcached 性能更高。而在 100k 以上的数据中,Memcached 性能要高于 Redis,虽然 Redis 最近也在存储大数据的性能上进行优化,但是比起 Remcached,还是稍有逊色。
6. 集群
(1)主从复制
单机版本Redis不能实现高可用,所以需要主从搭建集群,主从复制、读写分离。
主从分离的结构(一主多从),master节点的数据要及时有效完整的复制到slave中
master可以读,但是slave绝对不能写;master数据要及时有效的同步到所有slave中。
读写分离:master写、slave读,提高服务器的读写负载能力
负载均衡:基于主从结构,配合读写分离,由slave分担master负载,并根据需求的变化,改变slave的数量,通过多个从节点分担数据读取负载,大大提高Redis服务器并发量与数据吞吐量
故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复
数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式
高可用基石:基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案
主从数据同步:你启动一台slave 的时候,他会发送一个psync命令给master ,如果是这个slave第一次连接到master,他会触发一个全量复制。master就会启动一个线程,生成RDB快照,还会把新的写请求都缓存在内存中,RDB文件生成后,master会将这个RDB发送给slave的,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,然后master会把内存里面缓存的那些新命名都发给slave。
(2)哨兵
主从复制的结构中:master可以自动处理某个slave掉线之后的情况,但是无法处理master掉线的问题,无法实现持续高可用。
哨兵sentinel是另外一台redis服务器,会监控master、slave节点状态;在master异常时,投票选出新的master,保证高可用。
哨兵也是一台redis服务器,只不过不提供数据服务,数量通常为单数。
作用:
监控:不断检查master和slave是否正常运行。
通知:被监控的服务器出现问题时,向其他(哨兵间、客户端)发送通知。
自动故障转移:断开master和slave连接,选取一个slave作为master,并将其他slave连接新的master,并告知客户端新的服务器地址。
(3)集群
redis服务器怎么搭的?
三哨一主一从
主从模式下的脑裂:
redis的主从模式下脑裂是指因为网络问题,导致redis master节点跟redis slave节点和sentinel集群处于不同的网络分区,此时因为sentinel集群无法感知到 master 的存在,就会将某一个 slave 节点提升为 master 节点。此时就存在两个不同的 master节点,就像一个大脑分裂成了两个。
集群脑裂问题中,如果客户端还在基于原来的 master 节点继续写入数据,那么新的master 节点将无法同步这些数据,当网络问题解决之后,sentinel 集群将原先的master节点降为 slave 节点,此时再从新的 master 中同步数据,将会造成大量的数据丢失。
7.Redis的数据过期删除策略 与 内存淘汰机制
1.过期清除策略
删除策略指的是已经过期的数据怎么删除的问题。
定时删除:节约空间,占用CPU,拿时间换空间
惰性删除:内存占用严重,CPU利用率高,拿空间换时间
定期删除:折中方案,根据过期数据占比随机抽查删除
Redis 采用的是 定期删除+惰性删除。
2.内存淘汰机制
当内存不足时,淘汰哪些数据以腾出内存空间。淘汰的是未过期数据。
LRU,即:最近最少使用淘汰算法(Least Recently Used)。LRU是淘汰最近最少使用的页面。
LFU,即:最不经常使用淘汰算法(Least Frequently Used)。LFU是淘汰一段时间内,使用次数最少的页面。