百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

⑨ Redis

mhr18 2024-11-26 12:00 16 浏览 0 评论

1. redis 是什么?都有哪些使用场景?
2. redis 有哪些功能?
3. redis 和 memcache 有什么区别?
4. redis 为什么是单线程的?
5. 什么是缓存穿透?怎么解决?
6. redis 支持的数据类型有哪些?
7. redis 支持的 java 客户端都有哪些?
8. jedis 和 redisson 有哪些区别?
9. 怎么保证缓存和数据库数据的一致性?
10. redis 持久化有几种方式?
11.redis 怎么实现分布式锁?
12. redis 分布式锁有什么缺陷?
13. redis 如何做内存优化?
14. redis 淘汰策略有哪些?
15. redis 常见的性能问题有哪些?该如何解决?


1. redis 是什么?都有哪些使用场景?

  • Redis是现在最常用的一种NoSQL数据库,基于内存运行,性能高效的key-value存储系统。
  • 支持数据的持久化,对数据采用copy-on-write技术,可以异步保存数据到磁盘上。
  • Redis的所有操作都是原子操作。
  • 支持快速的数据备份,主从复制。

2. redis 有哪些优缺点?

  • 1)高性能,能够达到10万/秒的读写速度
  • 2)支持数据的持久化,使用copy-on-write技术,可以异步保存数据到磁盘上
  • 3)所有的操作都是原子操作
  • 4)快速备份数据,主从复制
  • 5)集群的使用,高性能,防止容灾,宕机

3. redis 和 memcache 有什么区别?

  • 1)redis支持5种数据类型,memcache只支持字符串
  • 2)如果是小数据量,Redis效率更快;大数据,memcache快一些
  • 3)Redis是单线程,基于非阻塞的IO多路复用机制;memcache是多线程,一个Master,多个worker线程
  • 4)Redis支持持久化操作;memcache数据都存储在内存中
  • 5)Redis自带cluster集群;memcache没有原生态的集群操作
  • 6)Redis宕机后可以通过aof恢复数据;memcache宕机后就无法恢复了

4. redis 为什么是单线程的?

Redis在6.X版本支持IO Thread,IO多线程,与外部数据的读写是多线程,但是Redis内部的操作还是单线程。

  • 1)单线程不需要进行线程切换,效率高
  • 2)不存在多线程争抢资源的情况,不需要考虑锁的问题
  • 3)基于内存操作,本身的效率就很高
  • 4)使用了非阻塞的IO多路复用功能
  • 5)数据存储进行了压缩优化
  • 6)使用了高性能的数据结构,如hash、跳表

5. 什么是缓存穿透?怎么解决?

缓存穿透:在Redis与数据库中都不存在的数据,被频繁的访问数据库,高并发下增加数据库的压力。

解决办法:

① 当查询Redis发现不存在数据的时候,会去查询物理库,如果物理库也不存在数据,在返回空的同时,在Redis中插入一条空数据,防止再次查询的时候去查询物理库。

这个操作会存在一个严重的问题,当查询的空数据越来越多,会导致Redis中数据越来越多,这时最好给Redis加一个失效时间,防止数据量过大。


② 添加一个布隆过滤器,在数据进行查询前先经过布隆过滤器去查询数据是否存在,如果不存在,直接返回空,如果存在则先查询Redis,Redis不存在再去查询物理库。

缺点:过滤数据不准确,布隆过滤器只可以增加数据,无法删除数据。


补充:

1. 什么是缓存雪崩?怎么解决?

缓存雪崩:在同一时间,大部分的缓存失效,导致大量的访问请求在同一时间访问物理库,增加物理机的压力。

场景:① Redis宕机 ② 大量设置了失效时间的key在同一时间失效

解决方法:① 搭建高可用的Redis集群(哨兵模式) ② Redis中key的失效时间不统一,设置不同的失效时间,防止key在同一时间失效。

2. 什么是缓存击穿?怎么解决?

缓存击穿: 热点数据在高并发的场景下,突然失效,导致大量请求访问物理库,导致物理库压力增大。

场景: ① 未被访问过的数据,在初始就被高并发访问。

② 热点key的失效时间达到,高并发请求直接访问物理库

解决方法:① 热点数据可以预初始化到Redis中,例如抢购。

② 当查询redis与查询数据库的时候,添加锁操作,只有当第一个查询数据库执行完成后,将数据存入redis中,才释放锁,允许后面的请求去查询redis

注:具体的操作还是需要看具体的使用场景。


9. 怎么保证缓存和数据库数据的一致性?

