questions
https://github.com/redisson/redisson/wiki/目录

1.memcached和redis区别有哪些,优势劣势?

redis支持多种数据类型,并且支持持久化策略,

2.实现本地缓存,有哪些方案?go本地,redis

3.redis通讯协议?特点是什么【TCP】

4.字符串最大长度是多少?512MB

5.介绍一下zset及底层实现机制

6.redis事务?原理是什么

7.事务相关命令?支持回滚吗

8.介绍一下pipeline和使用场景:批量读取写入

批量执行Redis命令的机制,它可以在客户端发送多个命令后,一次性将它们发送到服务器,然后一次性接收服务器的响应

和批量命令有什么不同

  1. pipeline是同时发送/执行不同命令的机制,批量是都需要执行相似的
  2. pipeline是顺序执行所有命令,执行一个一个状态,而批量需要等待所有的返回

    9.设置生存时间和过期时间用什么命令

    1
    2
    EXPIRE key n_seconds
    PEXPIRE mykey n_milseconds

10.介绍下redis的发布订阅功能

  • 允许多个客户端之间通过消息中间件来发送和接收消息。在这种模式下,消息的发送者称为发布者(Publisher),而消息的接收者称为订阅者(Subscriber)
  • Redis的发布订阅功能是异步的,消息的发送和接收是非阻塞的,因此在订阅者接收消息时需要特别注意处理并发和同步的问题。

    11.redis单线程为什么那么快

    单线程没有锁,主线程异步处理IO,避免多线程上下文切换

    12. 分布式缓存要注意哪些问题

  1. 缓存一致性
  2. 缓存击穿
  3. 缓存雪崩

13. redis的key删除策略【redis同时使用了惰性删除和定期删除】

  1. 定期删除,每 100 毫秒检查 20 个随机选择的过期 key,这个过期的key存储在expire字典中,如果发现有过期的 key,就会将其删除。
  2. 惰性删除,访问时检查key有没有过期,然后删除。

设置过期时间+一个随机的时间,防止缓存雪崩

lua

https://zhuanlan.zhihu.com/p/383994942?utm_oi=757371723308879872

lua的基本数据类型

  • nil 这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。
  • boolean 包含两个值:false和true。
  • number 表示双精度类型的实浮点数
  • string 字符串由一对双引号或单引号来表示
  • function 由 C 或 Lua 编写的函数
  • userdata 表示任意存储在变量中的C数据结构
  • thread 表示执行的独立线路,用于执行协同程序
  • table Lua 中的表(table)其实是一个”关联数组”(associative arrays),数组的索引可以是数字、字符串或表类型。在 Lua 里,table 的创建是通过”构造表达式”来完成,最简单构造表达式是{},用来创建一个空表。

1. pairs 和ipairs

  1. ipairs遇到nil会停止,pairs会输出nil值然后继续下去

  2. ipairs并不会输出table中存储的键值对,会跳过键值对,然后顺序输出table中的值。而pairs会输出table的键值对,先顺序输出值,再乱序(键的哈希值)输出键值对。

高频问题

1. Redis为什么那么快

  1. redis存储是基于内存的
  2. 命令的读写过程单线程执行,6.0之后引入了IO多线程,使用IO多路复用,提升网络IO的利用率和提速
  3. 底层数据存储结构使用的是全局hash,也就是kv存储,还有几种数据类型用了高效的压缩列表,哈希表跳表等等
    • String 简单动态字符串,线程安全,使用incr也线程安全,一个是incr原子操作,一个是string根据len去判断
    • Zset 有序集合,使用的跳表:有序链表的优化,

      2. Redis对于过期key的处理

  4. 惰性删除,一个key发生读写时,去判断是否过期,过期了直接删
  5. 定时删除,默认每100ms主动淘汰一批过期的key
  6. 定期删除,server.hz配置每秒钟执行serverCron()的次数,周期性轮询redis库中的时效性数据,采用随机抽取的策略

3. key没设置过期时间为什么还被删除了【在内存使用超阈值之后,会自动清一波没有使用的内存】

对于没有过期时间的key,使用allkeys-lru/allkeys-lfu/allkeys-random三种策略去淘汰

