redis高级

事务机制

简述

redis事务是基于队列实现的,创建一个事务队列,然后将事务操作都放入队列中,最后依次执行
在这里插入图片描述

作用

保证数据可以恢复操作,确保数据的完整性

列子

#我的关注 user:用户id:follow 被关注的用户id
#我的粉丝 user:用户id:fans 粉丝用户id

#开启事务
multi

#添加命令
#小明用户为1001 , 小张用户id为1002
sadd user:1001:follow 1002
sadd user:1002:follow 1001

sadd user:1001:fans 1002
sadd user:1002:fans 1002

#执行事务
exec
# 取消事务
discard

事务的机制

语法错误(编译)

#开启事务
multi

#命令
set name zhangsan
set age
seterror sex male

#执行事务
exec

#获取正确指令数据
get name

在这里插入图片描述
事务队列中的命令在进入队列后,在执行exec命令前,队列中的命令存在语法错误,此时队列中的所有命令都会执行失败

执行错误(运行)

#开启事务
multi

#命令
set lesson java
rpush lesson eureka feign nacos
set lesson redis

#执行事务
exec

#获取数据
get lesson

在这里插入图片描述事务队列中的命令在进入队并执行exec命令后,出现错误,此时队列中其他命令不会受到影响正常执行

springboot实现redis事务操作

1)修改RedisConfig配置类,开启事务控制

//开启redis事务控制
redisTemplate.setEnableTransactionSupport(true);

2)自定义方法,测试事务效果

@Test
@Transactional(rollbackFor = Exception.class)
public void multiTest(){
    //开启事务
    redisTemplate.multi();
    try{
        redisTemplate.opsForValue().set("lesson","java");
        redisTemplate.opsForSet().add("lesson","eureka","feign","gateway");
        redisTemplate.opsForValue().set("lesson","redis");
        System.out.println(redisTemplate.opsForValue().get("lesson"));
    }catch (Exception e){
        //回滚
        System.out.println("出现异常");
        redisTemplate.discard();
    }finally {
        redisTemplate.exec();
    }
}

持久化机制

RDB快照

RDB(Redis DataBase)是Redis默认存储方式。其基于快照思想,当符合一定条件(手动或自动触发)时,Redis会将这一刻的内存数据进行快照并保存在磁盘上,产生一个经过压缩的二进制文件,文件后缀名.rdb

触发条件

自动

在redis.conf文件中配置了一些默认触发机制。
在这里插入图片描述

手动

在redis客户端执行save或bgsave命令,手动触发RDB快照。

#进入客户端
bin/redis-cli

#执行save命令(同步执行)
save

#执行bgsave命令(异步子线程执行)
bgsave

在这里插入图片描述

save或bgsave命令的区别

save:同步处理,阻塞Redis服务进程,服务器不会处理任何命令,直到RDB文件保存完毕。
bgsave:会fork一个和主线程一致的子线程负责操作RDB文件,不会阻塞Redis服务进程,操作RDB文件的同时仍然可以处理命令。
Redis默认使用的是 bgsave 来保存快照数据。

执行过程

在这里插入图片描述1)Redis服务进程判断,当前是否有子线程在执行save或bgsave。

2)如果有,则直接返回,不做任何处理。

3)如果没有,则以阻塞式创建子线程,在创建子线程期间,Redis不处理任何命令。

4)创建完子线程后,取消阻塞,Redis服务继续响应其他命令。

5)同时基于子线程操作RDB文件,将此刻数据保存到磁盘。

AOF

AOF(append only file)是Redis提供了另外一种持久化机制。与RDB记录数据不同,当开启AOF持久化后,Redis会将客户端发送的所有更改数据的命令,记录到磁盘中的AOF文件。 这样的话,当Redis重启后,通过读取AOF文件,按顺序获取到记录的数据修改命令,即可完成数据恢复。
举个例子,对Redis执行三条写命令:

set name itheima

hset cart shop nike

sadd lesson java python hadoop

RDB会将name、cart、lesson三个键值对数据进行保存,而AOF会将set、hset、sadd三个命令保存到AOF文件中。

触发方式

AOF方式需要手动开启,修改redis.conf

# 是否开启AOF,默认为no
appendonly yes

#设置AOF文件名称
appendfilename  appendonly.aof

