Redis及其他缓存

1.NOSQL、Redis概述,通用命令,redis五大数据类型,三大特殊数据类型

NOSQL概述:

(NOT ONLY SQL-不仅仅是SQL),泛指非关系型数据库,为解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用问题

常见nosql:redis,hbase。

和关系型数据的对比区别:数据之间没有关联关系,数据存储在内存中,操作数据相对较快。关系型数据库数据之间存在关联关系,数据存储在磁盘中,操作数据非常耗时。

优点:成本低、查询速度快、支持多种数据格式(基本数据类型、集合、对象、图片、文档等格式)、扩展性相对关系型数据库较好。

非关系型数据库优势:复杂查询较方便,事务的支持导致安全性很高。

总结:关系型数据库和非关系型数据库并非对立而是互补的关系,从而弥补对方的劣势。一般将数据存储在关系型数据库中,非关系型数据库中备份关系型数据库的数据(热点数据、高频访问且不常修改的数据)。

主流的nosql:

key-value存储数据库:redis。典型用于内容缓存,处理大量数据的高访问负载

列存储数据库:Hbase。典型用于分布式的文件系统

文档型数据库:Mongdb。典型用于web应用

图形数据库:Neo4J。典型用于社交网络

Redis概述:

C语言开发的高性能键值对数据库,在内存中就是一个Map集合。支持多种键值数据类型。key为字符串,value可是任意类型。

value类型分类:

字符串类型-String:Map<String,String>

散列类型-hash:Map<String,Map<String,String>>

列表类型-list:Map<String,List<String>> 数据可重复

集合类型-set:Map<String,Set<String>> 数据不可重复

有序集合类型-sortedset:Map<String,sortedset<String>> 数据不可重复,支持排序

应用场景:缓存、聊天室好友在线列表、任务队列(秒杀、抢购、12306抢票)、应用排行榜、网站访问统计、数据过期处理、分布式集群架构中session分离

相关指令

数据库操作指令:

启动redis,默认16个库(编号从0至15),select 编号 选择指定库

清空当前库:FLUSHDB

清空全部库:FLUSHALL

客户端显示中文:./redis-cli -p 700 --raw

操作key相关指令:

DEL KEY[KEY...] 删除单个或多个Key,返回删除数量,不存在的key忽略

EXISTS KEY;判断key是否存在,存在返回1,否则返回0

EXPIRE KEY seconds;为key设置生存时间,秒为单位,生存时间为0自动删除。成功返回1

KEYS PATTERN;查找符合pattern的key

MOVE KEY DB;将Key移动到指定db中

PEXPIRE KEY milliseconds;为key设置生存时间,毫秒为单位。成功返回1,否则返回0

PEXPIREAT KEY milliseconds-timestap;为Key设置生存时间,以毫秒为单位设置过期的时间戳

TTL KEY ;以秒为单位,返回指定key的剩余存活时间

PTTL KEY ;以毫秒为单位,返回指定key的剩余存活时间

RANDOMKEY;随机返回一个key

RENAME KEY NEWKEY;将Key命名修改为newkey

TYPE KEY ;返回KEY对应VALUE的类型。none(key不存在),string,list(列表),set(集合),zset(有序集合),hash(哈希表)

5种数据类型

String:基础存储类型,在redis中二进制安全,存入和取出数据相同,最大容纳数据长度512M。

常用命令:

set key value;例如:set company "sunny";key存在则进行覆盖,返回 OK

get key;返回key对应的值

del key;删除 key

哈希类型-hash:适合存储值对象信息,value是一个键值对,key 无序

常用命令

hset key field value 为指定key设置field/value键值对。给同一个field设置,后者会覆盖前者

hmset key1 field/value key2 field/value 为多个key设定field/value

hget key field 返回指定Key中field的值

hmget key field1 field2 field3 返回指定Key中多个field的值

hdel key field [field ... ] 删除1个或多个字段,返回被删除字段的个数

hgetall key 获取Key的所有数据

列表类型-list:有序可重复,类似双端队列的数据结构,可作为redis实现消息队列的数据结构

常用命令:

lpush key values[value1 value2...] 在指定key关联的list头部添加这些元素,如果key不存在,则新建元素。添加成功,返回元素个数

