Redis的原理及应用

发布一下 0 0

Redis是一个开源(BSD许可)的内存中的数据结构存储系统,可以用作数据库、缓存和消息中间件,支持多种类型的数据结构,例如String(字符串)、Hash(散列)、List(列表)、Set(集合)、ZSet(有序集合)、Bitmap(位图)、HyperLogLog(超级日志)和Geospatial(地理空间)。Redis内置了复制、Lua脚本、LRU驱动事件、事务和不同级别的磁盘持久化,并通过Redis哨兵(Sentinel)模式和集群模式(Cluster)提供高可用性(High Availability)。

Redis的原理

Redis不但支持丰富的数据类型,还支持分布式事务、数据分片、数据持久化等功能,是分布式系统中不可或缺的内存数据库服务。

Redis的数据类型

(1)String:String是Redis基本的数据类型,一个key对应一个value。String类型的值最大能存储512MB数据。Redis的String数据类型支持丰富的操作命令,常用的String操作命令。

Redis的原理及应用

(2)Hash:Redis Hash是一个键值(key->value)对集合。Redis的Hash列表支持的操作。

Redis的原理及应用

(3)List:Redis List是简单的字符串列表,按照插入顺序排序。我们可以添加一个元素到列表的头部(左边)或者尾部(右边)。列表最多可存储231-1(4294967295≈4亿多)个元素。

Redis的原理及应用

(4)Set:Set是String类型的无序集合。集合是通过散列表实现的,所以添加、删除、查找的复杂度都是O(1)。

Redis的原理及应用

(5)ZSet:Redis ZSet和Set一样也是String类型元素的集合,且不允许有重复的成员,不同的是,每个元素都会关联一个double类型的分数。Redis正是通过分数来为集合中的成员进行从小到大的排序的。

Redis的原理及应用

(6)Bitmap:通过操作二进制位记录数据。

Redis的原理及应用

(7)HyperLogLog:被用于估计一个Set中元素数量的概率性的数据结构。

Redis的原理及应用

(8)Geospatial:用于地理空间关系计算。

Redis的原理及应用

Redis管道

Redis是基于请求/响应协议的TCP服务。在客户端向服务器发送一个查询请求后,需要监听Socket的返回,该监听过程一直阻塞,直到服务器有结果返回。由于Redis集群是部署在多个服务器上的,所以Redis的请求/响应模型在每次请求时都要跨网络在不同的服务器之间传输数据,这样每次查询都存在一定的网络延迟(服务器之间的网络延迟一般在20ms左右)。由于服务器一般采用多线程处理业务,并且内存操作效率很高,所以如果一次请求延迟20ms,则多次请求的网络延迟会不断累加。也就是说,在分布式环境下,Redis的性能瓶颈主要体现在网络延迟上。

Redis的原理及应用

Redis的管道技术指在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。管道技术能减少客户端和服务器交互的次数,将客户端的请求批量发送给服务器,服务器针对批量数据分别查询并统一回复,能显著提高Redis的性能。

Redis的原理及应用

Redis管道技术基于Spring Boot的使用如下:

Redis的原理及应用

以上代码使用redisTemplate.executePipelined()在Spring Boot中实现了基于Redis的管道操作。具体的步骤为:新建RedisCallback对象并覆写doInRedis();在doInRedis()中通过connection.openPipeline()开启Pipeline操作;在for循环中批量进行Redis数据写操作;最终将批量操作结果返回。

Redis的事务

Redis支持分布式环境下的事务操作,其事务可以一次执行多个命令,事务中的所有命令都会序列化地顺序执行。事务在执行过程中,不会被其他客户端发送来的命令请求打断。服务器在执行完事务中的所有命令之后,才会继续处理其他客户端的其他命令。Redis的事务操作分为开启事务、命令入队列、执行事务三个阶段。Redis的事务执行流程如下。

Redis的原理及应用

(1)事务开启:客户端执行Multi命令开启事务。

(2)提交请求:客户端提交命令到事务。

(3)任务入队列:Redis将客户端请求放入事务队列中等待执行。

(4)入队状态反馈:服务器返回QURUD,表示命令已被放入事务队列。

(5)执行命令:客户端通过Exec执行事务。

(6)事务执行错误:在Redis事务中如果某条命令执行错误,则其他命令会继续执行,不会回滚。可以通过Watch监控事务执行的状态并处理命令执行错误的异常情况。

(7)执行结果反馈:服务器向客户端返回事务执行的结果。

Redis事务的相关命令有Multi、Exec、Discard、Watch和Unwatch。

Redis的原理及应用

Redis事务基于Spring Boot的使用如下:

