Redis 读书考题

42 阅读16分钟

一 应用纬度 (数据结构应用、缓存应用、集群应用)(13)

1.1 数据结构应用 (5)
1.1.1 redis支持哪几种数据类型?
  • String(字符串)、SET runoobkey redis 【简单动态字符串】
  • List(列表)、LPUSH runoobkey redis 【双向链表+压缩列表】
  • Hash(字典)、 HMSET runoobkey name "redis tutorial" 【哈希表+压缩列表】
  • Sorted Set(有序集合):ZADD runoobkey 1 redis 【跳表+压缩列表】
  • Set(集合):SADD runoobkey redis 【哈希表+整数数组】

底层数据结构 image.png

1.1.2 redis的高级数据类型?
  • bitmap:本身是用String类型作为底层数据结构实现的一种统计二值状态的数据类型,常用于签到的情况。
  • hyperloglog:用于基数统计一个集合中不重复的数据计算网页的UV。
  • geo : 应用于地理位置计算,主要是经纬度的计算。
  • 布隆过滤器、布谷鸟过滤器
1.1.3 redis的常用类型的应用场景?
  • String:String是最常用的一种数据类,一般用于存储简单的字符,比如存个标志位,或者分布式锁。
  • List:b站的关注列表、粉丝列表、轻量级的消息队列
  • Hash:和Javamap相似。存储一些多key信息,比如缓存一下某个地区下活动的信息,活动信息可能是各种各样的。
  • Set:一般存一些黑名单、白名单之类的。支持差集、并集、交集计算。
  • Sorted Set:用来作为排行榜。
1.1.4 使用redis统计网站的UV,应该怎么做?
  • 使用hyperloglog,pfadd page:uv user1 2..... pfcount page1:uv
  • 用布隆过滤器,将每次访问的用户uid放到布隆过滤器。省内存,但无法精确。
1.1.5 redis如何实现延时队列?
long score = System.currentTimeMillis() + delayTime;
stringRedisTemplate.opsForZSet()
        .add(queueName, msgContent, score)
Boolean add(K key, V value, double score)

Set<String> tags = stringRedisTemplate
    .opsForZSet()
    .rangeByScore(key, 0, System.currentTimeMillis(), 0L, 60L);

使用soted set数据结构,将时间戳作为score,消息内容作为value调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理,并移除。

1.2 缓存应用(过期和淘汰策略)(4)
1.2.1 redis过期策略都有哪些?

image.png

  • ttl: 根据过期的时间先后进行删除
  • lru: least recently used 最近不常用的数据会被筛选出来,核心思想是认为刚刚被访问的数据还会被再次被访问
  • lfu: 核心思想是根据历史数据的频率来淘汰数据。
1.2.2 redis如何判断数据是否过期的?
  • Redis通过过期字典来保存数据过期的时间。
  • 过期字典的键指向 Redis数据库中的某个key,
  • 过期字典的值是一个long long类型的整数,这个整数保存了key所指向的数据库键的过期时间。
  • 过期字典可以看作是 hash 表。
1.2.3 redis key的过期时间和永久有效分别怎么设置?

expire key seconds expireat key timestamp , 建议使用这个,否则主从可能会有影响指定具体失效时间比较好 persist命令移除某个键的过期时间,永久有效

1.2.4 缓存可以通过哪些方式更新
  • 数据实时同步,对数据库数据进行更新的时候淘汰缓存
  • 设置缓存失效时间,兜底操作假设在更新缓存失效时间一到就会把缓存失效
  • 对数据库进行更新操作时保持数据库发送一个更新缓存的MQ消息,本地可以建立一个消息表在发生MQ失败后可以重试。
  • 通分布式调度任务进行定时更新缓存,使用场景:报表统计数据、对账数据定时更新到缓存。
