Redis缓存

Redis 有哪些常见的功能?
  1. 数据缓存功能
  2. 分布式锁的功能
  3. 支持数据持久化
  4. 支持事务
  5. 支持消息队列
Redis 适合的场景
  1. 缓存:减轻 MySQL 的查询压力,提升系统性能;
  2. 排行榜:利用 Redis 的 SortSet(有序集合)实现;
  3. 计算器/限速器:利用 Redis 中原子性的自增操作,我们可以统计类似用户点赞数、用户访问数等。这类操作如果用 MySQL,频繁的读写会带来相当大的压力;限速器比较典型的使用场景是限制某个用户访问某个 API 的频率,常用的有抢购时,防止用户疯狂点击带来不必要的压力;
  4. 好友关系:利用集合的一些命令,比如求交集、并集、差集等。可以方便解决一些共同好友、共同爱好之类的功能;
  5. 消息队列:除了 Redis 自身的发布/订阅模式,我们也可以利用 List 来实现一个队列机制,比如:到货通知、邮件发送之类的需求,不需要高可靠,但是会带来非常大的 DB 压力,完全可以用 List 来完成异步解耦;
  6. Session 共享:Session 是保存在服务器的文件中,如果是集群服务,同一个用户过来可能落在不同机器上,这就会导致用户频繁登陆;采用 Redis 保存 Session 后,无论用户落在那台机器上都能够获取到对应的 Session 信息。
Redis 不适合的场景

数据量太大、数据访问频率非常低的业务都不适合使用 Redis,数据太大会增加成本,访问频率太低,保存在内存中纯属浪费资源。

Redis这类NoSQL非关系型数据库与传统关系型数据库mysql的区别
  • NoSQL的数据主要存储在内存中,而mysql的数据主要存储在磁盘
  • NoSQL数据结构比较简单,功能有限,不如mysql的SQL语句强大
  • NoSQL高性能、高扩展、高可用,但难以保证数据一致性;MySQL成本低、结构稳定、便于查询,可以保证数据的一致性
如果key超时了,redis会回收key的存储空间吗?

不会。redis的key超时不会被自动回收,它只会标识哪些键值对超时了。因为如果一个很大的键值对超时,比如一个列表或哈希结构,存在数百万个元素,要对其回收需要很长的时间,如果采用超时回收,则可能产生停顿。

redis提供了两种方法来回收超时键值对:定时回收,惰性回收

  • 定时回收指在确定的某个时间触发一段代码,回收超时的键值对,一般可以选择在没有业务发生时触发redis的定时回收。
  • 惰性回收指当一个超时的键被再次用get命令访问时,触发redis将其从内存中清空,因此它可以指定回收超时的键值对。
Redis和Memcached的区别,为什么不用Memcached?
  • Redis支持的数据类型比较多,支持 string,list,set,zset,hash。
  • Redis提供了两种持久化机制,保障了业务的延续性。
Redis的存储类型
Redis基础数据类型底层数据结构应用背景
字符串(String)数组计数器,统计在线人数,存储图片或视频
列表(List)双向链表实现消息队列
哈希(字典)数组 + 链表二维结构存储对象的基本属性信息,比如用户信息,商品信息
集合(set)hash去重,例如用户名不能重复;交集并集功能,查找元素的共同点
有序集合(zset)Hash+跳跃表范围查找,排行榜功能或者topN功能
  • String(字符串)SDS结构
  • List(列表) 链表
  • Hash(字典) 哈希表
  • Set(集合)
  • Sorted Set(有序集合)跳跃表
Redis 支持的数据类型详细介绍