Redis的原理及应用

以上代码定义了名为transactionSet()的Redis事务操作方法,该方法接收事务命令commandList并以事务命令列表在一个事务中执行。具体步骤为:开启事务权限、开启事务、执行事务命令、提供事务和回滚事务。

Redis发布、订阅

Redis发布、订阅是一种消息通信模式:发送者(Pub)向频道(Channel)发送消息,订阅者(Sub)接收频道上的消息。Redis客户端可以订阅任意数量的频道,发送者也可以向任意频道发送数据。图8-7展示了1个发送者(pub1)、1个频道(channe0)和3个订阅者(sub1、sub2、sub3)的关系。由于3个订阅者sub1、sub2、sub3都订阅了频道channel0,在发送者pub1向频道channel0发送一条消息后,这条消息就会被发送给订阅它的三个客户端。

Redis的原理及应用

Redis常用的消息订阅与发布命令如表

Redis的原理及应用

Redis集群数据复制的原理

Redis提供了复制功能,可以实现在主数据库(Master)中的数据更新后,自动将更新的数据同步到从数据库(Slave)。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。

Redis的原理及应用

(1)一个从数据库在启动后,会向主数据库发送SYNC命令。

(2)主数据库在接收到SYNC命令后会开始在后台保存快照(即RDB持久化的过程),并将保存快照期间接收到的命令缓存起来。在该持久化过程中会生成一个.rdb快照文件。

(3)在主数据库快照执行完成后,Redis会将快照文件和所有缓存的命令以.rdb快照文件的形式发送给从数据库。

(4)从数据库收到主数据库的.rdb快照文件后,载入该快照文件到本地。

(5)从数据库执行载入后的.rdb快照文件,将数据写入内存中。以上过程被称为复制初始化。

(6)在复制初始化结束后,主数据库在每次收到写命令时都会将命令同步给从数据库,从而保证主从数据库的数据一致。

在Redis中开启复制功能时需要在从数据库配置文件中加入如下配置,对主数据库无须进行任何配置:

Redis的原理及应用

在上述配置中,slaveof后面的配置分别为主数据库的IP地址和端口,在主数据库开启了密码认证后需要将masterauth设置为主数据库的密码,在配置完成后重启Redis,主数据库上的数据就会同步到从数据库上。

Redis的持久化

Redis支持RDB和AOF两种持久化方式。

(1)RDB(Redis DataBase):RDB在指定的时间间隔内对数据进行快照存储。RDB的特点在于:文件格式紧凑,方便进行数据传输和数据恢复;在保存.rdb快照文件时父进程会fork出一个子进程,由子进程完成具体的持久化工作,所以可以最大化Redis的性能;同时,与AOF相比,在恢复大的数据集时会更快一些。

(2)AOF(Append Of Flie):AOF记录对服务器的每次写操作,在Redis重启时会重放这些命令来恢复原数据。AOF命令以Redis协议追加和保存每次写操作到文件末尾,Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。AOF的特点有:可以使用不同的fsync策略(无fsync、每秒fsync、每次写的时候fsync),只有某些操作追加命令到文件中,操作效率高;同时,AOF文件是日志的格式,更容易被操作。

Redis的集群模式及工作原理

Redis有三种集群模式:主从模式、哨兵模式和集群模式。

(1)主从模式:所有的写请求都被发送到主数据库上,再由主数据库将数据同步到从数据库上。主数据库主要用于执行写操作和数据同步,从数据库主要用于执行读操作缓解系统的读压力。

Redis的原理及应用

(2)哨兵模式:在主从模式上添加了一个哨兵的角色来监控集群的运行状态。哨兵通过发送命令让Redis服务器返回其运行状态。哨兵是一个独立运行的进程,在监测到Master宕机时会自动将Slave切换成Master,然后通过发布与订阅模式通知其他从服务器修改配置文件,完成主备热切。

Redis的原理及应用

(3)集群模式:Redis集群实现了在多个Redis节点之间进行数据分片和数据复制。基于Redis集群的数据自动分片能力,我们能够方便地对Redis集群进行横向扩展,以提高Redis集群的吞吐量。基于Redis集群的数据复制能力,在集群中的一部分节点失效或者无法进行通信时,Redis仍然可以基于副本数据对外提供服务,这提高了集群的可用性。

Redis的原理及应用

Redis集群遵循如下原则。

◎ 所有Redis节点彼此都通过PING-PONG机制互联,内部使用二进制协议优化传输速度和带宽。

◎ 在集群中超过半数的节点检测到某个节点Fail后将该节点设置为Fail状态。

◎ 客户端与Redis节点直连,客户端连接集群中任何一个可用节点即可对集群进行操作。

◎ Redis-Cluster把所有的物理节点都映射到0~16383的slot(槽)上,Cluster负责维护每个节点上数据槽的分配。Redis的具体数据分配策略为:在Redis集群中内置了16384个散列槽;在需要在Redis集群中放置一个Key-Value时,Redis会先对Key使用CRC16算法算出一个结果,然后把结果对16384求余数,这样每个Key都会对应一个编号为0~16383的散列槽;Redis会根据节点的数量大致均等地将散列槽映射到不同的节点。

Redis的应用

1.安装RedisRedis的安装分Redis单机版安装、Redis主从模式安装、Redis哨兵模式安装和Redis集群模式安装。下面介绍Redis集群模式的安装,该模式也是最复杂的一种模式。其他Redis模式的安装请读者参考官网教程。

(1)下载Redis软件。执行以下命令从官网下载稳定版本的Redis并解压:

Redis的原理及应用

(2)编译和安装。执行以下命令进入Redis的安装目录编译和安装Redis:

Redis的原理及应用

(3)创建Redis节点。执行以下命令在Redis根目录下创建节点目录:

Redis的原理及应用

以上命令分别建立了7000、7001、7002、7003、7004、7005共6个目录,用于存放6个节点的配置文件信息。将redis.conf文件分别复制到7000、7001、7002、7003、7004、7005目录下,并修改端口号和cluster-config-file。

(4)配置Redis集群。分别修改7000、7001、7002、7003、7004、7005目录下的redis.conf配置文件:

Redis的原理及应用

在以上配置中,port用于指定Redis服务端口,cluster-enabled用于设置Redis为集群模式,cluster-config-file用于设置集群配置文件。

(5)启动节点。执行以下命令分别启动6个节点

Redis的原理及应用

(6)创建集群。执行以下命令创建集群:

Redis的原理及应用

在以上命令中,cluster表示该命令是集群相关的命令;create表示创建一个集群,create后面的参数为参与集群创建的节点;cluster-replicas表示集群中的副本数。在创建集群的过程中命令行会列出集群的配置让我们确认,确认时输入yes即可。这样便在一个服务器上安装了一个Reds集群,在该集群中共有6个节点,节点的IP地址为127.0.0.1,节点的端口号分别为7000、7001、7002、7003、7004和7005。

2.应用Redis SpringBoot

在Spring Boot中使用Redis的步骤为:引入jar包、配置application.properties,以及配置和使用RedisTemplate,如下所述。

(1)引入jar包。按照如下代码在Spring Boot项目中加入Redis的jar包依赖:

Redis的原理及应用

(2)配置application.properties:在resource目录的application.properties加入以下Redis配置:

Redis的原理及应用

在以上配置中,spring.redis.cluster.nodes为Redis集群节点的服务地址,在多个服务地址之间使用逗号隔开;spring.redis.password为Redis服务密码,如果没有密码,则将其设置为空即可。需要注意的是,以上是集群模式下的Redis配置,如果Redis是主从模式,则将spring.redis.cluster.nodes地址修改为主从节点的服务地址即可;如果是哨兵模式,则注释掉spring.redis.cluster.nodes配置,在spring.redis.sentinel.master和spring.redis.sentinel.nodes中分别配置哨兵的名称和哨兵的节点即可;如果是单机模式,则注释掉spring.redis.sentinel.nodes的配置,通过spring.redis.host配置Redis服务的地址,并通过spring.redis.port配置Redis服务的端口即可。

(3)配置RedisTemplate。Spring Boot默认配置了RedisTemplate,在应用时注入、使用即可,也可以创建自定义的RedisTemplate。具体代码如下:

Redis的原理及应用

以上代码定义了RedisConfig类,并通过@Configuration开启配置文件注解,通过@AutoConfigureAfter配置自动注解类。在RedisConfig类中定义了RedisTemplate用于对Redis数据库进行操作。

(4)使用RedisTemplate。新建测试类,并在测试类中加入以下测试代码:

Redis的原理及应用

RedisTemplate基于Jedis对Redis数据库的操作进行了二次封装,使得操作Redis数据库更加方便。以上代码在测试类中依赖注入了RedisTemplate,并通过redisTemplate. opsForValue()实现了对Redis数据的插入、查询和删除操作。

分布式缓存设计的核心问题

分布式缓存设计的核心问题是以哪种方式进行缓存预热和缓存更新,以及如何优雅解决缓存雪崩、缓存穿透、缓存降级等问题。这些问题在不同的应用场景下有不同的解决方案,下面介绍常用的解决方案。

缓存预热

缓存预热指在用户请求数据前先将数据加载到缓存系统中,用户查询事先被预热的缓存数据,以提高系统查询效率。缓存预热一般有系统启动加载、定时加载等方式。

缓存更新

缓存更新指在数据发生变化后及时将变化后的数据更新到缓存中。常见的缓存更新策略有以下4种。

◎ 定时更新:定时将底层数据库内的数据更新到缓存中,该方法比较简单,适合需要缓存的数据量不是很大的应用场景。

◎ 过期更新:定时将缓存中过期的数据更新为最新数据并更新缓存的过期时间。

◎ 写请求更新:在用户有写请求时先写数据库同时更新缓存,这适用于用户对缓存数据和数据库的数据有实时强一致性要求的情况。

◎ 读请求更新:在用户有读请求时,先判断该请求数据的缓存是否存在或过期,如果不存在或已过期,则进行底层数据库查询并将查询结果更新到缓存中,同时将查询结果返回给用户。

缓存淘汰策略

在缓存数据过多时需要使用某种淘汰算法决定淘汰哪些数据。常用的淘汰算法有以下几种。◎ FIFO(First In First Out,先进先出):判断被存储的时间,离目前最远的数据优先被淘汰。

◎ LRU(Least Recently Used,最近最少使用):判断缓存最近被使用的时间,距离当前时间最远的数据优先被淘汰。

◎ LFU(Least Frequently Used,最不经常使用):在一段时间内,被使用次数最少的缓存优先被淘汰。

缓存雪崩

缓存雪崩指在同一时刻由于大量缓存失效,导致大量原本应该访问缓存的请求都去查询数据库,而对数据库的CPU和内存造成巨大压力,严重的话会导致数据库宕机,从而形成一系列连锁反应,使整个系统崩溃。一般有以下3种处理方法。

◎ 请求加锁:对于并发量不是很多的应用,使用请求加锁排队的方案防止过多请求数据库。◎ 失效更新:为每一个缓存数据都增加过期标记来记录缓存数据是否失效,如果缓存标记失效,则更新数据缓存。

◎ 设置不同的失效时间:为不同的数据设置不同的缓存失效时间,防止在同一时刻有大量的数据失效。

缓存穿透

缓存穿透指由于缓存系统故障或者用户频繁查询系统中不存在(在系统中不存在,在自然数据库和缓存中都不存在)的数据,而这时请求穿过缓存不断被发送到数据库,导致数据库过载,进而引发一连串并发问题。

比如用户发起一个userName为zhangsan的请求,而在系统中并没有名为zhangsan的用户,这样就导致每次查询时在缓存中都找不到该数据,然后去数据库中再查询一遍。由于zhangsan用户本身在系统中不存在,自然返回空,导致请求穿过缓存频繁查询数据库,在用户频繁发送该请求时将导致数据库系统负载增大,从而可能引发其他问题。常用的解决缓存穿透问题的方法有布隆过滤器和cache null策略。

◎ 布隆过滤器:指将所有可能存在的数据都映射到一个足够大的Bitmap中,在用户发起请求时首先经过布隆过滤器的拦截,一个一定不存在的数据会被这个布隆过滤器拦截,从而避免对底层存储系统带来查询上的压力。

◎ cache null策略:指如果一个查询返回的结果为null(可能是数据不存在,也可能是系统故障),我们仍然缓存这个null结果,但它的过期时间会很短,通常不超过5分钟;在用户再次请求该数据时直接返回null,而不会继续访问数据库,从而有效保障数据库的安全。其实cache null策略的核心原理是:在缓存中记录一个短暂的(数据过期时间内)数据在系统中是否存在的状态,如果不存在,则直接返回null,不再查询数据库,从而避免缓存穿透到数据库上。

缓存降级

缓存降级指由于访问量剧增导致服务出现问题(如响应时间慢或不响应)时,优先保障核心业务的运行,减少或关闭非核心业务对资源的使用。常见的服务降级策略如下。

◎ 写降级:在写请求增大时,可以只进行Cache的更新,然后将数据异步更新到数据库中,保证最终一致性即可,即将写请求从数据库降级为Cache。

◎ 读降级:在数据库服务负载过高或数据库系统故障时,可以只对Cache进行读取并将结果返回给用户,在数据库服务正常后再去查询数据库,即将读请求从数据库降级为Cache。这种方式适用于对数据实时性要求不高的场景,保障了在系统发生故障的情况下用户依然能够访问到数据,只是访问到的数据相对有延迟。

版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除

本文地址:http://0561fc.cn/204224.html