Redis总结面试

redis是什么

redis是c语言开发的一个开源的高性能键值对的内存数据库,一个内存中的数据结构存储系统,他可以用做数据库,缓存,消息中间件.支持多种类型的数据结构,如字符串,列表,哈希,集合,有序集合,bitmaps,Hyperloglogs,geo(地理空间)
1、字符串,是redis的基本类型,一个key对应一个value,最大可以存储512M,常用的命令有set,get,mget等,应用场景微博数,粉丝数列表,是一个字符串列表,按照插入的顺序排序,是一个双向链表,支持反向查找和遍历,常用命令lpush,rpush,lpop,rpop,lrange等命令,使用场景关注列表,好友列表等
2、哈希,和我们java中的hashmap类似,hash特别适合存储对象常用命令,hget,hset,hgetall等,应用场景可以存储用户的信息商品的信息等,
3、set,是一种无序集合,支持去重操作,但没有顺序,常用命令,sadd,spop,smemebers,sunion操作,方便集合之间的操作,引用场景,判断某个元素是否存在set集合中
4、zset,和set类似,且有序,使用一个额外的参数score为成员排序,内部使用hashmap和跳跃表实现存储和有序,HaspMap存放成员到score的映射,而跳跃表存放所有的成员,使用跳表实现比较高的查询效率,常用命令zadd,zrange,zrem,zcard等待,使用场景用分数进行成员的从小到大的排序
5、bitmaps(位图),实际上就是字符串,但是他可以对字符串的位进行操作,可以把位图当做一个以位为单位的数组,数组中只有0或1,如[00111010010010…],数组的下表就是偏移量,最大长度是512M,即2^32个比特币,常用命令setbit ,getbit,bitcount,使用场景,如用户的打卡,网站的浏览次数等等,(如果我们使用String记录用户的打卡,当用户量非常大的时候,就会占用内存,但是使用位图,一年365天相当于365bit,1字节=8bit,也就46字节而已,比如setbit user1 0 1表示user1第一天打卡成功,setbit user1 1 0表示user1第二天打卡失败)
6、Hyperloglogs,提供一种不太准确的基数统计算法(统计一批数据中的不重复的个数),常用命令pfadd,pfcount,pfmerge等等,使用场景网页的UV(用户访问网站的次数)
7、geospatial(地理空间),把指定的地理空间位置添加到指定的key中,如geoadd city 116.40 39.9 北京(geoadd key longitude latitude member),常用命令geoadd,geopos,geodist,georadius使用场景,计算两点之间的距离,查看指定位置附近范围的人.

redis雪崩,缓存穿透,击穿是什么意思,如何解决

1、redis雪崩,
我们认知的缓存都是存储热点数据,我们查询数据,先去缓存查找,如果缓存不存在,就直接到数据库查找,但是有一种情况我们要注意,比如,我们把缓存的key的有效时间是晚上0点,然而再0点正好有一次大促销活动,假设0点的请求量为8000请求/秒,同时所有的key失效了,因此8000个请求直接落到了数据库,此时数据库还没有反映过来,就直接过了,这就是雪崩。
如果遇到这种情况,我们可以给redis存储的数据设置一个随机事件,而不是设置同一时刻,这样就可以保证不会大面积失效,当然如果redis是集群,可以把热点数据分布在不同的redis库中也能避免全部失效,最暴力的就是不设置过期时间,更新操作在修改缓存就可以了
2、缓存穿透,
其实就是缓存和数据库都没有数据,此时有大量的请求,获取不存在的数据,如我们数据的id都是大于1的值,但是黑客使用id=-1的请求不断的攻击,导致数据库压力过大,严重的时候会导致数据挂掉
如果遇到这种情况,我可以给请求入参添加校验,只有合法的参数才能请求服务,也可以利用布隆过滤器,当不存在的时候就必要查询请求了。
3、缓存击穿,
是指一个大热点key,百万级用户不断请求,但是在某一刻失效了,也会导致大量请求到数据库,导致数据库挂掉,如果遇到这种情况,我也可以设置缓存不过期,或者使用分布式锁。

redis是单线程吗,为什么这么快

resi是单线程,但是官方声称redis的QPS可达100000+,为什么是单线程还这么快,如下原因