4. 删除key的命令会阻塞redis吗?【会发生阻塞】

因为在数据结构中删除存在一个,时间复杂度O(k),n为存在的数量,是个常数,返回值是删除的数量

5. 主从 哨兵 集群 优缺点

  1. 主从,主负责写,从负责读,主要作用相当于一个备份
  2. 哨兵三个sentinel去监控节点,master发生故障进行切换,提供服务的还是只有一个主节点,无法支持特别高的并发
  3. 集群,复制,高可用,分片,配置简单,

6. 集群模式,数据的hash分片算法

  1. redis集群时,有数据分片存储,找kv分在了哪个节点上
  2. 分片算法首先对key做CRC16得到一个中间值,然后mod 16384,根据分片规则,就能算到请求要到哪个master上

    7. 主从切换为什么会导致缓存雪崩【从节点所在系统时间戳不同】

8. RDB快照和AOF问题

主从复制只用RDB

9. 线上数据如何备份

  1. 定时把rdb或者aof持久化文件存到备份硬盘或者机器上,可以用crontab 分时日月周

10. 主从复制风暴是什么【发生在从节点特别多的情况】

节点重起的多,要求主节点发rdb文件,如果从节点只连接主节点,压力就特别大
如果要减轻压力,rdb复制的路线就采用树形结构,从节点发到下一级的从节点

11. 网络抖动导致频繁主从切换,怎么处理【redis timeout超过一定阈值,才认定故障,发生主从切换】

12. 为什么redis至少需要三个master

选举主节点时,要求半数以上的节点去选一个新主节点

13. mset mget批量指令支持redis集群吗【支持】

要借助hashtag,保证每次批量执行的key落在明确的节点上,要用大括号括一个值,在hash分片的时候查找

14. lua可以在集群执行吗【可以,但是有要求,同13问】

操作的key必须落在明确的节点上,hash分片

15. 主从切换导致分布式锁丢失

主节点把分布式锁的key发给slave是,因为是异步的,可能中间master挂了,导致丢失了

  • 有一种redlock的方法,要搞半数以上的独立redis节点,服务端才认定加锁成功。类似于zookeeper,但是

16. 大公司使用旁路写回的情况,是建立在设置好超时时间的前提下的

【redis集群一致性】:主从复制,分片算法

  1. 主从复制

    1
    2
    3
    4
    1)从节点连接主节点,并发送SYNC命令请求同步数据。
    2)主节点在接收到SYNC命令后,开始执行BGSAVE命令,将数据持久化到磁盘中,并将生成的RDB文件发送给从节点。
    3)从节点在接收到RDB文件后,通过LOAD命令将其加载到内存中,从而与主节点的数据保持一致。
    4)从节点开始接收主节点的增量数据,并将其应用到自己的数据集中,保持与主节点的同步。
  2. 分片算法,每次对key的CRC16值mod 16384 ,判定放置的slot号,然后落在哪个实例上

  3. 更改、增加、删除实例时,就更改slot和实例的分配,不会影响集群总体的一致性,但是不是强一致性。

    17. 解决缓存数据库双写不一致情况【双写指两个/多个写操作,其中有一个在查db和更新缓存之间顿了一下导致】

  4. 加个分布式锁,在查db和更缓存这两个过程绑一起,更新完再delete这把锁

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    RLock wlock = redission.createReadWriteLock(lockname);//在一个上锁的事务,两边都要
    try{
    Rlock wlock = redission.getReadWriteLock(lockname + id);
    wlock.lock();
    //transaction code
    //1. update db
    //2. set redis key
    }catch(){
    }finally{
    wlock.unlock();
    }

18. 分布式锁在遇到高并发时,出现串行征用问题

解决方法:读写锁
读写锁底层如何实现的?1.为什么写写互斥,写读互斥,读读不互斥?

19. 一个创建某个cache的操作进行上锁,几万个请求来搞这个请求,如何优化【使用redission的trylock】

就是所有线程都在自旋等待unlock锁,默认是非公平抢占锁

1
2
Rlock lock = redission.getlock()
lock.lock() // 改成lock.trylock()

