Java面试-Redis

1.为什么Redis能这么快

        完全基于内存,绝大部分请求是纯粹的内存操作,执行效率高
        数据结构简单,对数据操作也简单
        采用单线程,单线程也能处理高并发请求,想多核也可启动多实例
        使用I/O复用模型,非阻塞IO

  1.1 多路I/O复用模型

            FD:文件描述符(一个打开的文件通过唯一的描述符进行引用,该描述符是打开文件的元数据到文件本身的映射)    
            select可以同时监控多个文件描述符的可读可写情况。其他I/O多路复用函数:epoll(Linux)/kqueue(Mac)/evport/select

2.数据结构

        String:最基本的数据类型,二进制安全
        Hash:String元素组成的字典,适合用于存储对象
        List:列表,按照String元素插入顺序排序(栈)
        Set:String元素组成的无序集合,通过哈希表实现,不允许重复
        Sorted Set:通过分数来为集合中的成员进行从小到大的排序
        HyperLogLog:计数
        Geo:存储地理位置信息

3.从海量key里查询出某一固定前缀的key

       如果用keys pattern(keys k1*):keys指令一次性返回所有匹配的key;键的数量过大会使服务卡顿
       SCAN cursor [MATCH pattern] [COUNT pattern]:
            基于游标的迭代器,需要基于上一次的游标延续之前的迭代过程
            以0作为游标开始一次新的迭代,直到命令返回游标0完成一次遍历
            不保证每次执行都返回某个给定数量的元素,支持模糊查询
            一次返回的数量不可控,只能是大概率符合count参数
            >>> scan 0 match k1* count 10 (开始迭代,希望返回以k1为前缀的key,希望一次返回10个)
            1)游标 xxxx
            2)结果集
            >>> scan xxxx match k1* count 10 (从xxxx开始继续迭代)
            1)游标 xxxx
            2)结果集

4.如何通过Redis实现分布式锁

            set key value [EX seconds] [PX milliseconds] [NX|XX]
            set设置超时时间、判断是否存在才操作->如果返回OK:执行业务,删除key,释放锁,结束。如果返回nil:结束。
            注:如果大量的key同时过期,由于清除大量的key很耗时,会出现短暂的卡顿现象。
                解决方法:在设置key的过期时间的时候,给每个key加上随机值

5.如何使用Redis做异步队列

        使用List作为队列,RPUSH生产消息,LPOP消费消息;但是没有消息的时候,可能也会进行消费->应用层sleep进行LPOP重试
        BLPOP key [key...] timeout   阻塞直到队列有消息或超时
            缺点:只能提供一个消费者消费
        pub/sub:主题订阅者模式
            发送者(pub)发送消息,订阅者(sub)接收消息
            订阅者可以订阅任意数量的频道(topic)
            缺点:消息的发布是无状态的,无法保证可达
            SUBSCRIBE myTopic:订阅myTopic的频道
            PUBLISH myTopic aaa:向订阅了myTopic的频道发送'aaa'