lpop key 返回key关联链表的头部元素

rpop key 从尾部弹出元素

lrange key start end 输出该key的所有数据。示例:lrange key 0 10;输出key对应list的索引0至索引10的数据,即前11个元素

列表类型-set(无序且不可重复)

常用命令:

sadd key values[value1、value2...] 向key对应set中添加数据

smembers key 显示key对应set中所有数据

srem key members[member1、member2...] 删除key对应set中指定数据

有序列表类型-zset(sortedSet,可排序,可保证不重复),value中的每个元素都会关联一个double类型的份数,redis中正式通过分数来为元素实现从小到大的排序

特点:可排序的set集合,相当于java中的treeSet

常用命令:

zadd key values[value1、value2...] 向key对应set添加元素

zrange key start end 通过索引区间返回指定范围内的元素,升序

zrevrange key start end 通过索引区间返回指定范围内的元素,降序

zrange key start end [withscores] 通过索引区间返回指定范围内的元素及其对应score数字,升序

zrevrange key start end [withscores] 通过索引区间返回指定范围内的元素及其对应score数字,降序

redis通用命令

key pattern ;pattern表示格式,作用是获取与pattern匹配的Key。* 表示任意1个或多个字符,?表示任意1个字符

exists key ;判断key是否存在,存在返回1 否则返回0

type key ;返回key对应的value数据类型。none、string、list、set、zset、hash

expire key time;设置key的存活时间

3种特殊数据类型

Hyperloglog 基数统计算法,类似于set数据类型,允许容错,使用此类型。不允许容错使用set即可

Bitmap 位存储,操作二进制位来记录。

Geospatial 地理位置

2.redis持久化机制、RDB持久化、AOF持久化

REDIS持久化概述:

redis高性能原因是因为将数据保存在内存中,为了保证redis重启后数据不丢失,将数据从内存保存到硬盘中,过程称为持久化。

持久化支持RDB和AOF两种方式,可以单独使用1种,也可以将2种进行结合使用。

默认支持RDB持久化,无序配置。此机制是在固定时间间隔将内存的数据集快照写入磁盘。

AOF持久化以日志的形式记录服务器所处理的写操作,在redis启动之初会读取此文件来重建redis数据库。以保证重启后数据完整。

持久化可通过配置来禁用

可同时使用RDB和AOF持久化

RDB持久化,也称快照(Snapshot)

RDB持久化特点:将内存种数据以一定时间间隔,将内存数据写入硬盘中,默认持久化的方式,保存的文件以.rdb为后缀

快照生成方式:客户端方式(BGSAVE和SAVE指令)、服务器配置自动触发

客户端方式之BGSAVE操作(并行操作):客户端使用BGSAVE命令创建快照,当redis服务器收到客户端发送的BGSAE命令,服务器会调用fork创建1个子线程,

子线程负责快照写入磁盘,主线程继续处理命令请求

客户端方式之SAVE操作(串行操作):客户端使用SAVE命令创建快照,redis服务器收到客户端发送的SAVE命令,服务器在快照完毕之前不会响应其他命令。此模式不常用

配置自动触发:和Mysql的redo机制类似。如果在redis.conf种设置了save配置选项,redis会在选项满足之后自动触发一次BGSAVE命令,如果设置多个save配置选项,

其中一个满足,也会执行一次BGSAVE命令

服务器接受客户端shutdown指令:服务器收到客户端的shutdown指令后,会执行一个save命令,阻塞所有客户端,不再执行任何客户端命令,并再save命令执行完毕后关闭服务器

配置生成快照名称和位置:

修改生成快照名称:dbfilename dump.rdb

修改生成位置 dir./

RDB(快照)持久化的缺点:

无法保证系统高可用性质,即无法避免最大程度的数据丢失。因为一旦在持久化之前出现服务宕机,未来得及保存进入磁盘的数据就会丢失

AOF只追加日志文件

特点:可将客户端执行的所有set命令记录到日志文件中,AOF持久化会将被执行的写命令保存到AOF文件的末尾,以此来记录数据变化;

恢复内存数据,只需要将AOF文件中包含的写命令从头到尾执行一次即可;

redis服务器启动之初会读取该文件,来重新构建redis数据库,从而保证数据完整

开启AOF持久化:

redis.conf默认配置中的AOF持久化机制是关闭的,需要配置中开启。

开启步骤:修改 appendonly yes 开启持久化;修改appendfilename "appendonly.aof"; 指定生成文件名称

日志追加频率:

always:每次写操作,都写入磁盘,可最大程度减少数据的丢失,但是此同步策略需要对磁盘大量操作,因此redis处理速度会受到磁盘性能的限制。谨慎使用

everysec:每秒执行一次同步,显式的将多个命令存入磁盘。使用此方式和不使用此方式时性能相差无几,同时每秒一次即便系统崩溃也只会丢失1S的数据。 推荐使用

no:由操作系统决定何时同步。不会对性能带来影响,但是会丢失不定量数据。不推荐

修改同步频率:通过 appendfsync always/everysec/no 指定

AOF文件的重写

AOF(日志文件)的缺点:持久化文件越来越大,为了压缩AOF持久化文件,redis提供了AOF重写(ReWriter)机制

AOF重写可在一定程度上减小AOF文件的体积

触发重写方式

客户端方式触发重写:执行 BGREWRITEAOF 命令,不会阻塞redis服务

服务端方式配置自动重写:修改redis.conf文件中的 auto-aof-rewrite-percentage和auto-aof-rewrite-min-size。

例如:auto-aof-rewrite-percentage值为100和auto-aof-rewrite-min-size 64mb。在开启AOF持久化时,当AOF文件大于64M,并且AOF文件比上次重写后体积大了至少几倍,自动触发

重写原理:将内存中的数据库用命令的方式重写生成了一个AOF文件,来替换原来的文件

重写流程:

持久化总结

RDB和AOF两种方案可同时使用,也可单独使用,也可都不使用。使用那种取决于用户的数据和应用决定

无论是使用RDB还是AOF,持久化文件都是保存在磁盘的,有必要除了持久化外,还应该对持久化文件进行备份(最好备份在多个地方)

RDB和AOF的选择问题:

对数据非常敏感,选择AOF。但是文件体积较大,恢复速度较慢

数据呈现阶段有效性,选择rdb,可做到阶段内数据无丢失,恢复速度较快。但是利用RDB实现紧凑的持久化会使得redis性能降低很多

总之如果不能承受数分钟以内的数据丢失,对业务数据非常敏感选择AOF;可以承受数分钟以内的数据丢失,且追求大数据集的恢复速度,选择RDB。

灾难恢复选用RDB

双重保险策略,同时开启AOF和RDB,重启后先使用AOF进行数据恢复,降低丢失数据,两者同时开启,数据恢复时会选择忽略RDB,选择AOF进行恢复,从而避免数据不一致或重复问题

3.java操作redis、jedis连接池、使用redis缓存不常修改的数据

jedis基本使用:

redis不仅可通过命令操作,主流语言都有客户端支持。官方推荐java客户端使用jedis和redisson。企业中jedis使用居多

实现步骤:引入jedis依赖;创建jedis对象;调用jedis对方的方法实现对string、list、set、zset、hash的操作

jedis连接池的基本概念:jedis资源的创建和消费非常消耗性能,jedis提供了池化技术,jedispool在创建时初始化一些连接资源存储到池中,使用jiedis连接资源时间无需创建,从连接池中获取,使用完毕后将jedis还给连接池,供其他请求使用。使用GenericObjectPoolConfig 和JedisPool来创建连接池

4.spring boot整合redis核心api

springboot data redis 提供了stringredistemplate和redistemplate,stringredistemplate是redistemplate的子类。

区别在于stringredistemplate的key和value只能是string,而redistemplate的key和value可以是object任意类型的数据。

使用redistemplate默认是将对象序列化到redis中,因此放入的对象必须实现对象序列化接口 serializable

实现步骤:引入依赖;配置连接;使用redistemplate进行操作

5.redis事务、watch锁、redis实现分布式锁、数据的删除策略、淘汰策略

redis事务

定义:一系列预定义命令保证成一个整体(队列),执行时一次性按照添加顺序依次执行,中途不会中断或干扰。

本质:一组命令的集合

没有隔离级别的概念,所有命令在事务中并未直接执行,只有在执行exec命令时才会执行

redis单条命令保证原子性,事务不保证原子性