在这里插入图片描述
对于AOF的触发方式有三种:alwayseverysecno。 默认使用everysec。可以通过redis.conf中appendfsync属性进行配置。

  • always:每次执行写入命令都会将aof_buf缓冲区文件全部内容写入到AOF文件中,并将AOF文件同步到磁盘。该方式效率最低,安全性最高。
  • everysec:每次执行写入命令都会将aof_buf缓冲区文件全部内容写入到AOF文件中。 并且每隔一秒会由子线程将AOF文件同步到磁盘。该方式兼备了效率与安全,即使出现宕机重启,也只会丢失不超过两秒的数据。
  • no:每次执行写入命令都会将aof_buf缓冲区文件全部内容写入到AOF文件中,但并不对AOF文件进行同步磁盘。 同步操作交由操作系统完成(每30秒一次),该方式最快,但最不安全。

执行原理

在这里插入图片描述
开启AOF后,重启Redis,进入Redis客户端并执行多条写命令,这些命令会被保存到appendonly.aof文件中。

set name zhangsan
set age 18
set sex male
get name
get age
get sex

此时查看redis/data目录,会新产生一个appendonly.aof文件。 查看文件内容

*2  #表示该命令有两个词 (select 0 查询0号数据库)
$6	#表示第一个词由6个字符组成
SELECT	#表示第一词为select
$1	#表示第二个词由1个字符组成
0	#表示第二词为0
*3
$3
set
$4
name
$8
zhangsan
*3
$3
set
$3
age
$2
18
*3
$3
set
$3
sex
$4
male

出现的*1 $1这些可以防篡改

重写优化

随着操作redis越多,命令数据占用大量存储空间、数据还原花费的时间多

自动
#当前aof文件大小超过上一次aof文件大小的百分之多少时进行重写。如果之前没有重写过,以
启动时aof文件大小为准
auto-aof-rewrite-percentage 100

#限制允许重写最小aof文件大小,也就是文件大小小于64mb的时候,不需要进行优化
auto-aof-rewrite-min-size 64mb
手动

直接调用bgrewriteaof命令。(命令:redis-cli bgrewriteaof)

高可用

在这里插入图片描述
redis集群,主从分离,当一台服务器中数据更新后,可以自动的将更新的数据同步到其他服务器上

读写分离

在生产环境下,读请求会远远多于写请求,大概10:1的比率。 当单机无法应对大量读请求时,可以通过主从复制机制,实现读写分离。主节点只负责写请求,从节点只负责读请求
在这里插入图片描述

持久化优化

从节点上开启持久化、在主节点关闭持久化

操作流程

在这里插入图片描述1、Slave服务启动,主动连接Master,并发送SYNC命令,请求初始化同步;

2、Master收到SYNC后,执行BGSAVE命令生成RDB文件,并缓存该时间段内的写命令;

3、Master完成RDB文件后,将其发送给所有Slave服务器;

4、Slave服务器接收到RDB文件后,删除内存中旧的缓存数据,并装载RDB文件;

5、Master在发送完RDB后,即刻向所有Slave服务器发送缓存中的写命令;

作用

  • 读写分离:主写从读,提高服务器的读写负载能力
  • 负载均衡:基于主从结构,配合读写分离,由slave分担master负载,并根据需求的变化,改变slave的数量,通过多个从节点分担数据读取负载,大大提高Redis服务器并发量与数据吞吐量
  • 故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复
  • 数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式
  • 高可用基石:基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案

哨兵模式

如果主库挂了,我们就需要运行一个新主库,比如说把一个从库切换为主库,把它当成主库。

这就涉及到三个问题:

  1. 主库真的挂了吗?

  2. 该选择哪个从库作为主库?

  3. 怎么把新主库的相关信息通知给从库和客户端呢?

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

单机版哨兵

在这里插入图片描述
注意:

  • 哨兵也是一台redis服务器,只是不提供数据服务

  • 通常哨兵配置数量为单数

  • 如果配置启用单节点哨兵,如果有哨兵实例在运行时发生了故障,主从库无法正常

    切换啦,所以我们需要搭建 哨兵集群

哨兵集群

在这里插入图片描述

  • Redis提供了哨兵的命令,是一个独立的进程
  • 原理 哨兵通过发送命令给多个节点,等待Redis服务器响应,从而监控运行的多个Redis实例的运行情况
  • 当哨兵监测到master宕机,会自动将slave切换成master,通过通知其他的从服务器,修改配置文件切换主机