字符串
列表 哈希
集合 有序集合

  1. string 字符串
    字符串类型是 Redis 最基础的数据结构,首先键是字符串类型,而且其他几种结构都是在字符串类型基础上构建的。字符串类型实际上可以是字符串:简单的字符串、XML、JSON;数字:整数、浮点数;二进制:图片、音频、视频。
    使用场景:缓存、计数器、共享 Session、限速。
  2. Hash(哈希)
    在 Redis中哈希类型是指键本身是一种键值对结构,如 value={{field1,value1},…{fieldN,valueN}}
    使用场景:哈希结构相对于字符串序列化缓存信息更加直观,并且在更新操作上更加便捷。所以常常用于用户信息等管理,但是哈希类型和关系型数据库有所不同,哈希类型是稀疏的,而关系型数据库是完全结构化的,关系型数据库可以做复杂的关系查询,而 Redis 去模拟关系型复杂查询开发困难且维护成本高。
  3. List(列表)
    列表类型是用来储存多个有序的字符串,列表中的每个字符串成为元素,一个列表最多可以储存 2 ^ 32 - 1 个元素,在 Redis 中,可以队列表两端插入和弹出,还可以获取指定范围的元素列表、获取指定索引下的元素等,列表是一种比较灵活的数据结构,它可以充当栈和队列的角色。
    使用场景:Redis 的 lpush + brpop 命令组合即可实现阻塞队列,生产者客户端是用 lpush 从列表左侧插入元素,多个消费者客户端使用 brpop 命令阻塞式的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡和高可用性。
    在这里插入图片描述
  4. Set(集合)
    集合类型也是用来保存多个字符串的元素,但和列表不同的是集合中不允许有重复的元素,并且集合中的元素是无序的,不能通过索引下标获取元素,Redis 除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。合理的使用好集合类型,能在实际开发中解决很多实际问题。
    使用场景:如:一个用户对娱乐、体育比较感兴趣,另一个可能对新闻感兴趣,这些兴趣就是标签,有了这些数据就可以得到同一标签的人,以及用户的共同爱好的标签,这些数据对于用户体验以及曾强用户粘度比较重要。
  5. zset(sorted set:有序集合)
    有序集合和集合有着必然的联系,它保留了集合不能有重复成员的特性,但不同得是,有序集合中的元素是可以排序的,但是它和列表的使用索引下标作为排序依据不同的是:它给每个元素设置一个分数,作为排序的依据。
    使用场景:排行榜是有序集合经典的使用场景。例如:视频网站需要对用户上传的文件做排行榜,榜单维护可能是多方面:按照时间、按照播放量、按照获得的赞数等。
缓存雪崩是什么?缓存雪崩怎么处理?

如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。
解决办法:

  1. 加锁排队:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待;
  2. 数据预热:可以通过缓存 reload 机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存不同的 key,设置不同的过期时间,让缓存失效的时间点尽量均匀;
  3. 做二级缓存,或者双缓存策略:Cache1 为原始缓存,Cache2 为拷贝缓存,Cache1 失效时,可以访问 Cache2,Cache1 缓存失效时间设置为短期,Cache2 设置为长期。
  4. 在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期。
C字符串和SDS之间的区别?

在这里插入图片描述

Redis为什么查询数据这么快?
  1. Redis是一种基于键值对的NoSQL数据库,用C语言开发的,所以执行会比较快。
  2. Redis将所有数据放在内存中,非数据同步工作中,不需要从磁盘读取数据,0次IO。内存响应时间大约为100纳秒,这是Redis速度快的重要基础
  3. 采用单线程,避免了线程切换以及加锁释放锁带来的消耗。
  4. 使用epoll作为I/O多路复用技术的实现,再加上Redis自身的事件处理模型将epoll的read、write、close等都转换成事件,不在网络I/O上浪费过多的时间,提高了性能。
Redis为什么是单线程的?使用单线程快的原因?
  • 因为 Redis 是基于内存的操作,CPU 不是 Redis 的瓶颈,Redis 的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且 CPU 不会成为瓶颈,那就顺理成章地采用单线程的方案了,毕竟采用多线程会有很多麻烦。
  • 避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
Redis有两种过期键删除策略
  1. 惰性删除策略:对CPU时间来说是比较友好的,因为程序只会在取出键的时候才对它进行过期检查,删除的目标仅限于当前处理的键,不会在其他无关的过期键上浪费CPU的时间。缺点是对内存不友好,如果数据库中有很多过期键,而它们又恰好没有被访问到,那么它们也许一直不会被删除,这样占用了大量的内存。
  2. 定期删除策略:指每隔一段时间执行一次删除过期键的操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响,而且定期删除过期键,有效减少了对内存的浪费。

redis通过配合使用这两种删除策略,可以很好的在合理使用CPU时间和避免浪费内存空间之间取得平衡。

怎么保证缓存和数据库数据的一致性?
  1. 从理论上说,只要我们设置了合理的键的过期时间,我们就能保证缓存和数据库的数据最终是一致的。因为只要缓存数据过期了,就会被删除。随后读的时候,因为缓存里没有,就可以查数据库的数据,然后将数据库查出来的数据写入到缓存中。除了设置过期时间,我们还需要做更多的措施来尽量避免数据库与缓存处于不一致的情况发生。
  2. 新增、更改、删除数据库操作时同步更新 Redis,可以使用事物机制来保证数据的一致性。
    知道redis客户端和服务端使用的是什么协议吗
    知道redis对客户端的连接是怎么处理的吗
