面试—Redis

目录

对Redis的了解

Redis的数据类型

Redis的事务

Redis的事务冲突

Redis的持久化

Redis主从复制

三大招式

哨兵模式

集群

缓存问题

缓存穿透

缓存击穿

缓存雪崩

分布式锁


对Redis的了解

  • Redis是非关系型数据库,不依赖业务逻辑存储,以简单的key---value形式存储,基于内存存储

  • Redis采用单线程+多路IO复用技术

    • Redis采用单线程模式,无需进行线程切换,减少消耗一定的CPU时间和内存资源,处理请求更加高效

    • Redis主要是基于内存,单线程可以更好的利用CPU缓存。由于数据的访问和操作具有局部性,利用CPU缓存能提高内存访问速度

    • 多路IO复用技术可以同时监听多个连接,当一个连接准备就绪时,就可以进行相应的操作

    • Redis在等待IO操作的过程中,将CPU资源用于执行其他任务 ,如数据处理和存储,充分利用资源

    • 实现非阻塞IO ,当一个客户端的IO操作不可用时,Redis可以立即切换其他就绪的连接进行操作

Redis的数据类型

  1. 字符串(String)

    • Redis最基本的数据类型,一个Key对应一个Value
  2. 列表(List)

    • 单键多值,底层是一个双向链表

    • 对两端的操作性能高,中间查询性能低

  3. 集合(Set)

    • 与List相似,多一个自动排重的功能

    • 是一个无序集合,存储不重复元素

  4. 哈希(Hash)

    • 是一个string类型的fieldvalue的映射表

    • 适合存储对象,类似Java里的Map<String,Object>

  5. 有序集合(Zset)

    • sorted ser 与set相似,是没有重复元素的字符串集合

    • 每一个成员都关联了一个评分,评分用来排序

  6. Bitmaps

    • 本身是一个字符串类型,但是可以实现位操作

    • 可以把Bitmaps当作一个数组,每个元素只能存储0和1 ,数组的下标称为偏移量

    • 主要存储活跃用户,如某一时间段访问网址的用户,将用户id作为偏移量

  7. HyperLogLog

    • 用来做基数统计的数据结构,统计不重复元素

    • 可以去重,添加时相同的元素,无法添加

  8. Geospatital

    • 提供经纬度设置、查询、范围查询、距离查询、经纬度Hash等

Redis的事务

  • Redis事务是一个单独的隔离操作,所有的命令被序列化,按顺序执行

  • 事务主要分为两个部分

    • 组队阶段

      输入Milit命令开始组队阶段,将命令依次放入组队队列里面

    • 执行阶段

      输入Exec命令开始执行组队队列里面的代码

    • 在组队结束后可以输入discard放弃组队

  • 在组队阶段,如果命令出现错误,整个队列里面的命令全部都不会被执行

  • 在执行阶段,命令出现错误,只有出现错误的命令不会执行,不影响其他命令执行

Redis的事务冲突

  • 由于事务的单独隔离操作,当其他客户端发送请求后,会导致对同一个键值对进行操作,导致结果不同

  • 这时采用锁机制进行预防

  1. 悲观锁

    当一个客户端拿到数据后就会进行上锁,直到锁释放才会被其他客户端操作 效率较低

  2. 乐观锁

    采用版本号机制,每次拿到数据后会进行判断,判断别的客户端是否修改过版本(是否为数据进行过修改)

  • Redis中如果两个事务同时要对一个key进行操作,在组队阶段会先拿到键的版本号,当一个事务进入执行阶段执行后,另一个事务会在执行之前对键进行版本号校验,版本不同,事务就会被终止

