关于Redis相关内容的基础学习

本文深入探讨了Redis缓存系统,包括缓存定义、优点、本地缓存与分布式缓存的对比,重点介绍了Redis的五大数据类型(字符串、字典、列表、集合、有序集合)及其应用场景。此外,讨论了Redis的持久化机制,如RDB、AOF和混合持久化,以及应对缓存雪崩、穿透和击穿的解决方案。最后,提到了Redis的主从同步、哨兵模式和集群服务,展示了Redis在高可用性和扩展性上的设计。
摘要由CSDN通过智能技术生成

Redis相关内容的学习(1)

1.缓存的定义

    缓存是一个高速数据交换的存储器,使用它可以快速的访问和操作数据。
在没有使用缓存之前,我们通常的业务调用流程是这样的,如图,前台用户通过Java程序来访问数据库的资源,当有多个用户访问的时候,同样也是执行的此流程。
在这里插入图片描述

    当公司的业务流程发展的越来越大的时候,我们Java 的程序也越来越多了,我们有些系统是负责咨询的,有些系统是负责电商的,有些程序是否则接口三方调用的等等…不同的程序都要去调用同一套数据库,因此数据库的压力十分的大,此时缓存就可以发挥它的作用了,我们可以在Java程序和数据库之间创建一个缓存系统,这样,当Java的程序需要调用数据时,首先,会从缓存系统中查看有没有相关的数据,如果没有缓存的情况下,此时才会访问数据库,把此条信息存储到缓存中,当Java 程序第二次进行访问的时候,因为缓存中已经存储了信息,此时,就会直接将数据返回,就无需进行访问数据库的操作了,因此数据库的压力就会的到缓解。
在这里插入图片描述

2.缓存的优点:

1.缓存中的数据是以Key-Value的形式进行存储的,所以查询效率比较快。
2.缓存是存储在内存中的,而一般的数据库是将数据存储在磁盘,因此缓存的操作和读取会比较快。
3.缓存的可扩展能力比较强,更容易进行分布式应用的部署,相对于单机数据库来说,优势比较大了,可以将一台服务器压力分发给集群中的每台服务器,因此具有更高的效率以及更快的响应速度。

3.缓存的分类

缓存大致可以分为两类,即本地缓存和分布式缓存。
    本地缓存:本地缓存也叫单机缓存,也就是说可以应用在单机环境下的缓存。所谓的单机环境,是指将服务部署到一台服务器上,本地缓存只适用于当前系统,如图所示:
在这里插入图片描述

    分布式缓存:是指可以应用在分布式系统中的缓存,所谓的分布式系统是指将一套服务器部署到多台服务器,并且可以通过网关,比如Nginx进行统一的分发访问管理,分布式的缓存适用于所有的服务器(单台服务器多台服务器都可以),这是因为整个分布式环境的背后其实是有一个全局的缓存系统的,而这个缓存系统相当于所有的程序共用的,对于用户1来说,他操作的缓存是一个全局的缓存,当用户而访问缓存时,他拿到的也是一个共用的缓存。如下图所示:

在这里插入图片描述

4.常见缓存的使用

    本地缓存的常见使用:Spring Cache、MyBatis的缓存等。
    分布式缓存的常见使用:redis和Memchached。

4.1 本地缓存:Spring Cache

    在Spring Boot项目,可以直接使用Spring 内置Cache(本地缓存),只需要完成以下三个步骤,就可以正常使用了:
(1)开启缓存
在Spring Boot的启动类上添加如下代码,开启缓存。
在这里插入图片描述
2.操作缓存
在这里插入图片描述
3.调用缓存
在这里插入图片描述
同一个id,多次执行,控制台只会打印一次“我进入了getUser方法”,使用不同的Id,会再打印一次,但之后访问就不会打印了,此时就是缓存起到了作用。

4.2分布式缓存

1.执行原理
    项目一、项目二、项目三分别代表分布式环境,它们都会调用同一个缓存系统,也就是Redis,进行命令的发送和命令的解析,当项目一将某个Key值存到缓存系统中Redis中的时候,其实是一个全局的缓存操作,因此项目二也可以项目二可以访问到项目一存储的信息而进行直接的读取操作。因此我们可以得出Redis是一个完美的全局的分布式缓存,它可以适应于单机环境或者是多机分布式环境。
在这里插入图片描述
总结: 通常情况下,如果是单机的Spring项目,会直接使用Spring Cache作为本地缓存,如果是分布式环境一般会使用Redis.

5.Redis数据类型和使用

Redis有5大数据类型:
String----------------字符串类型
Hash-----------------字典类型
List--------------------列表类型
Set---------------------集合类型
ZSet-------------------有序集合类型
其中最常用的是字符串和字典类型。
    为了演示Redis中数据类型的使用,我们首先要进入Docker中的Redis容器,具体步骤如下:首先在Xshell中输入进入Redis容器的指令,也就是docker exec -it myredis redis-cli,紧接着输入你安装docker时设置的密码,紧接着就可以使用指令进行相关操作了。
在这里插入图片描述

5.1字符串类型

5.1.1 字符串信息的存储结构

    字符串类型(Simple Dynamic Strings 简称SDS),它是以key-value的形式进行存储的,根据key来存储和获取value值,它的使用相对来说比较简单,但是实际项目中应用非常广泛。

5.1.2 字符串信息的简单存取

    字符串类型的简单读取操作:
在这里插入图片描述

5.1.3 字符串数据设置过期时间

    我们还可以给存储的数据设置一个过期时间,如:
在这里插入图片描述

我们给数据设置的最大过期时间为5秒,过期之后会自动把数据进行淘汰,因此我们读到的数据为nil了。

5.1.4 字符数据类型的常见使用场景

1.存放用户(登录)信息。
2.存放文章详情和列表信息。
3.存放和累计网页的统计信息,如存储网页被访问了多少次。

5.2 字典类型

5.2.1 字典类型信息的存储结构

    字典类型(Hash)就相当于我们Java中的Map,只不过这个Map的key值是String,然后value值又是一个Map,类似于Map<String,Map<String,String>>这样的结构。下面这张图表示的就是字典类型数据存储的格式:我们存储了article_001这样的一篇文章,文章名是一个主键,它里面又是一个Map的结构,又是由key和value的这种形式进行存储的。

在这里插入图片描述

5.2.2 字典信息的简单存取

    在下图中,(integer) 2表示我们在h2中存储了两个字段
                                    图1,其具体结构如图2所示。
在这里插入图片描述
                                    图2
在这里插入图片描述

5.2.3 字典数据类型的常见使用场景

    同理我们也可以使用字典类型来存储用户信息,并且使用字典类型来存储此类信息就无需手动序列化和反序列化数据了。

:字典类型和字符串类型存储用户信息的区别
如何用字符串存储用户登录信息,我们就必须将用户对象进行JSON转换,JSON转换成字符串,然后再进行存入;如果使用字典类型,我们就无需将一个对象转换成字符串,我们可以直接将字符串进行一个相应的存储。

5.3 列表类型

5.3.1 列表类型信息的存储结构

    列表类型(List)是一个使用链表结构存储的有序结构,它的元素插入会按照先后顺序存储到链表中,因此它的元素操作(插入和删除)时间复杂度为O(1)。

5.3.2 列表类型信息的简单存取

    我们使用时,也是用key-value模型,用lpush list 1 2 3存储数据,lpop list(获取并删除列表中的第一个元素),list在这儿相当于是key值,1 2 3是存储的value值。
在这里插入图片描述

5.3.3 列表类型的常见使用场景

1.消息队列
    列表类型可以使用rpush实现先进先出的功能,同时又可以使用lpop轻松的弹出(查询并删除)第一个元素,所有列表类型可以用来实现消息队列。
2.文章列表
    我们可以将文章的所有id关联到这个用户的身上,那么我们就可以将list作为用户的K值,然后后面所有值作为用户的所有文章id,此时我们就可以实现文章列表功能。

5.4 集合类型

5.4.1 列表类型信息的存储结构

    集合类型(Set)是一个无序并且唯一的键值集合。
    集合和列表的差别就在于不能存储重复的数据。
    列表是按照元素的先后顺序存储元素的,而集合则是无需方式存储元素的。

5.4.2 集合类型信息的简单存取

在这里插入图片描述

5.4.3 集合类型的常见使用场景

1.微博中关注我的人和我关注的人都适合用集合存储,可以保证人员不会重复。
2.中奖人员的信息也适合用集合类型存储,这样会保证一个人不会重复中奖。

5.5 有序集合类型

5.5.1 列表类型信息的存储结构

    有序集合类型(Sorted Set)相比于集合类型多了一个排序属性score(分值),对于有序集合Zset来说,每个存储元素相当于有两个值组成的,一个是有序结合的元素值,一个是排序值。有序集合的存储元素值也是不能重复的,但是分值是可以重估的,例如:
在这里插入图片描述

5.5.2 集合类型信息的简单存取

在这里插入图片描述

5.4.3 集合类型的常见使用场景

1.存储学生的成绩,我们可以对成绩进行排名。
2.粉丝列表,根据关注的先后顺序进行排序。

6.Redis持久化

    所谓的持久化就是将数据从内存保存到磁盘的过程,它的目的就是为了防止数据丢失。因为在内存中的数据在服务器重启之后就会丢失,而磁盘的数据则不会,因此为了系统的稳定起见,我们需要将数据进行持久化。同时持久化功能又是Redis和Memcached最主要的区别之一,因为Redis支持持久化而Memcached不支持。
    持久化是Redis非常重要的一个功能,因为它保证了Redis缓存系统的稳定性。

6.1 Redis持久化的三种方式

    快照方式(RDB,Redis DataBase): 将某一时刻的内存数据,以二进制的方式写入磁盘。
    文件追加方式(AOF,Append Only File): 记录所有的操作命令,并以文本的形式追加到文件中。
    混合持久化方式: Redis 4.0之后新增的方式,混合持久化结合了RDB和AOF的优点,再写入的时候,先把当前的数据以RDB的形式写入文件的开头,再将后续的操作命令以AOF的个是存入文件按,这样既能保证Redis重启时的速度,又能降低数据丢失的风险。

6.1 Redis持久化策略设置

    可以在redis命令行中执行config set aof-use-rdb-preamble yes来开启混合持久化,当开启混合持久化时Redis就以混合持久化方式来作为持久化策略,当没有开启混合持久化的情况下,使用config set appendonly yes来开启AOF持久化策略,当AOF与混合持久化都没有开启的情况下默认会是RDB持久化的方式。

7.缓存雪崩和缓存穿透以及缓存击穿

7.1 缓存雪崩

7.1.1 缓存雪崩的介绍

1.    缓存雪崩是指在短期时间内,有大量的缓存同时过期,导致大量的请求直接查询数据库,从而对数据库造成了巨大的压力,严重情况下可能会导致数据库宕机的情况就叫做缓存雪崩。
     在正常情况下的请求流程为: 用户发送请求到Java的应用程序,Java的应用程序会从Redis中查看是否有相关的信息,如果有相关的信息,直接返回;如果没有,再去数据库中查找,并且把数据库中的信息同步到Redis当中,然后再返回给应用程序,这样当第二次访问Redis的时候,因为Redis已经从数据库拉取了相应的数据,直接就可以得到数据并进行数据的返回。
                                    图1
在这里插入图片描述
假如Redis发生了缓存雪崩的情况,就会出现图2这样的情况:当用户有大量的访问请求到应用程序之后,应用程序去查询Redis发现大量的缓存都已经过期了,此时会直接去访问数据库,就造成了数据库的压力骤然上升。
                                    图2
在这里插入图片描述

7.1.2 缓存雪崩的解决方案

1.加锁排队
    加锁排队可以起到缓冲的作用,防止大量的请求同时操作数据库,但它的缺点时增加了系统的响应时间,降低了系统的吞吐量,牺牲了一部分用户体验。
2.随机化过期时间
    为了避免缓存同时过期,可在设置缓存时添加随机时间,这样就可以极大的避免大量的缓存同时失效。

//缓存的原本失效时间
int exTime = 10 * 60;
//随机数生成类
Random random = new Random();
//缓存设置
jedis.setex(cacheKey,exTime+random.nextInt(1000),value);

3.设置二级缓存
    二级缓存指的是除了Redis本身的缓存,在设置一层缓存,当Redis失效之后,先去查询二级缓存。

    例如可以设置一个本地缓存,在Redis失效的时候先去查询本地缓存而不是查询数据库。
加入二级缓存之后程序执行流程,如图所示:
在这里插入图片描述

7.2 缓存穿透

7.2.1 缓存穿透的介绍

    缓存穿透是指查询数据库和缓存都无数据,因为数据库查询无数据,处于容错考虑,不会将结果保存到缓存中,因此每次请求都会去查询数据库,这种情况就叫做缓存穿透。

7.2.2 缓存穿透的解决方案

缓存空结果
    另一种方式是我们可以把每次从数据库查询的数据都保存到缓存中,为了提高前台用户的使用体验(解决长时间内查询不到任何信息的情况),我们可以将空结果的缓存时间设置的短一些,例如3-5分钟。
缓存空结果

7.3 缓存击穿

7.3.1 缓存击穿的介绍

    缓存击穿指的是某个热点缓存,在某一时刻恰好失效了,然后此时刻刚好有大量的并发请求,此时这些请求将会给数据库造成巨大的压力,这种情况就叫做缓存击穿。

7.3.2 缓存击穿的解决方案

1.加锁排队
    此处理方式和缓存雪崩加锁排队的方法类似,都是在查询数据库时加锁排队,缓冲操作请求以此来减少服务器的运行压力。