注意
哨兵必须要配置大于等于3的奇数,因为哨兵要进行投票判断主服务器是否挂了
如果某个哨兵检测到主服务器挂了,但是其他没有检测到,就说明哨兵出现了误判1
主观下线
哨兵检测到主服务器挂了就会先把它标记为“主观下线”,并进行投票。
客观下线
当哨兵判断主服务器挂的票数多于半数时,主服务器就会变成客观下线(此时才拿掉,客观下线条件只适用于主服务器
仲裁
投票的过程就叫仲裁

高可扩

在这里插入图片描述
先通过crc16算法判断数据是否有问题再通过hash槽进行计算,然后分配数据到Master服务器

key过期淘汰策略

定时删除

在这里插入图片描述
它会在设置键的过期时间的同时,创建一个定时器, 当键到了过期时间,定时器会立即对键进行删除。 这个策略能够保证过期键的尽快删除,快速释放内存空间
优缺点

  • Redis的操作频率是非常高的
  • 会造成出现大量定时器执行,严重降低系统性能
  • 该策略对内存空间足够友好, 但对CPU非常不友好,会拉低系统性能,因此不建议使用

惰性删除

在这里插入图片描述
它不持续关注key的过期时间, 而是在获取key时,才会检查key是否过期,如果过期则删除该key
优缺点

  • 不持续关注key的过期时间, 而是在获取key时,才会检查key是否过期,如果过期则删除该key
  • 惰性删除对CPU足够友好,但是对内存空间非常不友好,会造成大量内存空间的浪费

定期删除

在这里插入图片描述

  • 默认每秒运行10次会对具有过期时间的key进行一次扫描,但是并不会扫描全部的key,因为这样会大大延长扫描时间。
  • 每次默认只会随机扫描20个key,同时删除这20个key中已经过期的key。
  • 如果这20个key中过期key的比例达超过25%,则继续扫描。

可以通过参数配置修改每秒扫描次数只需要修改redis.conf中的hz参数即可。
在这里插入图片描述
缺点
因为是随机扫描,所以可能会出现过期了但一直没有扫描到的情况

内存淘汰策略

作用

Redis会检查内存空间大小,如超过最大内存,则触发内存淘汰策略,redis通过释放内存中的数据,来保证新数据的添加

最大内存参数配置

修改redis.conf中的maxmemory 来设置最大内存。
在这里插入图片描述

淘汰策略

过期时间数据淘汰

  • volatile-lru
    删除设置了ttl2,且最近中最久未被使用过的key
  • volatile-lfu
    删除设置了ttl,且最近中最少使用过的key
  • volatile-ttl
    删除设置了ttl,且即将过期的key
  • volatile-random
    从设置了ttl中的key中随机删除

所有数据淘汰

  • allkeys-lru
    所有key中,删除最近中最久未被使用过的key
  • allkeys-lfu
    所有key中,删除最近中最少使用过的key
  • allkeys-random
    从所有key中,随机删除key

不淘汰

  • noeviction
    不删除,当内存空间不足时,直接报异常

策略设置

redis默认使用noeviction,我们可以通过修改redis.confmaxmemory-policy属性值设置不同的内存淘汰策略。
在这里插入图片描述

使用场景

1、Redis只做缓存,不做DB持久化,使用allkeys。如状态性信息,经常被访问,但数据库不会修改。
2、同时用于缓存和DB持久化,使用volatile。如商品详情页。
3、存在冷热数据区分,则选择LRU或LFU。如热点新闻,热搜话题等。
4、每个key被访问概率基本相同,选择使用random。如企业内部系统,访问量不大,删除谁对数据库也造成太大压力。
5、根据超时时间长久淘汰数据,选择选用ttl。如微信过期好友请求。

redis6.0新特性

支持多线程

  • redis6多线程只是用来处理网络数据的读写和协议解析上,底层数据操作还是单线程
  • 执行命令仍然是单线程,之所以这么设计是不想因为多线程而变得复杂,需要去控制 key、lua、事务,LPUSH/LPOP 等等的并发问题
  • 默认不开启
io-threads-do-reads yes
io-threads 线程数
  • 官方建议 ( 线程数小于机器核数 )
    4 核的机器建议设置为 2 或 3 个线程
    8 核的建议设置为 4或6个线程,
  • 不会有安全问题,Redis 的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行。

acl

给用户创建权限,通过限制对命令和密钥的访问来提高安全性,以使不受信任的客户端无法访问

3.redis的客户端支持缓存

类似浏览器缓存一样

lettuce客户端

在这里插入图片描述
lettuce的依赖
在这里插入图片描述
jedis的依赖
在这里插入图片描述
lettuce的配置
在这里插入图片描述
jedis的配置
在这里插入图片描述
api一样


  1. 误判:主库实际并没有下线,但是哨兵误以为它下线了。误判一般会发生在集群网络压力较大、网络拥塞,或者是主库本身压力较大的情况下 ↩︎

  2. 设置了过期时间的key值 ↩︎

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值