Redis的持久化

  • 将内存中的数据写入到磁盘,就是持久化
  1. RDB

    在一定的时间间隔内,将内存中的数据集快照写入磁盘

    过程(写时复制技术

    1. 先复制创建一个**子线程(Fork)**来进行持久化

    2. 将数据写入到一个临时文件中

    3. 等持久化的过程结束,将临时文件替换会持久化文件

      • 由于直接创建持久化文件,当进程断开的时候,数据会丢失

      • 缺点:最后一次持久化的数据可能会丢失

        在durmp.rdb配置文件中,save 20 3意味着在20秒内当3个key发生变化时,进行持久化

  2. AOF

    AOF是以日志的形式记录写操作(增删改),将Redis执行过程中的指令记录下来,当Redis重启会重构数据

    过程

    1. 客户端的命令会被append追加到AOF的缓存区

    2. AOF缓存区会根据持久化策略(每次操作都立即写入日志、每隔一秒同步一次、不主动同步,由操作系统同步)将操作同步到磁盘中的appendonly.aof文件中

    3. AOF根据文件大小执行重写策略(文件大于64M的100%---128M)的时候,用写时复制技术将文件的指令进行压缩

    4. 当Redis重启时,会加载文件重构数据

  3. 备份

    先将.rdb和.aof配置文件复制下来,当Redis重启时会自动加载配置文件,以达到备份的功能

    当RDB和AOF同时开启,默认读取的是AOF的数据

Redis主从复制

  • Redis主从复制是将一台Redis服务器的数据复制到其他Redis服务器

  • 主服务器用来实现写的功能,从服务器实现读的功能,提高系统的并发性能

  • 当主服务器故障时,从服务器可以升级为主服务器,不会操作系统停滞

原理

  1. 当从服务器连接上主服务器后,会主动发送数据同步的消息

  2. 主服务器收到消息后,进行数据持久化,并将RDB文件发送给从服务器

  3. 从服务器收到RDB文件后进行读取,实现数据同步

  4. 当主服务器写的时候,会主动的和从服务器进行数据同步

三大招式

  1. 一主两仆

    • 当从服务器断开后,重写连接会变成单独的主服务器

    • 当主服务器断开后,从服务器不会篡位

  2. 新火相传

    • 从服务器可以组为主服务器(小组长),下面挂多个从服务器

    • 当主服务器断开后,依旧遵循一主两仆,不会篡位

    • 缺点:小组长从服务器断开后,下面的数据不会同步

  3. 反客为主

    • 当主服务器断开后,从服务器会晋升为主服务器

哨兵模式

  • 哨兵模式主要是检测Redis主从服务器的故障,当主服务器发送故障时,自动将从服务器升为主服务器,确保Redis服务的运行
  1. 配置sentinel.config文件,启动哨兵

  2. 哨兵会不断监控主从服务器的运行状态,包括时候在线、是否正常同步等

  3. 哨兵会定期的向主从服务器发送PING命令,如果主服务器在一定时间内没有响应,则认为出现故障

  4. 当检测主服务器故障时,会在从服务器中选择一个合适的服务器作为新的主服务器

  5. 哨兵会向其他服务器发送命令,让新的主服务器与其他服务器同步

  6. 最后将旧的主服务器重新配置为从服务器

  • 选举规则

    1. 优先级靠前的

      在redis.conf中默认配置:slave-priority 100 / replica-priority 100(值越小优先级越高)

    2. 偏移量大的

      与主句数据同步值最高的

    3. runid最小的从服务器

      Redis启动后自动生成的40位的runid

集群

  • Redis集群就是对Redis的水平扩容,将数据分布存储在多个节点上

  • 一个集群至少要有三个主节点

  • 无中心化集群:任何一个节点都可以作为集群的入口,各个节点之间是相互连通的

  1. 客户端可以连接到集群的任意一个节点上

  2. 当执行命令时,会根据键的哈希值对 16384 取模计算出槽位

  3. 每个节点都负责自己范围的键的存储和查询操作

缓存问题

缓存穿透

  • 主要是服务器被恶意攻击,大量的url访问服务器

解决方案

  1. 对空值缓存,如果查询数据库返回的时空值,对这个数据也存入缓存中,避免这个url一直访问服务器

  2. 设置白名单,利用Bitmaps类型作一个可访问名单,id作为偏移量,每次访问的时候与Bitmaps中的值进行比较(1表示用户访问过,无需在对服务器进行查询)

  3. 实时监控,当Redis命中率开始急速下降时,排查访问对象和访问数据,与运维人员配合处理

缓存击穿

  • 主要是某个时间段内的热点新闻

  • 在一点时间内,某一个key过期了,但是由大量返回去查询这个键,这是会去服务器中查询

  • 数据库无法将数据存入缓存中,造成击穿

解决方案

  1. 预先设置热门数据,增加key的过期时间

  2. 实时调整,及时的监控热门数据,增加过期时间

  3. 使用锁机制

缓存雪崩

  • 在某个时间内,大量的key过期,一直去数据库中查找,导致服务器奔溃

解决方案:

  1. 构建多级缓存架构

  2. 使用锁或队列,保证不会有大量的线程对数据库进行读写操作

    缺点:不适合高并发

  3. 设置过期标志更新缓存,记录缓存数据是否过期,如果快过期就会触发通知,让其他线程进行更新

  4. 将缓存失效时间分散开,在失效时间设置随机数,保证不会有大量ket同时失效

分布式锁

  • 对服务器加锁,加锁后,这个集群中的服务器都得加这个锁

  • 锁的四个条件

  1. 互斥性,在任意时间,只有一个客户端持有锁

  2. 不会发送死锁

    设置锁的过期时间,确保服务器断开后锁一直不被释放的问题

  3. 加锁和解锁必须是同一个客户端

    设置uuid,避免a服务器在执行过程中锁过期自动释放后,a服务器执行完释放锁,造成正在使用这个锁的b服务器被释放

  4. 原子性

    使用LUA脚本,确保在服务器执行操作的过程中别的客户端干扰

相关推荐
呆呆小雅1 小时前
C#关键字volatile
java·redis·c#
miss writer1 小时前
Redis分布式锁释放锁是否必须用lua脚本?
redis·分布式·lua
亽仒凣凣3 小时前
Windows安装Redis图文教程
数据库·windows·redis
希忘auto4 小时前
详解Redis的常用命令
redis·1024程序员节
岁月变迁呀11 小时前
Redis梳理
数据库·redis·缓存
Code apprenticeship13 小时前
怎么利用Redis实现延时队列?
数据库·redis·缓存
百度智能云技术站13 小时前
广告投放系统成本降低 70%+,基于 Redis 容量型数据库 PegaDB 的方案设计和业务实践
数据库·redis·oracle
装不满的克莱因瓶13 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
黄名富16 小时前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
G_whang17 小时前
centos7下docker 容器实现redis主从同步
redis·docker·容器