1、redis基于内存,所有数据都在内存中,类似hashMap,时间复杂度为O(1)

2、数据结构简单,对数据操作也简单

3、使用单线程,避免了不必要的上下文切换和竞争条件不存在多线程的CPU切换,也不存在加锁释放锁操作。

4、使用多路复用IO模型,非阻塞IO.

redis和memcached有什么区别

1、redis可以持久化,而memcached数据全部在内存中

2、redis支持多种数据结构,memcached支持key-value

3、使用的协议不一样,memcached的客户端通过TCP连接服务器通信,redis使用RESP协议通信,是专门为Redis设计的通讯协议,redis直接构建自己的VM机制,因为一般的系统调用系统函数,会浪费一定的时间去移动和请求.
4、value的大小,redis可以达到1GB,而memcached只有1MB

redis的持久化有几种

redis的持久化操作有两种,一种是RDB,RDB是以快照形式直接把内存的数据保存在一个dump文件中,而另外一种AOF,是把每一次修改命令存储在文件里,redis默认是RDB持久化方式,但是在重启的的时候,他会优先使用AOF,因为AOF保存的数据比RDB更加完成,

RDB触发的方式

1、手动触发,使用save,bgsave命令
1.1、save会阻塞redis服务器进行直到RDB文件创建完毕之后,否则服务器在这期间一直阻塞,而bgsave是会fork一个子进程,有子进程负责创建RDB文件,而父进程会继续处理请求。
2、自动触发,通过配置文件的命令save m n,满足下面任何一个条件如
2.1、save 900 1,到900秒内的时候,如果redis至少发生一次变化
2.2、save 300 10,到300秒内,至少发生10变化
2.3、save 69 10000,到10000秒内,知道发生10000变化
3、其他原因如主从复制场景,从节点执行全量复制操作,或执行shutdown命令时,都会执行RDB持久化

redis中bgsave执行流程

在这里插入图片描述

1、redis父进程判断是否有执行save,bgsave,bgrewriteaof的子进程,如果在执行则bgsave命令直接返回,
2、父进程执行fork操作创建子进程,这个过程父进程阻塞,redis不能执行客户端的任何命令
3、父进程fork后,bgsave命令返回"backgroud saving started"信息并不再阻塞父进程,并可以相应其他命令
4、子进程创建RDB文件,根据父进程内存快照生成临时文件,完成对原来文件的替换
5、子进程发送信号给父进程表示完成,父进程更新统计信息

AOF运行原理

开启AOF,需要在配置文件中配置appendonly yes,而AOF执行流程包括下面三种
1、命令追加,将redis的写命令追加到缓冲区aof_buf

2、文件写入和文件同步,根据不同的同步策略将aof_buf的内容同步到磁盘

3、文件重写,定期重写AOF文件,达到压缩的目的

命令追加

redis是将写命令追加到缓冲区,而不是直接写入文件,主要是为了避免每次写命令直接写入磁盘,导致硬盘IO成为redis负载的瓶颈

文件写入和文件同步

为了提高文件写入的效率,在现在操作系统中,当用户调用write函数将数据写入文件的时候,操作系统通常将数据暂存到一个内存缓冲区里,当缓冲区慢了或者超过了指定大小后,才会将内存缓存区中的数据写入到内存,这样虽然提高了效率,但是存在安全问题,比如计算机停机,内存缓存区的数据就会丢失,因此操作系统提供了文件同步的同步函数fsysnc,fdatasync函数,可以强制把操作系统立刻将缓存区中的数据写入到硬盘里,从而保证数据的安全性,文件同步策略的策略由参数appendfsync控制

appendfsync always,
//命令写入aof_buf后立刻调用系统fsync操作同步到AOF
appendfsync no
//命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步,
//此时的同步有操作系统负责,通常同步周期30s
appendfsync everysec
//命令写入aof_buf后调用系统write操作,write完成后线程返回,fsync同步文件操作由专门
//的线程每秒同步一次

文件重写

文件重写是指定期重写AOF文件,减少AOF文件的体积,重写就是把redis中的数据转成写命令,同步到AOF文件,不会对旧的AOF文件进行任何读取写入操作。具体的操作流程

在这里插入图片描述

1、redis父进程判断是否存在bgsave/bgrewriteaof的子进程,如果存在就直接返回,