执行步骤:开启事务(multi),执行操作,提交事务(exec)

事务操作

开启事务 multi (设定事务开启位置,后续所有指令均加入到事务中)

取消事务 discard 终止当前事务的定义,在multi之后,exec之前

执行事务 exec 设定事务的结束位置,同时执行事务,与multi成对出现。可保证事务的一致性

注意事项:定义事务中,命令存在语法错误,则事务中所有命令都不会执行;

如果命令格式语法正确,但是无法正确执行,则正确的命令会执行,运行错误的命令不会执行(例如对list执行incr),已经执行完毕的命令对应数据不会自动回滚,需要自行回滚。

watch锁:

问题:线程1监听某个key,当事务还未执行完,事务2操作了这个key,watch会通知线程1事务失败

基于特定条件的事务执行:假如对已售空的商城进行补货,多个采购员都可以进行,为了避免数据重复操作,所以在操作某一数据前,先锁定要操作的数据,一旦发生变化,终止当前事务

基于特定条件的事务执行(锁):对key添加监视锁,在执行exec操作前,如果Key发生了变化,则终止事务执行。watch key1[kye2...].取消所有key的监视 unwatch;

watch锁操作:

悲观锁:认为什么时候都会出问题,无论做什么都会加锁

乐观锁:认为什么时候都不会出现问题,所以不会加锁,更新数据时候判断一下,在此期间是否有人更改此数据(获取version,更新的时候比较version)

redis中数据的删除策略

定时删除、惰性删除、定期删除

淘汰策略

6.mybatis自身本地缓存结合redis实现分布式缓存

redis实现分布式缓存

缓存:计算机内存中的一段数据

内存中数据特点:读写快、断电立即丢失

缓存解决的问题:提高网站吞吐量,网络运行效率快,解决数据库访问压力

数据库中极少修改的数据适合使用缓存,更多用于数据查询

本地缓存和分布式缓存的区别:本地缓存保存在应用服务器内存中(mybatis的一级和二级缓存就是本地缓存);分布式缓存存储在应用服务器之外的数据

集群:将一种服务创建多个节点,放在一起共同对系统提供服务的过程称为集群

分布式:多个不同服务集群共同对系统提供服务的系统称为分布式系统。

利用mybatis自身本地缓存结合redis缓存实现分布式缓存:todo

7.主从复制简介、工作流程、常见问题

主从复制简介

redis集群实现高可用:避免单机redis服务故障,准备多台服务器,互相连通,将数据复制多个副本保存在多个服务器上,连接在一起,并保证数据式同步的。

即便其中1台服务宕机,其他服务器依然可以继续提供服务,实现redis的高可用,同时实现数据冗余备份。

主从复制定义:即将master中的数据及时、有效的复制到slave中.master支持读写,在进行写时间,将出现变化的数据自动同步至slave。

主从复制作用:

读写分离:master负责写,slave负责读取,提高服务器的读写负载能力

负载均衡:基于主从结构,配合读写分离,由slave分担master负载,并根据需求变化,改变slave数量,通过多个从节点分担数据读取负载,大大提高了redis服务器并发量和吞吐量

故障恢复:master出现问题,slave提供服务,实现快速的故障恢复

数据冗余:实时数据热备份,持久化之外的一种数据冗余方式,slava和master数据同步

高可用基石:基于主从机制,构建哨兵模式和集群,实现redis高可用方案

主从复制流程

建立连接:准备阶段,slave连接master。

连接的三种方式:

客户端发送命令:slaveof masterip masterport;

驱动服务器参数:redis-server -slaveof masterip masterport

服务器配置:slaveof masterip masterport

断开连接:slaveof no one;断开连接后之前接受数据不会删除,只是不在接收新的master数据

数据同步: master数据同步slave

命令传播:master后续执行写入操作,将数据同步slave

8.哨兵机制Sentinel、哨兵原理

哨兵机制sentinel

哨兵概念:是redis的高可用性解决方案,由1个或多个sentinel实例构成的sentinel系统可监视多个主服务器,以及这些主服务器下的所有子服务器。

当被监视的主服务器下线时,自动将下线主服务器中的某个从服务器升级为新的主服务器。简单来说哨兵就是带有自动故障转移功能的主从架构。

哨兵是一个分布式系统,用于对主从结构中的每台服务器进行监控,当master出现故障时,选择新的master,并将所有slave连接到新的master

哨兵作用

监控:不断检查master和slave是否正常运行,master存活检测,master和slave运行情况检测

通知:当被监控的服务器出现问题时,向其他(哨兵、客户端)发送通知

自动故障转移:如果master宕机,断开master和slave的连接,从slave中选取一个作为新的master,将其他slave和新的master建立连接,并告知客户端新的master地址

注意:哨兵也是一台服务器,只是不提供服务。通常哨兵配置数量为单数。(避免选举master同票)

启动哨兵机制

配置多个哨兵:将redis中的sentinel.conf拷贝2份,在sentinel.conf中修改端口,以及设置master的端口地址,最后通过 redis-sentinel sentinel-端口号.conf即可启动哨兵

哨兵机制原理

主从切换:哨兵在主从切换中经历了 监控、通知、故障转移 3个阶段。

监控阶段:启动哨兵服务之后,哨兵之间会互相监控,包括master及master下所有的slave节点信息。多个哨兵之间可相互通信,之间通过发布订阅来互相通知

通知阶段:哨兵之间相互通知,哨兵通知客户端

故障转移阶段:某个哨兵向master服务器发送指令,此时master没反应,也拿不到信息,哨兵意识到master宕机,将此消息告知另外2个哨兵,另外两哨兵也向master发送请求,也得不到响应,此时master确定下线,随后多个哨兵中会选出一个领头的哨兵将master清楚,并在slave中选出一个新的master,将slave切换为新的master

9.redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案

集群架构

集群架构概念

概念产生背景:业务发展过程中遇到的瓶颈。redis提供服务OPS可达到10万/S,当前业务ops已达到10万/s;内存单机容量为256G,当前业务需求内存容量为1T。使用集群可解决上述问题

集群:将同一个服务的多个节点放在一起,共同对系统提供服务的过程称为集群。换言之集群就是将若干台网络连接起来,并提供统一的管理方式,对外呈现单机的服务效果。

分布式:有多个不同服务集群共同对系统提供服务的系统称为分布式系统

集群架构作用:

分散单台服务器的访问压力,实现负载均衡

分散单台服务器的存储压力,实现可扩展性

降低单台服务宕机带来的宕机灾难

redis集群原理

所有redis节点彼此互联,通过二进制协议优化传输速度和带宽,每个redis节点都包含自己的master和slave,

集群中节点宕机是集群中超过半数的节点检测失效时才失效

客户端只需要连接集群中任意一个节点即可

客户端执行set命令时,会通过CRC16算法,计算出其哈希槽的位置,根据该位置存储到对应的node节点。执行get操作时,会根据哈希槽的位置,去指定节点内读取数据。

故障转移将宕机的master节点的哈希槽由选出来的slave来接管,不会新创建哈希槽

redis集群搭建

https://blog.csdn.net/m0_37989980/article/details/107778257

redis企业解决方案

缓存预热

定义:系统启动前,提前将相关的缓存数据直接加载到缓存系统,避免用户先查询数据库,再将数据缓存的问题!

解决问题:解决用户请求先查询数据库,再将数据缓存的问题

作用:用户直接查询事先被预热的缓存数据,加快查询速度

解决方案:

统计访问频率较高的热点数据,并将统计数据分类,根据级别排序,优先加载级别较高的热点数据,热点数据主从预热

脚本程序固定触发脚本预热

缓存雪崩

定义:同一时间大面积的缓存失效,后面的请求都会直接请求数据库,造成数据库短时间内接收大量请求而崩溃

后果:数据库服务器崩溃

原因:较短时间内,缓存中较多的key集中过期

解决方案(道):

更多的页面静态化处理(模板+动态数据)、构建多级缓存架构、针对慢SQL进行执行计划分析,进而优化SQL、

限流降级短时间内牺牲用户体验,限制一部分请求,降低应用服务器压力,请求低速运转后再逐步放开访问

解决方案(术):

数据有效期策略调整,根据业务有效期进行分类错峰,过期时间使用固定时间+随机值的方式,稀释集中过期的key

超热数据使用永久key

缓存击穿

