Redis知识点整理

分类: 互联网 > 面试题

一、基础

    1. 文件事件处理器:

        1)多个Socket

        2)IO多路复用程序 

        3)文件事件分派器

        4)事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)

    2. 客户端与Redis的一次通信过程

    3. redis单线程为什么效率高:(6.0以后支持多线程)

        1)纯内存操作

        2)核心是基于非阻塞的IO多路复用机制

        3)C语言实现:一般来说,C语言实现的程序“距离”操作系统更近,执行速度相对会更快

        4)单线程反而避免了多线程的上下文切换问题,预防了多线程可能产生的竞争问题

    4. redis引入多线程的原因:

        1)因为读写网络的Read/Write系统调用在Redis执行期间占用了大部分CPU时间,如果把网络读写做成多线程的方式,对性能会有很大的提升

        2)执行命令仍然是单线程,这样就不会因为多线程而变得复杂,去处理额外的并发问题

二、基础知识点

    1. 基础数据结构:

        1)string(字符串):原子性(incr)加减key,分布式setnx

        2)hash(哈希):类似于mysql数据表

            与string比的优势:

                a. 同类数据归类整合存储,方便数据管理

                b. 相比string操作消耗内存与CPU更小

                c. 相比string存储更省空间

            与string比的劣势:

                a. 过期功能不能使用在field上,只能用在key上

                b. Redis集群架构上不适合大规模应用

        3)list(列表):队列,阻塞队列,栈

        4)set(集合,值不重复):

                a. 抽奖、微信微薄点赞、收藏、标签

                b. 集合运算应用场景:共同关注、共同喜好、电商商品筛选

        5)zset(有序集合):排行榜、弹幕

        6)HyperLogLog:是用来做基数统计的算法,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的

    2. 过期策略:

        1)定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除,但会占用大量的CPU资源去处理过期数据,从而影响缓存的相应时间和吞吐量

        2)惰性过期:只有当访问一个key时,才回判断key是否已过期,过期则清除,该策略可以最大化地节省CPU资源,却对内存非常不友好

        3)定期过期:每隔一段时间就会扫描一定数据的数据库的expire字段中一定数据的key,并清除其中已过期的key。该策略是前两者的一个折中方案。

    3. 内存淘汰策略:在Redis用于缓存的内存不足时,怎么处理数据写入且需要申请额外空间的数据

        1)全局的键空间选择性移除

            (1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。

            (2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。(这个是最常用的)

            (3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。

        2)设置过期时间的键空间选择性移除

            (1)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。

            (2)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。

            (3)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

三、使用场景:

    1. 布隆过滤器:用来判断大数据量中,是否数据重复

        1)优点:空间效率和查询时间都远远超过一般的算法

        2)缺点:有一定的误识别率

    2. 限流:

        1)漏桶算法:缺点在于漏桶的出水口是固定大小,不能随意控制流量的大小,对于流量突发变大的情况缺乏控制

        2)令牌桶算法:有点在于可以随意控制令牌数,随时控制流量大小

    3. 分布式锁:

        1)redis加锁命令:

            (1)setnx key seconds value【原子性,秒级】

            (2)psetnx key milliseconds value(原子性,毫秒级)

        2)释放锁:

            (1)局限性:确保当前释放锁的线程是持有者,没问题再删除,就变成两个步骤,又违背了原子性

            (2)解决方式:将这两个操作放入lua操作,lua操作具有整个操作的原子性

四、高可用性:

    1. 持久化:

        1)RDB:在指定的时间间隔内将内存中的数据集快照写入到磁盘中

                1)优势:

                    a. 灾难恢复:一旦系统出现灾难性故障,RDB可以非常轻松的将一个单独的文件压缩后再转移到其他存储介质上

                    b. 性能最大化:在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进行执行IO操作

                2)劣势:

                    a. 容易丢失数据,不保证数据的高可用性

                    b. 由于RDB是通过fork子进程来协助完成数据持久化工作的,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟

        2)AOF:以日志的形式记录服务器所处理的每一个写,删除操作

            1)优势:

                a. 每秒同步,更高的数据安全性,即数据持久性

                b. 由于aof同步数据采用append模式,同步数据出现了系统崩溃,通过redis-check-aof工具来保持数据一致性

            2)劣势:

                a. 对于相同数据的数据集而言,AOF文件通常要大于RDB文件,RDB再恢复大数据集时比AOF的恢复速度快

                b. 根据同步策略的不同,AOF在运行效率上往往会慢于RDB

    2. 哨兵:

        1)哨兵至少需要3个实例,来保证自己的健壮性

        2)哨兵 + redis主从的部署架构,是不保证数据零丢失的,只能保证redis集群的高可用性

    3. redis Cluster:

        1)特点:针对海量数据+高并发+高可用性的场景,Redis cluster支撑N个Redis master node,每个master node都可以挂载多个slave node,这样整个Redis就可以横向扩容了,整个流程跟哨兵相比,非常类似,所以说Redis cluster功能强大,直接继承了replication和sentinel的功能

        2)分布式寻址算法:

            (1)hash算法(大量缓存重建)

            (2)一致性hash算法(自从缓存迁移)+ 虚拟节点(自动负载均衡)

            (3)Redis Cluster 的 hash slot 算法

五、注意事项

    1. 缓存雪崩解决方案:【缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机】

        1)事前:Redis高可用,主从+哨兵,Redis cluster,避免全盘崩溃

        2)事中:本地ehcache缓存 + hystrix 限流&降级,避免Mysql被打死

        3)事后:Redis持久化,一旦重启,自从从磁盘加载数据,快速恢复缓存数据

    2. 缓存穿透解决方案:【指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力】

        将数据库中所有可能的数据哈希映射到布隆过滤器中,然后对每个请求进行判断

    3. 缓存击穿解决方案:【缓存击穿是指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db】

        1)若缓存的数据是基本不会发生更新的,则可尝试将该热点数据设置为永不过期;

        2)若缓存的数据更新不频繁,且缓存刷新的整个流程耗时较少的情况下,则可以采用互斥锁以保证仅少量的请求能请求到数据库并重新构建缓存,其余线程则在锁释放后才能访问到缓存

        3)若缓存的数据更新频繁或者在缓存刷新的流程耗时较长的情况下,可以利用定时线程在缓存过期前主动的重新构建缓存或者延后缓存的过期时间,以保证所有的请求能一直访问到对应的缓存

    4. 冷热数据一致性问题【redis mysql数据一致性】

        如果mysql数据需要更新时,先更新mysql,然后更新消息放到mq队列消费更新到redis,利用mq的ack机制保证数据的一致性,redis的数据需要设置无线或者很长的过期时间。

六、应用场景

    1. 数据缓存

    2. 数据共享分布式: Redis 是分布式的独立服务,可以在多个应用之间共享

    3. 分布式锁:利用redis的原子性,string数据结构的setnx方法,不存在返回true,存在返回false,设置过期时间防止死锁

    4. 全局ID:利用redis的原子性,适用string数据结构的incrby方法

    5. 计数器:

        1)string数据结构:例如当日的注册用户数【incrby】

        2)hash数据结构:例如每篇文章的访问数【hincrby】

        3)发帖排行榜:例如发帖排行榜【zincrby】

    6. 限流:以访问者的ip和其他信息作为key,访问一次增加一次计数,超过次数则返回false【incrby】

    7. 位统计:统计用户留存率、活跃用户【setbit、getbit】

    8. 基数统计:HyperLogLog结构,例如用户日活月活统计

    9. 时间轴:list结构,例如利用lpush写入最新数据,lrange获取最新数据

    10. 消息队列:

        1)消息的生产者只需要通过lpush将消息放入 list,消费者便可以通过rpop取出该消息

        2)实现带有优先级的消息队列也可以选择sorted set

    11. 抽奖:利用set结构的无序性,通过 Spop( Redis Spop 命令用于移除集合中的指定 key 的一个或多个随机元素,移除后会返回移除的元素。 ) 随机获得值

    12. 点赞、签到、打卡、商品标签:

        点赞了这条微博:sadd like:t1001 u3001

        取消点赞:srem like:t1001 u3001

        是否点赞:sismember like:t1001 u3001

        点赞的所有用户:smembers like:t1001

        点赞数:scard like:t1001

    13. 好友关系、用户关注、推荐模型:set结构,例如用户的关注与粉丝记录到set,通过sinter获取共同关注或者共同好友

    14. 倒排索引:set结构,记录一个关键字的关联ID


来源:原创 发布时间:2022-06-25 10:55:50