1.3 集群应用(主从、切片) (4)
1.3.1 redis Sentinal与reids Cluster 区别
  • redis sentinal 属于高可用,在master宕机会自动为slave提升为master,继续提供服务
  • redis cluster 属于扩展性,当单个redis内存不知时候,使用cluster进行分片存储
1.3.2 什么是 redis 哈希槽的概念?

image.png redis集群有15384个哈希槽,每个key通过crc16校验后对16384取模来决定放置哪个哈希槽。集群每个节点负责一部分的哈希槽。 主要考虑集群内的网络带宽,而16384刚好是2k字节大小。

1.3.3 redis 主从复制的核心原理

image.png

  • 第一阶段:集群启动时,主从库会先建立连接,为全量复制做准备
  • 第二阶段:主库将所有数据同步从库。从库接受到数据库后,在本地完成清空数据并加载RDB
  • 在主库将数据同步给从库的过程中,主库不会阻塞,仍然可以正常接受请求,为了保证数据一致性会在内存中用专门的replication buffer记录rdb文件生成收到的所有写操作
  • 第三阶段:主库会把第二阶段执行过程中接收到的写命令发送给从库。当主库完成rdb文件后,就会把此时的replication buffer中修改操作发送给从库。从库在执行这些操作,实现主从库同步

后续主库和从库可以处理客户端读操作,写操作只能交给主库处理。 主库接受到写操作,还会将写操作发送给从库,实现增量同步。

1.3.4 什么情况下redis哨兵模式会产生数据丢失

1.3.4.1 异步复制导致的数据丢失 解决方案: 有了min-slaves-max-lag这个配置,就可以确保说,一旦slave复制数据和ack延时太长,就认为可能master宕机后损失的数据太多了,那么就拒绝写请求,这样可以把master宕机时由于部分数据未同步到slave导致的数据丢失降低的可控范围内。

1.3.4.2 脑裂导致的数据丢失 image.pngimage.png 解决方案: image.png image.png 如果一个master出现了脑裂,跟其他slave丢了连接,那么上面两个配置可以确保说,如果不能继续给指定数量的 slave发送数据,而且slave超过10秒没有给自己ack消息,那么就直接拒绝客户端的写请求。 这样脑裂后的旧master就不会接受client的新数据,也就避免了数据丢失。 上面的配置就确保了,如果跟任何一个slave丢了连接,在10秒后发现没有slave给自己ack,那么就拒绝新的写请求。

二 系统纬度(7)

2.1 高性能(有序索引、支持范围操作、压缩列表、整数数组、jemalloc)
2.1.1 redis常见性能问题和解决方案?ok
  • master最好不要写内存快照,如果master写内存快照,使用save命令会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务。如果数据比较重要可以采用bgsave命令或者再某个slave开启aof备份数据,策略设置每秒同步一次。
  • 为了主从复制速度和连接的稳定性,master和slave最好在同一个局域网
2.2 高可靠(rdb、aof、主从集群)ok
2.2.1 redis有哪些持久化方式
  • RDB是指定的时间间隔内 将内存中的数据集 快照写入磁盘
  • AOF是以日志的形式记录服务器所处理的每一个写操作,在Redis服务器启动之初会读取该文件来重新构建数据库,以保证启动后数据库中的数据是完整的
  • 无持久化
  • AOF和RDB配合
2.2.2 rdb的优势与劣势

优势

  • 采用rdb的方式,那么你的整个redis数据库只包含一个文件,比如你打算每小时归档一次近24小时的数据,同时还要每天归档一次最近30天的数据,一旦出现灾难性故障,我们可以非常容易的进行恢复。
  • 性能最大化,开始持久化时,它唯一需要做的只是fork出子进程然后由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。
  • 相比AOF机制,如果数据集很大,rdb的启动效率会更高。

劣势

  • 如果在定时持久化之前出现宕机的现象,此前没来得及写入磁盘的额数据都将丢失
  • rdb通过fork子进程来协助完成数据持久化工作的,如果当数据集较大时可能会导致停止服务几百毫秒,甚至1秒钟