Redis和MongoDB的区别

Redis和MongoDB都是流行的开源NoSQL数据库,但它们的设计理念和使用场景有所不同。本文将重点介绍Redis和MongoDB的区别和使用场景。

Redis是一个高性能的数据存储系统,常被用作缓存和消息中间件。
Redis以内存为主要存储介质,但它也支持将数据持久化到磁盘上。Redis是一款键值数据库,它支持多种数据结构(例如字符串、列表、哈希表、有序集合等),并提供了丰富的命令和API供开发者使用。

  1. MongoDB是一个面向文档的数据库,它以JSON格式存储数据。MongoDB是一款NoSQL数据库,它支持复杂的查询和数据聚合操作。MongoDB的数据模型和关系型数据库有所不同,它不需要事先定义表结构和字段,可以动态地添加或删除数据字段。MongoDB也支持数据的分片和复制,以实现数据的高可用和横向扩展。

Redis和MongoDB的区别
(1)数据模型

Redis是一个键值数据库,数据结构简单,适用于存储缓存数据和消息队列等场景。Redis支持字符串、列表、哈希表、有序集合等基本数据结构,同时还支持订阅与发布机制、Lua脚本等高级特性。Redis的数据操作速度非常快,可以达到单机每秒数百万次读写的性能。

MongoDB是一个面向文档的数据库,数据结构相对复杂,适用于存储各种应用数据。MongoDB的数据以BSON格式存储,类似于JSON,但支持更多的数据类型和地理位置信息等特性。MongoDB支持文档级别的事务和复杂的数据聚合操作。

(2)持久化机制

Redis最初是一个基于内存的缓存系统,但它提供了多种持久化机制来保证数据安全。Redis的持久化是异步的,默认情况下,Redis将数据写入内存,然后将数据异步地写入磁盘上的RDB文件或AOF文件。RDB文件是一个快照文件,可以定期保存数据库的状态,而AOF是一个日志文件,可以记录每个写操作的命令序列。

MongoDB支持多种持久化机制,包括基于写前日志(Write Ahead Log,WAL)和基于快照的持久化机制。MongoDB将每个写操作写入WAL,然后异步地将WAL中的操作应用到数据集中。MongoDB还可以定期创建数据集的快照,并将快照写入磁盘中的文件。WAL和数据集的快照可以用于数据的恢复和复制。

(3)查询特性

Redis的查询特性相对简单,主要支持基于键值的查询和基本的条件查询。Redis的查询速度非常快,因为它的数据都在内存中,可以直接访问。Redis还支持数据交集、并集和差集等高级查询特性。

MongoDB的查询特性非常强大,支持复杂的查询和数据聚合操作。MongoDB支持索引、分片、复制和副本集等技术,以提高查询的速度和可靠性。MongoDB还支持地理位置查询、全文搜索和图形查询等特性,可以满足不同应用场景的需求。

Redis和MongoDB的使用场景
(1)Redis的使用场景

Redis的内存存储特性和高性能的数据读写能力,使它非常适合作为缓存系统和消息队列。Redis也可以用于会话管理、分布式锁和实时计数器等场景。Redis的数据结构和高级特性(例如Lua脚本和发布订阅机制)可以实现智能匹配、排行榜和广告推广等应用。

(2)MongoDB的使用场景

MongoDB的文档存储特性和丰富的查询特性,使它非常适合作为Web应用和移动应用的后端数据库。MongoDB可以处理复杂的数据结构和数据关系,支持动态增加和删除数据字段,可以快速地适应应用的变化。MongoDB还可以用于数据分析、数据挖掘和机器学习等领域,以支持大规模数据的处理和分析。

总结
Redis和MongoDB都是优秀的NoSQL数据库,在不同的应用场景中有着不同的表现。Redis的内存存储和高性能的数据读写能力,使它适用于缓存和消息队列等场景。MongoDB的文档存储和强大的查询特性,使它适用于Web应用和移动应用的后端数据库。在选择Redis或MongoDB作为数据存储系统时,需要考虑应用的性能需求、数据模型和查询特性等因素。