讲一下Redis的持久化方式

持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。Redis 提供了两种持久化方式:RDB(默认) 和 AOF。

  • RDB 是 Redis DataBase 的缩写。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件。即 Snapshot 快照存储,对应产生的数据文件为 dump.rdb,通过配置文件中的 save 参数来定义快照的周期。核心函数:rdbSave(生成 RDB 文件)和 rdbLoad(从文件加载内存)两个函数。
    在这里插入图片描述
  • AOF 是 Append-only file 的缩写。Redis会将每一个收到的写命令都通过 Write 函数追加到文件最后,类似于 MySQL 的 binlog。当 Redis 重启是会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。每当执行服务器(定时)任务或者函数时,flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作:
  1. WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件;
  2. SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。
    在这里插入图片描述
RDB 和 AOF 的区别:

RDB和AOF详细介绍

  1. AOF 文件比 RDB 更新频率高,优先使用 AOF 还原数据;
  2. AOF比 RDB 更安全也更大;
  3. RDB 性能比 AOF 好;
  4. 如果两个都配了优先加载 AOF。
Redis 怎么实现分布式锁?

Redis 为单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对 Redis 的连接并不存在竞争关系。Redis 中可以使用 SETNX 命令实现分布式锁。一般使用 setnx(set if not exists) 指令,只允许被一个程序占有,使用完调用 del 释放锁。

Redis 淘汰策略有哪些?
  1. volatile-lru:从已设置过期时间的数据集(server. db[i]. expires)中挑选最近最少使用的数据淘汰;
  2. volatile-ttl:从已设置过期时间的数据集(server. db[i]. expires)中挑选将要过期的数据淘汰。
  3. volatile-random:从已设置过期时间的数据集(server. db[i]. expires)中任意选择数据淘汰。
  4. allkeys-lru:从数据集(server. db[i]. dict)中挑选最近最少使用的数据淘汰。
  5. allkeys-random:从数据集(server. db[i]. dict)中任意选择数据淘汰。
  6. no-enviction(驱逐):禁止驱逐数据。
什么是缓存穿透?怎么解决?

缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。

  • 解决办法:
  1. 缓存空对象:如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
  2. 布隆过滤器:将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力。
缓存空对象带来的问题:
  1. 空值做了缓存,意味着缓存中存了更多的键,需要更多的内存空间,比较有效的方法是针对这类数据设置一个较短的过期时间,让其自动剔除。
  2. 缓存和存储的数据会有一段时间窗口的不一致,可能会对业务有一定影响。例如:过期时间设置为 5分钟,如果此时存储添加了这个数据,那此段时间就会出现缓存和存储数据的不一致,此时可以利用消息系统或者其他方式清除掉缓存层中的空对象。
Redis 怎么实现高并发

Redis通过主从架构,实现读写分离,主节点负责写,并将数据同步给其他从节点,从节点负责读,从而实现高并发。

redis如何做到高可用?

一个slave挂掉了不会影响程序,还会有其他的slave给程序提供查询服务
但是master死掉了就没发进行写程序了,所有redis有个主备切换,当master死掉了,会找一个slave来代替master作为新的master,这就叫做故障转移也叫做主备切换

redis原子性

一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。

redis事务

事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

Redis并发竞争key如何来解决?

答案

一致性锁定读是什么,为什么又用Redis分布式锁代替了一致性锁定读
Redis 的哨兵机制是什么,有哪些功能,选举算法是什么样的
Redis 主从节点是怎样通信的,传输数据是全量复制还是半增量复制
跳表结构和复杂度,为什么不用红黑树而用跳表,跳表优点,有序集合底层实现?跳表如何实现?第二个项目里边用到了关于kafka、zookeeper的内容,问kafka有哪几种组件?kafka相比其他消息队列为什么吞吐量这么大?kafka从消息生产者到消费者这整个的流程是怎么样的?Redis在项目里边是用作缓存还是消息队列?过程是怎么样的?用到了Redis的哪几种数据结构?Redis和Memcached的区别,为什么不用Memcached(答Redis支持的数据类型比较多且支持持久化)Redis有几种持久化方式?(AOF和RDB)Redis的事务了解么?Redis的哨兵模式和Redis集群各解决什么问题?这两种方式可以混合在一起使用么?

redis的内存模型?
redis 的hash怎么实现的,rehash过程讲一下和Java HashMap的rehash有什么区别?
redis集群怎么对key进行分片的