定义:缓存中没有但数据库中有的数据,一般是缓存时间到期,此时大量并发请求同一条数据,缓存中没有,查询数据库,从而造成数据库崩溃

原因:缓存中某一个热点key过期,该Key访问量巨大,多个请求都压在这个Keys上,但是均为命中,redis短时间内发起了大量对数据库中同一数据的访问

解决方案(术):

设置热点数据永不过期、现场调整Key的过期时间、后台定时刷新热点key有效期

缓存穿透(布隆过滤器解决)

定义:缓存和数据库中都没有的数据,导致所有请求都落在数据库上,造成数据库短时间接到大量请求而崩掉

示例:例如数据库及缓存中的数据都是从id为0开始自增,有人恶意请求id=-1的数据,即缓存穿透

解决方案:

接口层增加校验,如用户鉴权校验,id基础校验,小于等于0的直接拦截

缓存和数据库中都没取到,可以设置为key-null,有效期短一点,30秒左右,可防止用户针对同一个key进行暴力攻击

使用布隆过滤器,判断请求的key是否存在

布隆过滤器:

定义:是一个很长的二进制向量(bit数组)和一系列哈希函数(hash),用于检索一个元素是否在一个集合中。

优点:因为基于位数组和哈希算法,空间效率和查询时间远超一般算法

缺点:有一定的误识别率和删除困难,但是可以通过增加位数组大小和hash函数来降低误识别率(无法避免)

添加数据过程:初始化之后,位数组中值都为0,当增加变量,会通过多个hash函数将元素映射到位数组中各个位上,将对应位置设置为1

查询数据过程:通过多个hash函数将元素映射到位数组中各个位上,如果各个位都是1,则元素可能存在,但如果其中有位不为1,则元素一定不存在

缓存降级

定义:流量骤增,造成响应速度较慢,可对非核心缓存业务进行降级

目的:保证核心服务可用。有些服务无法降级(如加入购物车、结算)

服务降级目的:防止redis故障,导致数据库一起发生雪崩问题,因此可对不重要的缓存数据,采用服务降级策略。

例如redis出现问题,不去数据库查询数据,而是直接返回默认值(兜底默认值)

10.布隆过滤器解决缓存穿透问题

人工智能学习网站:https://www.captainai.net/itcoke/

目的:redis实现布隆过滤器

使用场景:准确判断某个数据是否在大数据集合中,并且不占用内存

简介:一种数据结构,一串很长的二进制向量组成,可看作一个二进制数组,初始默认值都是0

添加数据:通过多个hash函数,计算出在二进制数组中的位置,将其设置为1

判断数据是否存在:将元素通过hash函数算出在二进制数组中的位置,看其是否为1,如果都为1则可能存在,否则一定不存在

优点:二进制数据,占用内存极少,插入和查询速度很快

缺点:随着数据增加,误判率增加;无法判断数据一定存在;无法删除数据

redis实现布隆过滤器:

在redis中,bitmaps提供了一套命令来操作类似字符串中的每一位(setbit、getbit、bitcount等),因此redis实现布隆过滤器底层是通过bitmap数据结构。

Redission是在java中操作redis的库,因此可利用Redission来实现布隆过滤器,也可用guava来实现布隆过滤器

相关推荐
大厂小码哥1 小时前
图解Redis 01 | 初识Redis
数据库·redis·缓存
我的程序快快跑啊18 小时前
redis:全局ID生成器实现
数据库·redis·缓存
84869811918 小时前
Spring为什么要用三级缓存解决循环依赖?
java·spring·缓存
littleschemer21 小时前
Go缓存系统
缓存·go·cache·bigcache
Amd79421 小时前
Nuxt Kit 中的页面和路由管理
缓存·中间件·路由·nuxt·管理·重定向·动态
理想青年宁兴星1 天前
【MySQL】了解并操作MySQL的缓存配置与信息
数据库·缓存
三木几1 天前
redis中的5中数据结构
数据库·redis·缓存
啊·贤1 天前
Redis详细解析
java·数据库·spring boot·redis·缓存
day3ZY1 天前
磁盘写入缓存区太大,如何清理C盘缓存
c语言·开发语言·缓存
少林码僧2 天前
详细介绍 Redis 列表的应用场景
数据库·redis·缓存