⑨ 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、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)