2、父进程fork出子进程,这个过程父进程阻塞

3、父进程fork后,bgrewriteaof命令就返回"Background append only file rewrite started",此时父进程不在阻塞,同时redis客户端写命令写入AOF缓存区,并根据同步策略同步到旧的AOF文件

4、在上图中3.2步骤,在子进程生成新的AOF文件的同时,新的命令会同时写入aof_rewrite_buf中,这样就可以防止数据丢失,

5、子进程根据内存的快照,按照命令合并规则写入新的AOF文件

6、子进程完成新AOF文件后,就会通知父进程,父进程更新统计信息,

7、在5.2步骤,父进程会把aof_rewrite_buf的数据写入到新AOF文件,这样就保证了新的AOF保证了数据的完成性

8、最后使用新AOF文件替换旧的AOF文件

RDB和AOF的优缺点

在这里插入图片描述

如何选择RDB和AOF持久化策略

两种持久化策略持久化都是有性能代价的,RDB持久化,在使用bgsave的时候会阻塞主进程,子进程向硬盘写数据会带来Io压力,AOF持久化,向硬盘写数据的频率越大,IO压力更大,甚至导致AOF阻塞问题,
而在实际场景,根据数据量,应用数据安全的要求,预算限制等不同情况,会有各种各样的持久化策略,我们可以单独用一种策略,也可以两种混合使用.
如果数据完全对丢失数据对业务没有任何影响,就可以不进行任何持久化如果在单机情况,如我们自己练习,如何可以接受丢失数据,可以使用RDB,如果只能接受秒级别的数据丢失,可以选择AOF

如果是我们的生产环境,主从环境,一般我们可以master关闭持久化,可以在slave关闭RDB,开启AOF,然后关闭自动重写,添加定时任务,定时调用bgrewriteaof上面只是简单的举例,所以如果你可以接受几分钟你的数据丢失,那么可以使用RDB,否则可以使用AOF持久化,但是AOF每一条命令追加磁盘,会降低redis性能,对于数据备份和灾难恢复,定时生成RDB快照非常便于进行数据库备份,但是RDB的回复数据集的速度比AOF恢复速度快,如果混合持久化,AOF重写的时候就直接把RDB的内容写到AOF文件开头,这样做的好处是可以结合RDB和AOF的优点,快速加载同时避免丢失过多的数据,当然AOF里面的RDB部分是压缩格式不再是AOF格式,可读性差.

redis主从复制过程

主从模式结合哨兵模式能够解决掉单点模式,提高redis可用性,从节点仅提供读服务,而主节点提供些操作,对于读多写少的情况,可以从节点的数量,从而提高响应效率,而主节点和从节点直接的复制过程如下
从节点执行slave masteip masterPort.保存主节点信息

从节点的定时任务发现主节点信息,建立和主节点的socker链接

从节点发送ping信号,主节点返回pong,两边就能互相通讯

连接建立以后,主节点将所有数据发送给从节点进行数据同步

主节点把当前的数据同步给从节点后,便完成了复制的建立过程,接下来,主节点就会持续把写命令发送给从节点,保证主从数据一致性。

哨兵原理

在这里插入图片描述

上图就是一张哨兵的架构图,我接着说他是如何工作的
1、每个sentinel节点都需要定期执行向所有主从服务器以及其他sentinel实例发送ping命令

2、但是当主节点最后一次回复ping命令超过了设置的时间(down-after-milliseconds参数指定的值),那么就会认为这个节点主观下线

3、如果一个主服务器被标记为主观下线,此时全部的sentinel节点都会每秒一次的频率确认主服务器的确是否进入主观下线状态此时大多数sentinel确认主服务器为下线,那个这个主服务器标记为客观下线

4、正常情况下,每个sentinel会以每10秒一次的频率向已知的所有主从服务器发送info命令,但当一个主服务被标记为客观下线时,sentinel就会把info命令的频率改为每秒一次

5、sentinel和其他sentinel协商客观下线的主节点状态,如果处于sdown状态则重新投票选出新的主节点,将剩余的节点指向新的节点进行数据复制

6、但是如果没有足够sentinel认为主服务下线时候,主服务器的客观下线状态就会移除,同时当主服务器的ping命令返回有效的恢复时候,就会移除主观下线。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ヾ凉秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值