在进行缓存与数据库都存储数据的时候,就需要考虑双写时候数据一致性的问题。

极端情况,可以讲读操作与写操作串行执行,效率极低

经典情况是: 1)读取的时候先去读取缓存,如果缓存不存在数据,去数据量读取数据,读取到数据后更新缓存信息同时返回数据。 2) 进行写操作的时候,先删除缓存数据,然后再更新数据库数据。

为什么先删除缓存,然后再更新数据库就结束呢(需要根据实际场景设计)

在进行更新操作的时候,先删除数据库是为了防止在执行更新操作时,读取到老数据,如果更新数据库失败,那么redis中数据已经不存在了,再次查询也只会查询到老数据。 如果更新成功,是否需要写入redis中,需要看实际业务场景,如果更新的redis数据需要根据复杂的计算后才能够得到,那么可以不写入,如果redis对象的更新操作频繁,那等需要读取的时候再读取数据库再写入redis(相当于懒加载),尽量减少资源的浪费。

在上述情况会遇到一个比较常见的问题:当删除缓存中的数据,但是物理库还没有更新的时候,来了一个查询请求,发现redis中不存在数据,就会把物理库中当前的老数据写入到缓存中,会导致物理库更新了新值,但是缓存中数据是老数据。

解决方法:

① 延时双删操作 1)在更新数据库前先删除缓存数据 2)更新物理库数据 3)等待N毫秒后再次删除缓存数据。 该操作可能会存在N毫秒的脏数据。

② 在更新数据库数据前先将缓存中数据置为一个默认值 2)再更新物理库数据 3)如果查询的时候发现缓存中置为默认值,进行自循环等待直至数据库中数据为新值或者key被删除。 该操作需要等待,降低吞吐量。


10. redis 持久化有几种方式?

RDB与AOF

1)RDB:通过快照在指定的时间内对数据进行保存操作

三种触发方式: save命令、bgsave命令、配置文件配置(自动触发)

  • 1. save命令:会阻塞当前线程,执行save操作的时候,redis不能够执行其它的操作(串行操作),直到RDB操作结束。
  • 2. bgsave命令:不影响主进程,主进程会fork一个完全一样的子进程来处理RDB操作。期间主进程还是正常处理redis操作,子进程把数据写入到dump.rdb文件中,写完之后会将新的文件替换老文件。
  • 3. 在配置文件中配置save命令,save m n :在m秒内,有n个key发生改变就保存快照。

优点:

  • 1. 保存的文件紧凑,数据全面,适合用于数据备份与容灾恢复
  • 2. 在进行备份的时候,会fork一个子进程操作,主进程不会受到影响。
  • 3. 因为保存的是快照信息,用于恢复数据的时候非常快

缺点:

在进行RDB操作的时候,主进程执行的操作信息不会保存进这次的RDB文件中,这可能会导致数据丢失

2)AOF:记录Redis的操作信息,即日志信息:每收到一条写命令,就会通过write函数将命令添加到文件中

随着使用时间越来越长,AOF文件会越来越大,可以通过bgrewriteaof命令,对AOF文件进行压缩。

触发方式appendfsync:

  • 1)aways:同步执行,每执行修改命令后将命令添加到日志文件中
  • 2)everysec:异步执行,每秒钟同步一次,如果宕机会丢失一秒数据
  • 3)no:从不同步 (同步是指同步写入到磁盘中)

aways最安全,no效率最高

缺点:与RDB相比,使用AOF进行数据恢复的时候会比较慢。 但是如果执行了flushall命令,dump.rdb文件会被清空,AOF文件只需要删除最后的这条flushAll命令就可以执行恢复操作。


11.redis 怎么实现分布式锁?

获取锁与释放锁都需要保证操作的原子性

加锁: set key value nx|xx ex|px timeout

nx: if not exist xx:if exist

ex:秒 px:毫秒

解锁:

String script = " if redis.cell('get',key[1]) == avg then return redis.cell('del',key[1]) else return 0 end ";

jedis.eval(script);

执行lua命令,当get获取key的值等于目标值,则执行删除当前key,否则不操作


12. redis 分布式锁有什么缺陷?

jedis会产生的问题:1)业务逻辑较长,导致Redis锁自动释放。 2)会导致B锁被A释放的情况。

redisson的getLock方法会调用一个定时任务去监测这个锁,每个10秒检查锁是否存在,存在则延长过期时间,一般为30秒。 看门狗操作。


13. redis 如何做内存优化?

  • 1)缩减键值对对象,key越短越好,value适当压缩
  • 2)共享对象池的使用
  • 3)尽可能使用散列表hash
  • 4)尽量减少key的个数

