凭借这份Redis面试题,我成功拿下了京东,美团的offer_欢迎您访问我的公众号【前程有光】 -CSDN博客1.Redis是什么?Redis是一个开放源代码(BSD许可)的内存中数据结构存储,可用作数据库,缓存和消息代理,是一个基于键值对的NoSQl数据库。2.Redis特性?速度快基于键值对的数据结构服务器丰富的功能、丰富的数据结构简单稳定客户端语言多持久化主从复制高可以 & 分布式3.Redis合适的应用场景?缓存排行榜计数器分布式会话分布式锁社交网络最新列表消息系统4.除了Redis你还知道哪些NoSQL数据库?MongoDB、MemcacheDB、Cass
https://blog.csdn.net/weixin_47277170/article/details/106335793Redis缓存之穿透、雪崩、热Key问题_好记性不如烂笔头--玲博小记-CSDN博客_热key高并发的情况会给系统带来很高的访问流量,这就给存储这些热点信息的Redis数据造成了一些压力。热key问题及解决方案产生原因用户消费的数据远大于生产的数据 (热卖商品、热点新闻、热点评论、明星直播)等。在日常工作生活中一些突发的的事件,例如某明星突然宣布恋情,导致某新闻点击量瞬间变大,请求远超过对数据的写入。就会造成热数据问题。我们 一般采用缓存 + 过期时间的策略来帮助我们加...
https://blog.csdn.net/mayfla/article/details/80112241
1、redis的5种数据结构和场景
String: 一般做一些复杂的计数功能的缓存
List: 做简单的消息队列的功能
Hash: 单点登录
Set: 做全局去重的功能
SortedSet: 做排行榜应用,取TopN操作;延时任务;做范围查找
类型 | 简介 | 特性 | 场景 |
---|---|---|---|
String (字符串) | Redis的字符串是动态字符串,是可以修改的字符串,它的内部表示就是一个字符数组, 内部结构的实现类似于Java的ArrayList 它的内部结构是一个带长度信息的字节数组 | 可以包含任何数据,比如jpg图片或者序列化的对象,规定字符串的长度不得超过512MB。 Redis的字符串有两种存储方式,在长度特别短时,使用embstr形势存储,而长度超过44字节时候,使用raw形势存储 | 1、访问量统计:每次访问博客和文章使用 INCR 命令进行递增 2、将数据以二进制序列化的方式进行存储 |
Hash (字典) | Redis的字典相当于Java语言里面的HashMap 字典结构内部包含了两个Hashtable,通常情况下只有一个Hashtable是有值的, 但是在字典扩容缩容时候,需要重新分配新的Hashtable,然后进行渐进式搬迁,这时候两个Hashtable存储的分别是旧的Hashtable和新的Hashtable;待搬迁结束后,旧的Hashtable被删除,新的Hashtable取而代之 | 适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去)。 大字典的扩容是比较耗时的,需要重新申请新的数组,然后将旧字典所有链表中的元素重新挂接到新的数组下面,这是一个O(n)级别的操作,作为单线程的Redis很难承受这样耗时的过程,所以Redis使用渐进式rehash小步搬迁虽然慢一点,但是肯定可以搬完。 | 1、存储、读取、修改对象属性,比如:用户(姓名、性别、爱好),文章(标题、发布时间、作者、内容) |
List (列表) | Redis的列表相当于Java的LinkedList List的结构底层实现不是一个简单的LinkedList,而是快速链表(quicklist)。 首先在列表元素较少的情况下,会使用一块连续的内存存储,这个结构是ziplist,即压缩列表。它将所有的元素彼此紧挨着一起存储,分配的是一块连续的内存;当数据量比较多的时候才会改成quicklist。 | 增删快,提供了操作某一段元素的API 普通的链表需要的附加指针空间太大,会浪费空间,加重内存的碎片化。Redis将链表和ziplist结合起来组成了quicklist,也就是将多个ziplist使用双向指针串联起来使用,既满足了快速的插入删除性能,又不会出现太大的空间冗余 | 1、最新消息排行等功能(比如朋友圈的时间线) 2、消息队列 |
Set (集合) | Redis的集合相当于Java语言里面的HashSet,内部的键值对是无须的、唯一的 Set的结构底层实现是字典,只不过所有的value都是NULL,其他的特性和字典一摸一样。 | 1、添加、删除、查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作 当set集合容纳的元素都是整数并且元素个数较少时,Redis会使用intset来存储集合元素。intset是紧凑的数组结构,同时支持16位,32位和64位整数 | 1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐 |
Sorted Set (有序集合) | Redis有序列表类似于Java的SortedSet和HashMap的结合体, 一方面是一个set,保证内部value的唯一性,另一方面可以给每个value赋予一个score,代表这个value的排序权重。 它的内部实现是一个Hash字典 + 一个跳表。 | 数据插入集合时,已经进行天然排序 Redis的跳表共有64层,能容纳2的64次方个元素。 Redis之所以用跳表来实现有序集合 1. 插入、删除、查找以及迭代输出有序序列这几个操作,红黑树都能完成,时间复杂度跟跳表是一样的。但是按照区间来查找数据,红黑树的效率就没有跳表高 2. 跳表更容易代码实现,比起红黑树来说还是好懂、好写很多,可读性好,不容易出错 3. 跳表更加灵活,可以通过改变索引构建策略,有效平衡执行效率和内存消耗 | 1、排行榜,取TopN操作 2、带权重的消息队列 |
2、redis的hash怎么实现
edis的哈希对象的底层存储可以使用ziplist(压缩列表)和hashtable。当hash对象可以同时满足一下两个条件时,哈希对象使用ziplist编码。
哈希对象保存的所有键值对的键和值的字符串长度都小于64字节
哈希对象保存的键值对数量小于512个
3、为什么要实现Redis Cluster
1.主从复制不能实现高可用 2.随着公司发展,用户数量增多,并发越来越多,业务需要更高的QPS,而主从复制中单机的QPS可能无法满足业务需求 3.数据量的考虑,现有服务器内存不能满足业务数据的需要时,单纯向服务器添加内存不能达到要求,此时需要考虑分布式需求,把数据分布到不同服务器上 4.网络流量需求:业务的流量已经超过服务器的网卡的上限值,可以考虑使用分布式来进行分流 5.离线计算,需要中间环节缓冲等别的需求
4、redis的持久化机制,为啥不能用redis做专门的持久化数据库存储?
Redis本身是支持数据持久化的,很多有些程序员都会觉得Redis应该可以替代MySQL,但是我们在使用一项技术的时候,不是看它能不能,而是要看它适合不适合;而在大部分场景下,Redis是无法替代MySQL的。
- MySQL是关系型数据库,数据储存在磁盘上,数据的格式是我们熟知的二维表格的样式。关系型数据库具有很多强大的功能;大部分都支持SQL语句查询,对事务也有很好的支持。
- Redis被称作非关系型数据库,属于内存数据库,数据都储存在内存中(Redis有RDB持久化策略),Redis支持的数据类型也比较多,比如字符串,HASH,List等。
- MySQL和Redis没有竞争的关系,通常当并发访问量比较大的时候,特别是读操作很多,架构中可以引入Redis,帮助提升架构的整体性能,减少Mysql(或其他关系型数据库)的压力;
- 不是MySQL or Redis;而是MySQL + Redis ;
因为Redis的性能十分优越,可以支持每秒十几万次的读/写操作,并且它还支持持久化、集群部署、分布式、主从同步等,Redis在高并发的场景下数据的安全和一致性,所以它经常用于这些场景:
- 经常要被查询,但是CUD操作频率低的数据;比如数据字典,确定了之后很少被修改,是可以放到缓存中的;还有热点数据,查询极为频繁的数据,放到Redis中可以减少MySQL的压力;
- 经常被查询,但是实时性要求不高数据,比如购物网站的热销排行榜,定时统计一次后把统计结果放到Redis中提供查询(请不要每次都使用select top 10 from xxxx)。
- 缓存还可以做数据共享(Session共享),在分布式的架构中,把用户的Session数据放到Redis中。
- 高并发场景下的计数器,比如秒杀,把商品库存数量放到Redis中(秒杀的场景会比较复杂,Redis只是其中之一,例如如果请求超过某个数量的时候,多余的请求就会被限流);
- 因为Redis对高并发的支持和单线程机智,它也经常用作分布式锁;
Redis虽然功能强大、性能高效,但是也不是万能的,项目在引入Redis的时候,需要考虑的问题也比较多,并且会带来额外的开发和运维的工作量。
- 首先要判断数据是否适合缓存到Redis中,可以从几个方面考虑:数据会被经常查询么?命中率如何?写操作多么?数据大小?数据一致性如何保证?
- 我们经常采用这样的方式将数据刷到Redis中:查询的请求过来,现在Redis中查询,如果查询不到,就查询数据库拿到数据,再放到缓存中,这样第二次相同的查询请求过来,就可以直接在Redis中拿到数据;不过要注意【缓存穿透】的问题。
- 缓存的刷新会比较复杂,通常是修改完数据库之后,还需要对Redis中的数据进行操作;代码很简单,但是需要保证这两步为同一事务,或最终的事务一致性。
5、Redis的持久化方式:
redis提供两种方式进行持久化,一种是RDB持久化(原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化),另外一种是AOF(append only file)持久化(原理是将Reids的操作日志以追加的方式写入文件)
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
RDB存在哪些优势呢?
1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。
2). 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
3). 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。
4). 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。
RDB又存在哪些劣势呢?
1). 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
2). 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。
AOF的优势有哪些呢?
1). 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。
2). 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。
3). 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。
4). AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。
AOF的劣势有哪些呢?
1). 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
2). 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。
二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。
7、redis的持久化常用配置
RDB持久化配置
Redis会将数据集的快照dump到dump.rdb文件中。此外,我们也可以通过配置文件来修改Redis服务器dump快照的频率,在打开6379.conf文件之后,我们搜索save,可以看到下面的配置信息:
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。
AOF持久化配置
在Redis的配置文件中存在三种同步方式,它们分别是:
appendfsync always #每次有数据修改发生时都会写入AOF文件。
appendfsync everysec #每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync no #从不同步。高效但是数据不会被持久化。