2.设置永不过期
    对于某些热点缓存,我们可以设置永不过期,这样就能保证缓存的稳定性,但需要注意在数据更改之后,要及时更新此热点缓存,不然就会造成查询结果的误差。

7.3 缓存预热

7.3.1 缓存击穿的介绍

    首先来说,缓存预热并不是一个问题,而是使用缓存是的一个优化方案,它可以提高前台用户的使用体验。
    缓存预热指的是在系统启动的时候,先把查询结果预存到缓存中,以便用户后面查询时可以直接从缓存中读取,以节约用户的等待时间。

7.3.2 缓存预热的实现思路

    1.把需要缓存的方法写在系统初始化的方法中,这样系统在启动的时候就会自动的加载数据并缓存数据,
    2.把需要缓存的方法挂载到某个页面或者后端接口上,手动触发缓存预热。
    3.设置定时任务,定时自动进行缓存预热。

7.Redis集群

    随着业务的不断发展,单机Redis的性能已经不能满足我们的需求了,此时我们需要将单机Redis扩展为多机服务,Redis多机服务主要包含以下三个内容:
(1)Redis主从同步
(2)Redis哨兵模式
(3)Redis集群服务

7.1主从同步

    主从同步(主从复制)是Redis高可用服务的基石,也是多机运行中最基础的一个。我们要把主要存储数据的节点叫做主节点,把其它通过复制主节点数据的副本节点叫做从节点。

在这里插入图片描述

    在Redis中一个主节点可以拥有多个从节点,一个从节点也可以是其它服务器的主节点,如下图所示:
在这里插入图片描述

主从同步优缺点分析:
主从同步具有以下三个优点:
1.性能方面:有了主从同步之后,可以把查询任务分配给从服务器,用主服务器来执行写操作,这样极大提高了程序运行的效率,把所有压力分摊到各个服务器了;
2.高可用:当有了主从同步之后,当主服务器节点宕机之后,可以很迅速的把从节点提升为主节点,为Redis服务器的宕机恢复节省了宝贵的时间。
3.防止数据丢失
当主服务器磁盘坏掉之后,其它从服务器还保留着相关的数据,不至于数据全部丢失。

2.哨兵模式

假如晚上发生了主从服务器宕机的情况,尤其是在主从服务器节点比较多的情况下,如果需要人工恢复,那么需要的时间和难度是很大的,因为我们需要一个自动的工具----------Redis Sentinel (哨兵模式) 来把手动的过程变成自动的,让Redis拥有自动容灾恢复(failover)的能力。Redis Sentinel的最小分配单位是一主一从。
哨兵模式如下图所示:
在这里插入图片描述
哨兵工作原理:
    哨兵的工作原理是,首先每个Sentinel会议每秒钟1次的频率,向已知的主服务器、从服务器和以及其它Sentinel实例,发送一个PING命令。
    如果最后一次有效回复PING命令的时间超过down-after-milliseconds所配置的值(默认30s),那么这个实例会被Sentinel标记为主观下线。
    如果一个主服务器被标记为主观下线,那么正在监视这个主服务器的所有Sentinel节点,要以每秒1次的频率确认主服务器的确进入了主观下线状态。
    如果有足够数量(quorum 配置值)的Sentinel在指定的时间范围内同意这一判断,那么这个主服务器被标记为客观下线。此时所有的Sentinel会按照规则协商自动选出新的主节点。

注意:一个有效的PING回复可以是:+PONG、-LOADING或者-MASTERDOWN。如果返回值非以上三种回复,或者在指定时间内没有回复PING命令,那么Sentinel认为服务器返回的回复无效(non-valid)。

Redis集群服务

    Redis集群(Redis Cluster)是Redis 多机云从最完美的终极方案,它是Redis 3.0 之后推出的服务,它的出现可以让我们完全抛弃主从同步和哨兵模式来实现Redis多机运行。
    Redis Cluster是无代理模式去中心化的运行模式,客户端发送的绝大数命令会直接交给相关节点执行,这样大部分情况请求命令无需转发,或仅转发一次的情况下就能完成请求与响应,所以集群单个节点的性能与单机Redis服务器的性能是非常接近的,因此在理论情况下,当水平扩展已被的主节点就相当于请求处理的性能也提高了已被,所以Redis Cluster的性能是非常高得。

Redis Cluster架构图如下所示:
在这里插入图片描述
    从上图可以看出Redis的主从同步只能有一个主节点,而Redis Cluster可以拥有无数个主从节点,因此Redis Cluster拥有更强大的平行扩展能力,也就是说当Redis Cluster拥有两个主从节点时,从理论上来讲Redis的性能相比于单机服务来说性能提升了两倍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值