14. redis 淘汰策略有哪些?

  • 1) volatile-lru 从设置失效时间的key中淘汰最少使用的
  • 2) volatile-ttl 从设置失效时间的key中淘汰最早失效的
  • 3) volatile-random 从设置失效时间的key中随机淘汰
  • 4) allkeys-lru 从所有key中淘汰最少使用的
  • 5) allkeys-random 从所有key中随机淘汰
  • 6) noeviction(默认策略):内存使用完,新增对象的时候,直接返回错误
LRU算法:最少使用的key被淘汰

public class LRUCache {

 private int capacity;
 private int count = 0;
 Map<Integer,Node> nodeMap;
 Node head;
 Node last;

 public LRUCache(int capacity){
  this.capacity = capacity;
  nodeMap = new HashMap<Integer,Node>();
  
  head = new Node(1,1);
  last = new Node(1,1);
  head.next = last;
  last.pre = head;
 }

 public int get(int key){
   /**
    * 1. 先判断这个key是否在nodeMap中,如果不存在,直接返回null
    * 2. 当存在nodeMap中,获取node信息,调用方法删除node节点的前置与后者节点信息,然后将node节点移到首位
    * 3. 返回node节点的value值
    */
 }

 public void set(int key,int value){
   /**
     * 1. 先判断key是否在nodeMap中,如果存在,获取node节点信息,然后删除当前node的位置,移动到首位。
     * 2. 如果不存在,判断count是否已经等于capacity,如果等于,删除尾节点,将node节点添加到nodeMap中,并且添加到首位
     * 3. 如果count小于capacity,直接在首位添加node节点,在nodeMap中添加node信息
    */
}


 class Node{
  int key;
  int value;
  Node pre;
  Node next;

  public Node(int key,int value){  //设置node节点
   this.key = key;
   this.value = value;
  }
 }
} 
LFU算法:访问次数最少的被淘汰

class HitRate implements Comparable<HitRate> {

 int capacity;

//存放key、value
Map<Integer, Object> map = new HashMap<Integer, Object>();

//存放key、hitRate对象
Map<Integer, HitRate> hitMap = new HashMap<Integer, HitRate>();

public LFUCache(int capacity) {
  this.capacity = capacity;
}

//HitRate对象存放key,使用次数,最后更新时间
 class HitRate implements Comparable<HitRate> {
  private int key;
  private int hitCount;
  private long lastTime;

  public HitRate(int key, int hitCount, long lastTime) {
   this.key = key;
   this.hitCount = hitCount;
   this.lastTime = lastTime;
  }

  @Override
  public int compareTo(HitRate o) {
   // 先比较访问次数,如果次数一样,比较最后访问时间
   int compare = Integer.compare(this.hitCount, o.hitCount);
   return compare == 0 ? Long.compare(this.lastTime, o.lastTime) : compare;
  }
}
}


15. redis 常见的性能问题有哪些?该如何解决?

1. Redis master执行save命令保存快照的时候,会使用主进程来操作,会导致进程阻塞,建议使用bgsave命令,fork()出一个子进程来保存快照。
2. Master如果开启AOF日志功能,如果不重写AOF文件,影响比较小,但是随着系统的运行,AOF文件会越来越大,当Master重新启动的时候,AOF过大会影响重启的恢复速度。一般重启使用RDB快照来进行数据恢复。
3. Master开启了AOF功能,执行BGREWRITEAOF命令进行AOF文件重写的时候,AOF重写会占用大量的CPU和内存资源。
4. Redis的主从复制性能问题,为了Master与slave之间的性能与网络稳定性,最好将Master与slave部署再同一个局域网内

相关推荐

【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库

如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...

Pure Storage推出统一数据管理云平台及新闪存阵列

PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...

对Java学习的10条建议(对java课程的建议)

不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...

SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!

官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...

JDK21有没有什么稳定、简单又强势的特性?

佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...

「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了

在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...

Java面试题及答案最全总结(2025版)

大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...

数据库日常运维工作内容(数据库日常运维 工作内容)

#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...

分布式之系统底层原理(上)(底层分布式技术)

作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...

oracle 死锁了怎么办?kill 进程 直接上干货

1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...

SpringBoot 各种分页查询方式详解(全网最全)

一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...

《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略

《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...

LoadRunner(loadrunner录制不到脚本)

一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...

Redis数据类型介绍(redis 数据类型)

介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...

RMAN备份监控及优化总结(rman备份原理)

今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...

取消回复欢迎 发表评论: