zoukankan      html  css  js  c++  java
  • Redis从入门到高级笔记【涵盖重点面试题】

    1. NoSQL数据库

    DBEngines网站中会统计目前数据库在全世界的排名

    1.1 什么是NoSQL

    最常见的解释是"non-relational",很多人说它是"Not only SQL"
    NoSQL仅仅是一个概念,泛指非关系型数据库
    区别于关系型数据库,他们不保证关系数据的ACID特性

    1.2 NoSQL的特点

    应用场景
    高并发的读写
    海量数据的读写
    高可扩展性
    速度快
    不适用场景
    需要事务支持
    基于sql的结构化查询存储,处理复杂的关系,需要即席查询(用户自定义查询条件的查询)

    1.3 NoSQL有哪些
    1.3.1 memchache

    很早出现的NoSQL数据库
    数据都在内存中,一般不持久化
    支持简单的key-value模式
    一般是作为缓存数据库辅助持久化的数据库

    1.3.2 redis

    几乎涵盖了memchache的绝大部分功能
    数据都在内存中,支持持久化,主要用作备份恢复
    除了支持简单的key-value模式,还支持多种数据结构的存储,比如 list,set,hash,zset等
    一般是作为缓存数据库 辅助持久化的数据库
    现在市面上用得非常多的一款内存数据库

    1.3.3 mongoDB

    高性能、开源、模式自由(schema free)的文档型数据库
    数据都在内存中,如果内存不足,把不常用的数据保存到硬盘
    虽然是key-value模式,但是对value(尤其是json)提供了丰富的查询功能
    支持二进制数据及大型对象
    可以根据数据的特点替代RDBMS,成为独立的数据库,或者配合RDBMS,存储特定的数据库

    1.3.4 列存储HBase

    HBase是Hadoop项目中的数据库,它用于需要对大量的数据进行随机、实时读写操作的场景中。HBase的目标就是处理数据量非常庞大的表,可以用普通的计算机处理超过10亿行数据,还可以处理有数百万列元素的数据表

    1. Redis介绍
      2.1 Redis的基本简介

    Redis是当前比较热门的NoSQL系统之一
    它是一个开源的,使用ANSI C语言编写的key-value存储系统
    和memcache类似,但是很大程度上补偿了memcache的不足,redis数据都是缓存在计算机内存中,不同的是,memcache只能将数据缓存到内存中,无法自动定期写入硬盘,这就表示,一断电或者重启,内存清空,数据就会丢失。

    2.2 Redis的应用场景

    取最新N个数据的操作
    排行榜应用,取TOP N操作
    需要精准设定过期时间的应用
    计数器应用
    uniq操作,获取某段时间所有数据排重值
    实时系统,发垃圾系统
    缓存

    2.3 Redis的特点

    高效性
    读取速度是110000次/s,写的速度是81000次/s
    原子性
    支持多种数据结构 string list set hash zset
    稳定性:持久化,主从复制(集群)
    其他特性:支持过期时间,支持事务,支持订阅

    1. Redis单机环境安装
    # 下载redis安装包
    cd /opt/software
    wget http://download.redis.io/releases/redis-3.2.8.tar.gz
    
    #解压redis压缩包到指定目录
    tar -zxvf redis-3.2.8.tar.gz -C /opt/module/
    
    
    # 安装c程序运行环境
    yum -y install gcc-c++
    
    
    # 安装tcl
    # 在线安装
    yum -y install tcl
    
    
    # 编译redis
    
    cd redis-3.2.8/
    make MALLOC=libc
    make test && make install PREFIX=/opt/module/redis-3.2.8
    
    
    # 修改redis配置文件
    
    cd /opt/module/redis-3.2.8/
    mkdir log
    mkdir data
    
    vim redis.conf
    # 修改第61行
    bind hadoop104.sl.cn
    # 修改第128行
    daemonize yes
    # 修改第163行
    logfile "/opt/module/redis-3.2.8/log/redis.log"
    # 修改第247行
    dir /opt/module/redis-3.2.8/data
    
    
    # 启动redis
    
    cd /opt/module/redis-3.2.8
    bin/redis-server redis.conf
    
    
    # 关闭redis
    
    bin/redis-cli -h hadoop104 shutdown
    
    
    # 连接redis客户端
    bin/redis-cli -h hadoop104
    
    1. Redis的数据类型

    string字符串
    list列表
    set集合
    hash表
    zset有序集合

    4.1 对字符串string的操作

     # 设置获取key
     set hello world
     get hello
     # 批量设置获取key
     mset hello1 world1 hello2 world2
     mget hello1 hello2
     # 设置一个key,并指定过期时间
     setex hello 3 world
     # INCR +1  DECR -1  将key中存储的数字加1或者减1
     set pv 1
     INCR pv
    

    注意:
    在执行累加器的操作时,千万不能使用set/get来操作,会造成一些数据被覆盖【多个线程同时在操作redis缓存】
    要使用INCR/DESC/INCRBY,就是执行原子的累加/累减

    4.2 对hash表的操作

    # 设置获取key  大key和小key
    hset userinfo userid 1     -->  hget userinfo userid
    hset userinfo username sun 	 -->  hget userinfo username
    # 获取hash中所有key
    hkeys userinfo
    # 获取hash中所有的key和值
    hgetall userinfo
    

    4.3 对list列表的操作

    # 往列表的头部插入数据
    lpush list 1 2 3 4 
    # lrange表示取指定范围[索引]的元素
    lrange list 0 -1
    

    4.4 对set集合的操作

    # 向集合添加元素
    sadd set_test 1 2 3 4
    # 获取所有的元素
    smembers set_test
    # 获取元素的个数
    scard set_test
    

    4.5 对key的操作

    # 删除一个key
    del list
    # 检查key是否存在
    exists list
    # 返回所有的key
    keys *
    

    4.6 对zset的操作

    它用来保存需要排序的数据,例如排行榜
    有序集合中,每个元素都有score(权重),以此来对元素进行排序
    它有三个元素:key member和score

    # 向集合添加元素
    zadd key score1 member1 score2 member2 ...
    # 获取所有的元素
    zrange key 0 -1 withscores
    # 获取元素的个数
    zcard key
    # 给member1的score1加一
    zincrby key increment member1
    # 求member1的排名
    # 默认升序  索引
    zrank key member1
    # 注意:这个操作效率很高,并不是重新排序,只是把zset反转即可
    zrevrank key member1
    

    4.7 对位图BitMaps的操作

    计算机最小的存储单位是位bit,BitMaps是针对位的操作的,相较于String,Hash,Set等存储方式更加节省空间
    BitMaps不是一种数据结构,操作是基于String结构的,一个String最大可以存储512M,那么一个BitMaps则可以设置2^32个位
    BitMaps单独提供了一套命令,所以在Redis中使用BitMaps和使用字符串的方法不太相同,可以把BitMaps想象成一个以位为单位的数组,数组的每个单元只能存储0和1,数组的下标在BitMaps中叫做偏移量
    BitMaps命令说明:将每个独立用户是否访问过网站放在BitMaps中,将访问的用户记作1,没有访问过的用户记作0,用偏移量作为用户的id

    4.7.1 设置值

    setbit key offset value
    

    4.7.2 获取值

    getbit key offset
    

    4.7.3 获取BitMaps指定范围值为1的个数

    bitcount key start end
    

    4.7.4 BitsMaps间的运算

    bitop operation destkey key 
    

    bitop是一个复合操作,它可以做多个BitMaps的and、or、not、xor(异或) 操作并将结果保存在destkey中

    4.8 对HyperLogLog结构的操作

    HyperLogLog常用于大数据量的统计,比如页面访问量统计或者用户访问量统计
    要统计一个页面的访问量(PV),可以直接用redis计数器或者直接存数据库都可以实现,如果要统计一个页面的用户访问量(UV),一个页用户一天内如果访问多次的话,也只能计算一次,这样,我们可以使用set集合来做,因为set集合是有去重功能的,key存储页面对应的关键字,value存储对应的userid,这种方法是可行的,但如果访问量较多,假如有几千万的访问量,这就麻烦了。为了统计访问量,要频繁创建set集合对象。

    # 查看hyperloglog的用法
    help @hyperloglog
    # pfadd key userid userid ...
    # pfcount key	
    # pfmerge destkey sourcekey sourcekey ...
    

    限制:
    这个HyperLogLog结构存在一定的误差,误差很小,0.81%,所以它不适合对精确度要求特别高的统计,而uv这种操作,对精确度要求没那么高,是可以适用该结构的
    HyperLogLog结构不会存储数据的明细,针对uv场景,它为了节省空间资源,只会存储数据经过算法计算后的基数值,基于基数值【去重后的长度】来进行统计的

    1. Redis Java API操作
      5.1 创建maven工程并导入依赖
    <dependencies>
            <!--Redis的java客户端-->
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>2.9.0</version>
            </dependency>
        	<!--单元测试-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.testng</groupId>
                <artifactId>testng</artifactId>
                <version>6.14.3</version>
                <scope>test</scope>
            </dependency>
    </dependencies>
    

    5.2 创建包结构和类

    在test目录下创建 com.sl.redis.api_test包结构
    创建RedisTest类

    5.3 连接以及关闭redis客户端

    public class RedisTest {
        private JedisPool jedisPool;
        @BeforeTest
        public void beforeTest() {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxIdle(10);  // 指定最大空闲连接数 10个
            config.setMinIdle(5);   // 指定最小空闲连接数 5个
            config.setMaxWaitMillis(3000); // 最大等待时间为3000ms
            config.setMaxTotal(50); // 最大连接数50
            jedisPool = new JedisPool(config, "hadoop104",6379);
    
        }
        @Test
        public void keysTest() {
            // 从redis连接池获取redis连接
            Jedis jedis = jedisPool.getResource();
            // 调用keys方法获取所有的key
            Set<String> keySet = jedis.keys("*");
            for (String key : keySet) {
                System.out.println(key);
            }
        }
        @AfterTest
        public void afterTest() {
            jedisPool.close(); // 关闭连接池
        }
    }
    
    1. Redis的持久化
      由于redis是一个内存数据库,所有的数据都是保存在内存中的,内存中的数据极易丢失,所以redis的数据持久化就显得尤为重要,在redis当中,提供了两种数据持久化的方式,分别为RDB以及AOF,且redis默认开启的数据持久化方式为RDB

    6.1 RDB持久化方案

    redis会定期保存数据快照至一个rdb文件中,并在启动时自动加载rdb文件,恢复之前保存的数据。可以在配置文件中配置redis进行快照保存的时机:

    # 表示在seconds秒内如果发生了changes次数据修改,则进行一次rdb快照保存
    save [seconds] [changes]
    

    rdb是一种全量备份,是将整个redis中的所有的数据,保存到一个rdb文件中

    6.2 AOF持久化方案

    redis会把每一个写请求都记录在一个日志文件里,在redis重启时,会把aof文件中记录的所有写操作顺序执行一遍,确保数据恢复到最新。

    aof默认是关闭的,可以进行如下配置

    # 开启aof
    appendonly yes
    # 配置aof
    appendfsync everysec 由后台线程每秒fsync一次
    appendfsync always 每写入一条日志就进行一次fsync操作,数据安全性最高,但速度最慢
    
    
    AOF rewrite
        只保留能够把数据恢复到最新状态的最小写操作集
    

    6.3 RDB or AOF

    RDB效率要高,因为它是直接将Redis的最新数据完整的保存下来,但如果Redis中存储的数据量比较大时,也会有一定的性能消耗,因为它需要创建额外的进程来进行数据的持久化,所以要制定合理的策略
    AOF效率相对RDN要低一些,因为它会将历史的写操作都执行一遍来进行恢复,同时在执行写操作的时候也会将每一个指令存储下来,当我们对数据的安全性要求较高的时候,可以考虑AOF

    1. Redis的高级操作
      7.1 Redis事务
      7.1.1 Redis事务简介

    Redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令
    没有隔离级别的概念,不保证原子性!!!
    一个事务从开始到执行会经历以下三个阶段:
    第一阶段:开始事务
    第二阶段:命令入队
    第三阶段:执行事务
    注意:
    只有当语法有错误的时候,事务才会回滚,但是运行的错误,事务不会回滚
    为什么redis不支持事务回滚? 为了保证性能!!!

    7.1.2 Redis事务演示

    set k1 v1
    set k2 v2
    multi # 开启事务
    set k1 11
    set k2 22
    exec  # 依次执行命令 
    get k1
    get k2
    

    7.2 Redis过期策略

    Redis的过期策略是指当Redis中缓存的key过期了,Redis如何处理 【针对设置了expire过期时间的key】
    过期策略有以下三种:
    定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会被立即清除
    懒惰过期:只有当访问一个key时,才会判断该key是否过期,过期则删除
    定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key

    7.3 内存淘汰策略

    指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据
    实际项目中设置内存淘汰策略:maxmemory-policy allkeys-lru,移除最近最少使用的key
    默认:maxmemory-policy noeviction

    1. Redis的主从复制架构
      8.1 简介

    主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点。
    默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点或者没有,但一个从节点只能由一个主机点。

    8.2 主从复制原理

    当从数据库启动后,会向主数据库发送SYNC命令
    主数据库收到命令后,开始在后台保存快照(RDB持久化),并将保存快照期间接收到的命令缓存下来
    快照完成后,Redis(master)将快照文件和所有缓存的命令发送给从数据库
    Redis(slave)接收到RDB和缓存命令时,会开始载入快照文件并执行接收到的缓存的命令

    注意:后续,每当主数据库接收到写命令时,就会将命令同步给从数据库。所以3和4只会在初始化的时候执行。
    8.3 主从复制的应用场景

    读写分离:写操作由master节点操作,读操作由slave节点操作
    比较适合用来处理读多写少的场景。而当单个主数据库不能满足需求时,就需要使用Redis 3.0后推出的集群功能
    从数据库持久化
    Redis中相对耗时的就是持久化,为了提高性能,可以通过主从复制创建一个或多个从数据库,并在从数据库中启动持久化,同时在主数据库中禁用持久化。
    当从数据库崩溃重启后主数据库会自动将数据同步过来,无需担心数据丢失
    而当主数据库崩溃时,后续我们可以通过哨兵来解决

    1. Redis中的Sentinel架构
      9.1 Sentinel介绍

    哨兵是Redis的高可用解决方案:由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器

    9.2 配置哨兵

    # 每台服务器都需要对哨兵进行配置
    vi sentinel 
    # 修改第15行
    bind 主机名
    # 在下方添加配置,让sentinel服务后台运行
    daemonize yes
    # 修改第71行
    sentinel monitor mymaster hadoop104 6379 2
    

    参数说明:
    sentinel monitor 代表监控
    mymaster 代表服务器的名称,可以自定义
    hadoop104 代表监控的主服务器,6379代表端口
    2代表只有两个或两个以上的哨兵认为主服务不可用的时候才会进行failover操作

    9.3 sentinel模式代码开发连接

    public class RedisSentinelTest {
        private JedisSentinelPool jedisSentinelPool;
        @BeforeTest
        public void beforeTest() {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxIdle(10);  // 指定最大空闲连接数 10个
            config.setMinIdle(5);   // 指定最小空闲连接数 5个
            config.setMaxWaitMillis(3000); // 最大等待时间为3000ms
            config.setMaxTotal(50); // 最大连接数50
            HashSet<String> sentinelSet = new HashSet<String>();
            sentinelSet.add("192.168.15.104:26379");
            sentinelSet.add("192.168.15.105:26379");
            sentinelSet.add("192.168.15.106:26379");   
            jedisSentinelPool = new JedisSentinelPool("mymaster", sentinelSet, config);
        }
        @Test
        public void test() {
            Jedis jedis = jedisSentinelPool.getResource();
            Set<String> keySet = jedis.keys("*");
            for (String key : keySet) {
                System.out.println(key);
            }
        }
        @AfterTest
        public void afterTest() {
            jedisSentinelPool.close();
        }
    }
    
    
    1. Redis集群
      10.1 简介

    Redis最开始使用主从模式做集群,若master宕机需要手动配置slave转为master;后来为了高可用提出哨兵模式,该模式下有一个哨兵监视master和slave,若master宕机可自动将slave转为master,但还是有一个问题,就是不能动态扩充,所以在redis 3.x提出cluster集群模式

    为什么要实现Redis Cluster?
    主从复制不能实现高可用
    QPS(每秒查询率)可能无法满足业务需求
    数据量的考虑
    技术组件不是内存越多越好,因为内存配置的越大,例如JVM的Heap内存配置的很大后,就会导致内存碎片整理很耗时,垃圾回收会发生卡顿,导致集群的效率下降
    网络流量需求,可考虑使用分布式来进行分流

    10.2 分布式存储的重点–分区

    mysql–根据顺序分区的方式,例如:根据主键来进行分区(分库分表),一般是在java web中会遇到

    按照哈希取余的方式来进行分区(类似于MapReduce的默认分区策略)
    当分区的数量发生变化的时候,会导致key产生较大影响,原先分布在第一个节点上的数据,分区数量调整后,指定到了其他的分区

    按照一致性哈希的方式来进行分区
    是一个环状的hash空间,它的分区算法是和哈希取余算法不一样的
    算法过程 :
    首先将每一个分区的标号(0,1,2)进行算法计算,然后将计算出来的值,放入到环状的hash空间
    再将key同样进行算法计算,然后将计算出来的值,同样也放入到环状的hash空间
    最后,找到key在hash空间中距离自己位置最近的分区,放入到该分区中
    这样,当分区的数量发生变化的时候,影响不会太大

    Redis集群是使用槽的方式来进行分区的
    现有一个槽的空间(0-16353),需要将这些空间分布到不同的节点中
    node1: 0-3xxx
    node2: 3xxx-6xxx

    有一个key,首先进行CRC16算法&16353 = 值,Redis会判断这个值应该在哪个槽中

    10.3 集群搭建

    # 下载redis-5.0.8安装包
    cd /opt/software
    wget http://download.redis.io/releases/redis-5.0.8.tar.gz
    # 解压
    tar -zxvf redis-5.0.8.tar.gz -C /opt/module/
    # 编译
    cd redis-5.0.8/
    make
    # 安装至指定目录
    make PREFIX=/opt/module/redis-5.0.8-bin install
    # 创建安装目录软连接
    cd /opt/module
    ln -s redis-5.0.8-bin redis
    # 配置环境变量
    export REDIS_HOME=/opt/module/redis
    export PATH=:$PATH:$REDIS_HOME/bin
    # 拷贝配置文件
    cd /opt/module/redis-5.0.8
    cp redis.conf /opt/module/redis
    # 修改配置文件  每台机器启动2个redis服务,一个是主节点服务:7001,一个从节点服务:7002
    cd redis
    mkdir 7001 7002
    cp redis.conf 7001/redis_7001.conf
    vi 7001/redis_7001.conf
    # 步骤较多,自行百度解决......
    # 启动集群,需要启动6个服务就可以了
    
    
    
    初始化集群(只需要一次):
    
    /opt/module/redis/bin/redis-cli --cluster create 192.168.15.104:7001 192.168.15.104:7002 192.168.15.105:7001 192.168.15.105:7002 192.168.15.106:7001 192.168.15.106:7002 --cluster-replicas 1
    
    
        --replicas 1 1其实代表的是一个比例,就是主节点数/从节点数的比例
    
    测试集群:(在任意一台机器)
    
    redis-cli -c -p 7001
    

    注意:
    配置完后,需要启动所有的端口Redis进程,一共有6个
    启动好6个节点(进程)后,需要进行集群初始化
    集群初始化会自动分配master和slave,我们可以指定一个master对应几个slave
    redis还会自动分配槽
    连接redis集群
    redis-cli -c -p 端口号
    但我们访问某个key的 时候,如果这个key不在本机,redis集群会自动跳转到另外的机器

    补充:

    问题解决办法
    看log
    StackoverFlow网站(上面有各种异常解决办法)
    看源码
    学习技术的三点
    轻量级框架、技术组件(轻量级是要花少一点时间去学习各种API,因为此时没有应用场景)
    重量级项目(将技术组件结合起来,切记:和业务场景结合在一起)
    大师级面试题(提升自己的沟通表达能力、组织话术、熟记各种原理)

    10.4 JavaAPI操作redis集群

    JedisPool–操作单机版本的redis

    JedisSentinelPool–操作哨兵系统的主从结构

    JedisCluster–操作redis集群

    public class RedisClusterTest {
        private JedisCluster jedisCluster;
        @BeforeTest
        public void beforeTest() {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxIdle(10);  // 指定最大空闲连接数 10个
            config.setMinIdle(5);   // 指定最小空闲连接数 5个
            config.setMaxWaitMillis(3000); // 最大等待时间为3000ms
            config.setMaxTotal(50); // 最大连接数50
    
            HashSet<HostAndPort> hostAndPort = new HashSet<HostAndPort>();
            hostAndPort.add(new HostAndPort("hadoop104", 7001));
            hostAndPort.add(new HostAndPort("hadoop104", 7002));
            hostAndPort.add(new HostAndPort("hadoop105", 7001));
            hostAndPort.add(new HostAndPort("hadoop105", 7002));
            hostAndPort.add(new HostAndPort("hadoop106", 7001));
            hostAndPort.add(new HostAndPort("hadoop106", 7002));
    
            jedisCluster = new JedisCluster(hostAndPort, config);
    
        }
        @Test
        public void test() {
            jedisCluster.set("k2","v2");
            System.out.println(jedisCluster.get("k2"));
        }
        @AfterTest
        public void afterTest() throws IOException {
            jedisCluster.close();
        }
    }
    

    注意事项:
    在构建JedisCluster的时候,需要将集群中的所有主从节点添加到set中
    如果使用JedisCluster操作Redis的时候,不再需要获取Redis连接,直接去操作Redis即可,因为JedisCluster已经封装好了对应的操作

    10.5 Redis集群面试题

    问题1:Redis的多数据库机制,了解多少?

    正常版:Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,单机下的redis可以支持16个数据库(默认下标为0~15)。
    
    高调版:在redis cluster架构下,只有一个数据库空间,即0下标的数据库,因此,我们没有使用Redis的多数据功能。
    

    问题2:懂Redis的批量操作吗?

    正常版:懂一点。比如mset、mget操作等。
    
    高调版:在生产上采用的是Redis Cluster结构,不同的key会划分到不同的slot中,因此直接使用mset或者mget等操作是行不通的。
    

    问题3:Redis集群机制中,你觉得有什么不足的地方吗?

    正常版:不知道
    
    高调版:假设有一个key,对应的value是hash类型的,如果hash对象非常大,是不支持映射到不同节点!只能映射到集群中的一个节点上!还有就是做批量操作比较麻烦!
    

    问题4:在Redis集群模式下,如何进行批量操作?

    正常版:不知道
    
    高调版:如果执行的key数量比较少,就不用mget了,就用串行get操作。如果真的需要执行的key很多,就需要使用Hashtag保证该这些key映射到同一台redis节点上
    

    问题5:懂Redis事务吗?

    正常版:redis事务是一系列redis命令的集合
    
    高调版:在生产中采用的是redis cluster架构,不同的key是有可能分配在不同的redis节点上,在这种情况下redis的事务机制是不生效的,其次,redis事务不支持回滚操作
    
    1. Redis高频面试题

    在应用程序和mysql数据库之间建立一个中间层:redis缓存,通过redis缓存可以有效减少查询数据库的时间消耗,但是引入redis又有可能出现缓存穿透,缓存击穿,缓存雪崩等问题

    11.1 缓存穿透

    key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。
    一言以蔽之:查询key,缓存和数据源都没有,频繁查询数据源
    解决的方案:
    方案1:当查询不存在时,也将结果保存在缓存中
    方案2:提前过滤掉不合法的请求,可以使用redis中的布隆过滤器【可以快速的过滤掉缓存中不存在的key】

    11.2 缓存击穿

    key对应的数据库存在,但在redis中过期
    一言以蔽之:查询key,缓存过期,大量并发,频繁查询数据源
    解决的方案:
    使用互斥锁
    setnx("互斥锁", 1) : 表示当key不存在的时候,才会设置一个key

    11.3 缓存雪崩

    当缓存服务器重启或者大量缓存集中在某一个时间失效
    一言以蔽之:缓存不可用,频繁查询数据源
    解决的方案:
    加锁或者消息队列
    将缓存失效时间分散开

    11.4 Redis的命名规范

    使用统一的命名规范
    一般使用业务名(或数据库名)为前缀,用冒号分割,例如 业务名:表名:id
    控制key名称的长度,不能使用过长的key
    名称中不要包含特殊字符

  • 相关阅读:
    Spring Cloud(面试必备):服务雪崩、降级与熔断
    SpringCloud 分布式事务解决方案
    2020年3月25java现场面试(有点料)
    SpringCloud Feign工作原理
    MySQL数据库引擎详解
    MySQL Hardware--CentOS 6修改CPU性能模式
    MySQL Hardware--网络测试
    MySQL Execution Plan--EXPLAIN用法
    MySQL Event--Event and EventScheduler
    MySQL Error--Error Code
  • 原文地址:https://www.cnblogs.com/sanduzxcvbnm/p/14576815.html
Copyright © 2011-2022 走看看