2.2.3 aof机制的优势和劣势

优势

  • 该机制带来更高的数据安全性,即数据持久性。提供了三种写回策略,always同步写回,可靠性高数据基本不会丢失,性能影响较大;everysec每秒写回,性能适中,宕机丢失1秒内的数据。no操作系统控制的写回。
  • 该机制对日志文件的写入操作采用的是append模式。在写入的过程中即使宕机也不会破坏日志文件已经存在的内容。本次操作只是写入了一半数据就出现了系统崩溃问题,可以使用redis-check-aof工具来帮助我们解决数据一致性的问题。
  • 如果日志过大。AOF有一个重写机制,也就是说在重写时,读取数据库中的所有键值对,根据这个键值对当前最新的状态,为它生成对应的写入命令。多变一的思想。

劣势

  • 对于相同的数据集而言,aof文件通常要大于RDB文件
  • 根据同步策略的不同,aof在运行效率上往往会慢于rdb,每秒同步策略的效率是比较高的。

2.2.4 数据库和缓存的数据一致性如何保障,有哪些方案?ok 我觉得出现不一致的情况要分两个方向来讨论的 第一个方向是无并发请求

  • 先删除缓存,后更新数据库
  • 先更新数据库,后删除缓存只要两个操作无法保证原子性就会出现不一致的情况。
  • 这时候我们采用把第二个操作放入消息队列进行重试机制即可。

第二个方向是有并发请求

  • 先删除缓存。后更新数据库。在更新数据库的之前有其他并发线程读取旧数据。这时候采用延迟双删,更新完数据库后再去删除缓存。
  • 先更新数据库,后删除缓存,在删除缓存前有并发请求导致读取的旧数据。这个是我们生产用的方法。我们缓存的哪些appid 等其实是不会怎么变的。所以对业务影响比较小。我们也提供删除缓存的方法在管理端进行删除如果服务端删除失效的情况下 以及提示用户耐心等待几分钟。
  • 而且建议使用这种办法,如果说先删除缓存,有可能会导致请求因缓存确认而访问数据,导致给数据库压力极大。
2.3 高可扩展(切片集群)ok
2.3.1 redis持久化数据和缓存怎么做扩容?

使用redis切片集群进行横向扩展。

三 其他纬度(22)

3.1 概念性(11)
3.1.1 redis 的线程模型是什么?

image.png 组成部分:多个套接字、IO多路复用程序、文件时间分派器、事件处理器。 因为文件时间分派器队列的消费是单线程的,所以redis才叫单线程模型。

文件事件处理器使用 I/O多路复用程序 来监听多个套接字,并根据套接字目前执行的任务来为套接字关联不同的事件处理器。

当被监听的套接字准备好执行连接应答accept、读取read、写入write、关闭close等操作时,与操作相对应的文件事件就会产生,这时文件事件处理器就会调用套接字关联之前关联号的事件处理器来处理这些事件。

虽然文件事件处理器以单线程方式运行,但通过使用I/O多路复用程序来监听多个套接字,文件事务处理器既实现了高性能的网络通信模型,又可以很好地与redis服务器中其他同样以单线程方式运行的模块进行对接,保持了redis内部单线程设计的简单性。

3.1.2 redis的优点,redis为什么这么快
  • 采用了高效的数据结构例如哈希表和跳表
  • 采用了多路复用机制,使其在网络IO操作中能并发处理大量的客户端请求
  • 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速
  • 采用单线程,避免了不必要的上下文切换以及多线程导致的切换而消耗cpu,不用考虑锁的问题
3.1.3 redis相比Memcached有哪些优势

image.png

3.1.4 memcache与redis的区别都有哪些?

image.png

3.1.5 redis是单进程单线程的?