6.Redis如何做持久化

  6.1 RDB(快照)持久化:保存某个时间点的全量数据快照

            配置:
                redis.windows.conf中 save 900 1:在900秒内如果有一次写入操作,就做快照持久化
                redis.windows.conf中 stop-writes-on-bgsave-error yes:当备份进程出错的时候,主进程就停止接受新的写入操作了。
                redis.windows.conf中 rdbcompression yes:在备份的时候,需要将rdb文件压缩后保存
            命令:
                SAVE:阻塞Redis的服务器进程,直到RDB文件被创建完毕(可能会阻塞所有client请求,较少使用)
                BGSAVE:Fork出一个子进程来创建RDB文件,不阻塞服务器进程
            自动化触发RDB持久化的方式:
                根据redis.windows.conf配置里的save m n定时触发(用的是BGSAVE)
                主从复制时,主节点自动触发
                执行Debug Reload
                执行Shutdown且没有开启AOF持久化
            BGSAVE原理:
                执行BGSAVE命令,会先检查是否存在AOF/RDB的子进程正在执行,存在则返回错误。如果不存在会触发持久化,调用rdbSaveBackground方法,执行fork()系统调用(创建进程)
                当进行写入操作,fork的时候,主进程会拿到资源的快照文件(副本),子进程把内存数据写入到rdb临时文件中,写入完成后,替换快照文件。
                当redis启动时,如果检测到了rdb文件的存在,会自动载入这个文件
            缺点:
                内存数据的全量同步,数据量大会由于I/O而严重影响性能
                可能会因为Redis挂掉而丢失从当前至最近一次快照期间的数据  

  6.2 AOF(Append-Only-File)持久化:保存写状态

            记录下除了查询以外的所有变更数据库状态的指令
            以append的形式追加保存到AOF文件中(增量)
            配置:
                redis.windows.conf中 appendonly no:不开启AOF
                redis.windows.conf中 appendfilename "appendonly.aof":这就是aof文件
                redis.windows.conf中 appendfsync everysec:只要缓存区发生变化,就会每隔一秒,将指令写入到aof文件中
            为了解决AOF文件大小不断增大的问题,利用日志重写,原理如下:
                调用fork(),创建一个子进程
                子进程产生一条能生成所有原数据的新AOF指令,把新的AOF写到一个临时文件里,不依赖原来的AOF文件
                主进程持续将新的变动同时写到内存和原来的AOF里
                主进程获取子进程重写AOF的完成信号,往新的AOF同步增量变动
                使用新的AOF文件替换掉旧的AOF文件

  6.3 区别

        RDB和AOF文件共存情况下的数据恢复流程:
            redis启动时,会先判断是否存在AOF文件,如果存在就只加载AOF文件;如果不存在则判断是否存在RDB文件,如果存在就加载RDB文件。
        RDB和AOF的优缺点:
            RDB优点:全量数据快照,文件小,恢复快。
            RDB缺点:无法保存最近一次快照之后的数据。
            AOF优点:可读性高,适合保存增量数据,数据不易丢失。
            AOF缺点:文件体积大,恢复时间长。
        RDB-AOF混合持久化方式:
            BGSAVE做镜像全量持久化,AOF做增量持久化

7.Pipeline的好处

        Redis基于请求/相应模型,单个请求出来需要一一应答。(如果有大量指令,那么可能会堵塞)
        Pipeline批量执行指令,节省多次IO往返时间
        有顺序依赖的指令建议分批发送

8.Redis的同步机制

  8.1 全量同步过程

            Slave发送sync命令到Master
            Master启动一个后台进程,将Redis中的数据快照保存到文件中(BGSAVE)
            Master将保存数据快照期间接收到的写命令缓存起来(将增量数据缓存起来)
            Master完成写文件操作后,将该文件发送给Slave
            使用新的AOF文件替换掉旧的AOF文件
            Master将这期间收集的增量写命令发送给Slave端

  8.2 增量同步过程

            Master接收到用户的操作指令,判断是否需要传播给Slave
            将操作记录追加到AOF文件中
            将操作传播到其他Slave:1、对齐主从库;2、往响应缓存写入指令
            将缓存中的数据发送给Slave

9.Redis Sentinel(哨兵)

  9.1 解决主从同步Master宕机后的主从切换问题

            监控:检查主从服务器是否运行正常
            提醒:通过API向管理员或者其他应用程序发送故障通知
            自动故障迁移:主从切换(将一个Slave变成一个Master)

  9.2 流言协议Gossip

            每个节点都随机地与对方通信,最终所有节点的状态达成一致
            种子节点定期随机向其他节点发送节点列表以及需要传播的消息
            不保证信息一定会传递给所有节点,但是最终会趋于一致

10.Redis集群

        如何从海量数据里快速找到所需?
            分片:按照某种规则去划分数据,分散存储在多个服务器节点上(节点之间通过Gossip协议传播信息)
            常规的按照哈希划分无法实现节点的动态增减
            一致性哈希算法:对2^32取模,将哈希值空间组织成虚拟的圆环
            写入数据的时候,会将数据进行Hash,然后选择顺时针离他最近的服务器存储。如果这个服务器宕机了,则继续顺时针选取服务器。
            问题:如果节点较少时,可能会出现数据倾斜,即被缓存的对象大部分集中存储在某一台服务器上。
            解决:引入虚拟节点均匀分布到环上(存储过程多了一步:虚拟节点到实际节点的映射)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值