redis cluster采用哈希槽来进行数据存储和读取。redis cluster一共有2^14(16384)个槽,所有的master节点都会有一个槽区比如0~1000,槽数是可以迁移的。key的定位规则是根据CRC-16(key)%16384的值来判断属于哪个槽区,从而判断该key属于哪个节点。当master节点挂机后,slave节点会通过选举机制选举出一个节点变成master节点,实现高可用。

新建的master节点是没有槽区的,需要给master节点分配槽
删除master节点
1.如果主节点有从节点,需要将从节点转移到别的主节点上。
2.转移后 如果主节点有哈希槽,去调哈希槽,然后在删除master节点
所以Redis集群的高可用是依赖于节点的主从复制与主从间的自动故障转移。
参考博客:https://www.jianshu.com/p/4163916a2a8a

redis的hotkey如何处理?

hotkey问题:就是瞬间有几十万的请求去访问redis上某个固定的key,从而压垮缓存服务的情情况
怎么发现:

  1. 凭借业务经验,进行预估哪些是热key。比如某商品在做秒杀,那这个商品的key就可以判断出是热key。
  2. 在客户端进行收集,这个方式就是在操作redis之前,加入一行代码进行数据统计。那么这个数据统计的方式有很多种,也可以是给外部的通讯系统发送一个通知信息。缺点就是对客户端代码造成入侵。
  3. 在Proxy层做收集,但是缺点很明显,并非所有的redis集群架构都有proxy。
  4. 用redis自带命令,monitor命令,该命令可以实时抓取出redis服务器接收到的命令,然后写代码统计出热key是啥;hotkeys参数,redis 4.0.3提供了redis-cli的热点key发现功能,执行redis-cli时加上–hotkeys选项即可。但是该参数在执行的时候,如果key比较多,执行起来比较慢。

怎么解决:

  1. 利用二级缓存,发现hotkey后,把hotkey加载到本地缓存,会直接从jvm中取,而不会走到redis层。工具:ehcache、guava cache、Caffeine
  2. 备份热key,我们把这个key,在多个redis上都存一份。接下来,有热key请求进来的时候,我们就在有备份的redis上随机选取一台,进行访问取值,返回数据。为了防止缓存雪崩,需要将各台机器的过期时间都尽量设置的不一样。
    参考博客:https://www.cnblogs.com/leeego-123/p/11588429.html
    https://blog.csdn.net/harleylau/article/details/86246806
一致性哈希是什么,与哈希取余的相比的优势
  1. 一致性哈希用于解决分布式系统中的数据选择节点存储和读取问题以及在增删节点后只有一部分数据会失效。一致性哈希使用了取模的思想,不过不是对节点数量取模,而是对2的32次方取模,简单来说,它将整个哈希值空间组织成一个圆环,圆环上的值是0-2的32次方-1,表示有这么多节点。然后将机器的节点进行哈希,按照一定的规则,比如ip地址,让机器节点落在圆环上。然后就是将数据key找到对应的服务器存储。我们约定,通过key的哈希值落在圆环上的节点,如果命中了机器节点就存储在这个机器上,否则就存储在顺时针碰到的第一个机器。
  2. 如果用哈希取余算法的话,如果Redis要新加几台机器,或者数据库要多分几个库,那么就需要改变取余的数字。这就会导致原本的记录查不到了,如果要解决这个问题,必须在机器节点数量变化时对数据重新哈希,但是这样代价比较高。所以有了一致性哈希。

优势:
一致性Hash算法对于节点的增减都只需重定位环空间中的一小部分数据,有很好的容错性和可扩展性。

问题:数据倾斜问题,一致性Hash算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜(大部分集中缓存在某一台服务器上)。
解决:为了避免出现数据倾斜问题,一致性 Hash 算法引入了虚拟节点的机制,也就是每个机器节点会进行多次哈希,最终每个机器节点在哈希环上会有多个虚拟节点存在,使用这种方式来大大削弱甚至避免数据倾斜问题。
参考博客:https://www.jianshu.com/p/735a3d4789fc

锁冲突处理

对于加锁失败的请求,有三种处理策略:

  1. 直接抛出异常,通知用户稍后重试,用户看到错误对话框后,可以决定是否重新发起请求。
  2. sleep 一会再重试,会导致消息处理出现延迟,在队列里消息比较多、冲突比较频繁场景,不适合使用。
  3. 将请求转移至延时队列,过一会再试,适合处理异步消息。延时队列通过 zset 有序列表来实现,将消息序列化成一个字符串作为 zset 的 value,这个消息的到期处理时间作为 score,多个线程轮询 zset 获取到期的任务进行处理。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值