redis采用的是单线程模型,因为redis是一个基于内存的数据库,将所有的数据放入内存,所以使用单线程的操作效率是最高的。 但是单线程不是意味着redis就一个线程,redis其他模块还有各自的线程。

redis使用I/O treads指的是网络I/O处理方面使用了多线程,如网络数据的读写和协议解析等。 这是因为读写网络的read/write在redis执行期间占用了大部分cpu时间,如果把这部分模块使用多线程方式实现会对性能带来极大地提升。 但是redis执行命令的核心模块还是单线程。

3.1.6 什么是缓存穿透 什么是缓存击穿 什么是缓存雪崩

image.png

3.1.7 本地缓存与分布式缓存区别
image.png
3.1.8 redis的setnx和setex区别

setex :setex key seconds value 作用 = set key value expire key seconds作用一致,如果key值存在,使用setex将覆盖原有值

setnx :setnx key value 只有当key不存在情况下,将key设置为value。

3.1.9 redis的同步机制是什么?

redis可以使用主从同步、从从同步。 第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存中,待完成后将rdb文件同步到复制节点。 复制节点接受完成edb加载到内存,加载完成后通知主节点将期间修改的操作记录同步到复制节点进行重放。

3.1.10 Jedis与Redisson对比有什么优缺点?

image.png

3.1.11 redis中的管道有什么用?

image.png

3.2 事务(3)
3.2.1 什么是redis事务机制?

redis 事务的本质是一组命令的集合。 支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令不会请求插入到事务执行命令序列中。

redis事务三个阶段:开始事务 命令入队 执行事务 相关命令 image.png

不保证原子性、持久性 保证一致性、隔离性

3.2.2 redis事务其他的实现方式?

image.png

3.2.3 redis事务保证原子性吗,支持回滚吗?

image.png

3.3 key相关(4)
3.3.1 redis在集群种查找key的时候,是怎么定位到具体节点的?

使用crc16算法对key进行hash,将hash值对16384取模,得到具体的槽位、根据节点和槽位的映射信息找到具体的节点地址,去具体的节点找key。 如果key不在这个节点上,则redis集群会返回moved指令,加上新的节点地址给客户端;同时客户端会刷新本地的节点槽位关系。 如果槽位正在迁移中,那么redis集群返回asking指令给客户端。

3.3.2 redis中的大key怎么处理

大key会造成数据倾斜比如某些节点内存占用过高以及如果大key消失会导致qps突降。 将一个大key进行分片处理,分成多个小的set。

3.3.3 如果有大量的key需要设置同一时间过期,一般需要注意什么?

如果大量的key过期设置的时间过于集中到了过期的那个时间点,redis可能会出现卡顿的现象。 一般需要再时间加一个随机值。

3.3.4 如果redis正在给线上的业务提供服务,那使用keys指令会有什么问题?

redis是单线程的,keys指令会导致线程阻塞一段时间,线上服务会停顿直到指令执行完毕,服务才能恢复。 也可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重 就可以了,但是整体所花费的时间会比直接用keys指令长。

3.4 内存相关(4)
3.4.1 redis如何在对象层面做内存优化?

可以好好利用Hash,list,sorted set,set等集合类型数据,因为通常情况下很多小的Key-Value可以用更紧凑的方式存放到一起。尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽 可能的将你的数据模型抽象到一个散列表里面。 比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面。

3.4.2 redis回收进程如何工作的?

image.png

3.4.3 redis的内存用完了会发生什么?

如果达到设置的上限,Redis的写命令会返回错误信息,但是读命令还可以正常返回。可以将Redis当缓存来使用配置 淘汰机制,当内存达到上限时会冲刷掉旧的内容。

3.4.4 redis如何做内存优化?

尽可能使用散列表,因为散列表使用的内存非常小,所以应该尽可能的将数据模型抽象到一个散列表里面。 比如web 系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信 息存储到一张散列表里面。

四 规范与建议

image.png image.png image.png