Redis总结

官网

https://www.redis.net.cn/

Redis 数据类型(5种常用)

string
hash
list
set
sorted_set
sorted_set 底层存储还是基于set结构的,因此数据不能重复,如果重复添加相同的数据,score值将被反 复覆盖,保留最后一次修改的结果 。

Redis 持久化

持久化过程保存什么?
1.将当前数据状态进行保存快照形式,存储数据结果,存储格式简单,关注点在数据 。
2.将数据的操作过程进行保存日志形式,存储操作过程,存储格式复杂,关注点在数据的操作过程 。

RDB

启动方式:1.save 2.bgsave 3.save配置
save指令的执行会阻塞当前Redis服务器,直到当前RDB过程完成为止,有可能会造成长时间阻塞。
bgsave过程:
客户端向服务端发送bgsave指令,服务端调用fork函数生成子进程,创建rdb文件,返回消息。
bgsave命令是针对save阻塞问题做的优化。Redis内部所有涉及到RDB操作都采用bgsave的方式,save命令可以放弃使用。
save配置:
在conf文件中进行配置 。
范例:
save 900 1
save 300 10
save 60 10000
save配置要根据实际业务情况进行设置,频度过高或过低都会出现性能问题,结果可能是灾难性的。
save配置中对于second与changes设置通常具有互补对应关系,尽量不要设置成包含性关系。
save配置启动后执行的是bgsave操作。

RDB优点:
RDB是一个紧凑压缩的二进制文件,存储效率较高。
RDB内部存储的是redis在某个时间点的数据快照,非常适合用于数据备份,全量复制等场景。
RDB恢复数据的速度要比AOF快很多。
RDB缺点:
RDB方式无论是执行指令还是利用配置,无法做到实时持久化,具有较大的可能性丢失数据。
bgsave指令每次运行要执行fork操作创建子进程,要牺牲掉一些性能。
Redis的众多版本中未进行RDB文件格式的版本统一,有可能出现各版本服务之间数据格式无法兼容现象。

AOF

AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令 达到恢复数据的目的。与RDB相比可以简单描述为改记录数据为记录数据产生的过程 。
AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式 。

AOF写数据三种策略(appendfsync)

always(每次)
每次写入操作均同步到AOF文件中,数据零误差,性能较低。
everysec(每秒)
每秒将缓冲区中的指令同步到AOF文件中,数据准确性较高,性能较高,建议使用,也是默认配置 在系统突然宕机的情况下丢失1秒内的数据
no(系统控制)
由操作系统控制每次同步到AOF文件的周期,整体过程不可控
AOF功能开启:

#配置
appendonly yes|no 
#配置策略
appendfsync always|everysec|no 

AOF重写

随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis引入了AOF重写机制压缩文件体积。AOF文件重 写是将Redis进程内的数据转化为写命令同步到新AOF文件的过程。简单说就是将对同一个数据的若干个条命令执行结果转化成最终结果数据对应的指令进行记录

Redis事务

DISCARD
EXEC
MULTI
UNWATCH
WATCH
1.事务中的所有命令都被序列化并顺序执行。在Redis事务的执行过程中,永远不会发生另一个客户端发出的请求。这样可以确保将命令作为单个隔离操作执行。
2.所有命令都将被处理,或者不处理任何命令,因此Redis事务也是原子的。
开启事务

#设定事务的开启位置,此指令执行后,后续的所有指令均加入到事务中 
multi 

执行事务

#设定事务的结束位置,同时执行事务。与multi成对出现,成对使用 
exec 

加入事务的命令暂时进入到任务队列中,并没有立即执行,只有执行exec命令才开始执行
如果定义的事务中所包含的命令存在语法错误整体事务中所有命令均不会执行。包括那些语法正确的命令。
在 Redis 中使用 watch 命令可以决定事务是执行还是回滚。一般而言,可以在 multi 命令之前使用 watch 命令监控某些键值对,然后使用 multi 命令开启事务,当 Redis 使用 exec 命令执行事务的时候,它首先会去比对被 watch 命令所监控的键值对,如果没有发生变化,那么它会执行事务队列中的命令,提交事务;如果发生变化,那么它不会执行任何事务中的命令,而去事务回滚。

定义事务的过程中,命令执行出现错误怎么办?
能够正确运行的命令会执行,运行错误的命令不会被执行 。
已经执行完毕的命令对应的数据不会自动回滚,需要程序员自己在代码中实现回滚。
为什么Redis不支持回滚?
1.仅当使用错误的语法(并且在命令排队期间无法检测到该问题)或针对包含错误数据类型的键调用Redis命令时,该命令才能失败:这实际上意味着失败的命令是编程错误的结果,还有一种很可能在开发过程中而不是生产过程中发现的错误。
2.Redis在内部得到了简化和加快,因为它不需要回滚的能力。

删除策略

过期数据

数据删除策略

1.定时删除
2.惰性删除
3.定期删除

定时删除

创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作 。

惰性删除

数据到达过期时间,不做处理。等下次访问该数据时,如果未过期,返回数据,发现已过期,删除,返回不存在 。

定期删除

周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度。

逐出算法

检测易失数据(设置了过期时间的key)
① volatile-lru:挑选最近最少使用的数据淘
② volatile-lfu:挑选最近使用次数最少的数据淘汰
③ volatile-ttl:挑选将要过期的数据淘汰
④ volatile-random:任意选择数据淘汰
== 检测全库数据==
⑤ allkeys-lru:挑选最近最少使用的数据淘汰
⑥ allkeys-lfu:挑选最近使用次数最少的数据淘汰
⑦ allkeys-random:任意选择数据淘汰
== 放弃数据驱逐==
⑧ no-enviction(驱逐):禁止驱逐数据(默认策略),会引发错误OOM(Out Of Memory)

主从复制

主从复制的作用

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

主从复制工作流程

主从复制过程大体可以分为3个阶段
1.建立连接阶段
2.数据同步阶段
3.命令传播阶段

增量复制的三个核心要素
服务器的运行id(run id)
主服务器的复制积压缓冲区
主从服务器的复制偏移量

哨兵模式

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

哨兵的作用

监控
不断的检查master和slave是否正常运行。 master存活检测、master与slave运行情况检测。
通知(提醒)
当被监控的服务器出现问题时,向其他(哨兵间,客户端)发送通知。
自动故障转移
断开master与slave连接,选取一个slave作为master,将其他slave连接到新的master,并告知客户端新的服务器地址。
提供配置:Sentinel充当客户端服务发现的授权来源:客户端连接到Sentinels,以询问负责给定服务的当前Redis主服务器的地址。如果发生故障转移,Sentinels将报告新地址。

可以从 sentinel 日志中出现的几个消息来进行查看故障转移:
1.+switch-master:表示切换主节点(从节点晋升为主节点)
2.+sdown:主观下线
3.+odown:客观下线

集群

Redis集群结构设计

数据存储设计

通过算法设计,计算出key应该保存的位置。
将所有的存储空间计划切割成16384份,每台主机保存一部分 每份代表的是一个存储空间,不是一个key的保存空间。

集群内部通讯设计

各个数据库相互通信,保存各个库中槽的编号数据
一次命中,直接返回
一次未命中,告知具体位置

故障转移

发现故障节点
1.集群内的节点会向其他节点发送PING命令,检查是否在线
2.如果未能在规定时间内做出PONG响应,则会把对应的节点标记为疑似下线
3.集群中一半以上负责处理槽的主节点都将主节点X标记为疑似下线的话,那么这个主节点X就会被认为是已下线
4.向集群广播主节点X已下线,大家收到消息后都会把自己维护的结构体里的主节点X标记为已下线
从节点选举
1.当从节点发现自己复制的主节点已下线了,会向集群里面广播一条消息,要求所有有投票权的节点给自己投票(所有负责处理槽的主节点都有投票权)
2.主节点会向第一个给他发选举消息的从节点回复支持
3.当支持数量超过N/2+1的情况下,该从节点当选新的主节点
故障的迁移
1.新当选的从节点执行 SLAVEOF no one,修改成主节点
2.新的主节点会撤销所有已下线的老的主节点的槽指派,指派给自己
3.新的主节点向集群发送命令,通知其他节点自己已经变成主节点了,负责哪些槽指派
4.新的主节点开始处理自己负责的槽的命令

redis cluster的批处理中ask重定向解决方案

redis cluster的批处理中ask重定向解决方案

键空间通知(keyspace notification)

键空间通知使得客户端可以通过订阅频道或模式, 来接收那些以某种方式改动了 Redis 数据集的事件。

事件通过 Redis 的订阅与发布功能(pub/sub)来进行分发, 因此所有支持订阅与发布功能的客户端都可以在无须做任何修改的情况下, 直接使用键空间通知功能。

因为 Redis 目前的订阅与发布功能采取的是发送即忘(fire and forget)策略, 所以如果你的程序需要可靠事件通知(reliable notification of events), 那么目前的键空间通知可能并不适合: 当订阅事件的客户端断线时, 它会丢失所有在断线期间分发给它的事件。

事件的类型

对于每个修改数据库的操作,键空间通知都会发送两种不同类型的事件。

比如说,对 0 号数据库的键 mykey 执行 DEL key [key …] 命令时, 系统将分发两条消息, 相当于执行以下两个 PUBLISH channel message 命令:

PUBLISH __keyspace@0__:mykey del
PUBLISH __keyevent@0__:del mykey

订阅第一个频道 keyspace@0:mykey 可以接收 0 号数据库中所有修改键 mykey 的事件, 而订阅第二个频道 keyevent@0:del 则可以接收 0 号数据库中所有执行 del 命令的键。

以 keyspace 为前缀的频道被称为键空间通知(key-space notification), 而以 keyevent 为前缀的频道则被称为键事件通知(key-event notification)。

当 del mykey 命令执行时:

键空间频道的订阅者将接收到被执行的事件的名字,在这个例子中,就是 del 。

键事件频道的订阅者将接收到被执行事件的键的名字,在这个例子中,就是 mykey 。

配置

因为开启键空间通知功能需要消耗一些 CPU , 所以在默认配置下, 该功能处于关闭状态。

可以通过修改 redis.conf 文件, 或者直接使用 CONFIG SET 命令来开启或关闭键空间通知功能:

当 notify-keyspace-events 选项的参数为空字符串时,功能关闭。

另一方面,当参数不是空字符串时,功能开启。

notify-keyspace-events 的参数可以是以下字符的任意组合, 它指定了服务器该发送哪些类型的通知:

在这里插入图片描述
输入的参数中至少要有一个 K 或者 E , 否则的话, 不管其余的参数是什么, 都不会有任何通知被分发。

举个例子, 如果只想订阅键空间中和列表相关的通知, 那么参数就应该设为 Kl , 诸如此类。

将参数设为字符串 “AKE” 表示发送所有类型的通知。

NOTE:
所有命令都只在键真的被改动了之后,才会产生通知。

比如说,当 del key val 试图删除不存在的元素时,删除操作会执行失败,因为没有真正的改动键,所以这一操作不会发送通知。

解决方案

缓存预热

缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!*

缓存雪崩

问题排查:
在一个较短的时间内,缓存中较多的key集中过期
此周期内请求访问过期的数据,redis未命中,redis向数据库获取数据
解决方案
1.限流、降级
2.过期时间使用固定时间+随机值的形式,稀释集中到期的key的数量
3.超热数据使用永久key
总结
缓存雪崩就是瞬间过期数据量太大,导致对数据库服务器造成压力。如能够有效避免过期时间集中,可以有效解决雪崩现象的出现 ,配合其他策略一起使用。

缓存击穿

缓存击穿就是单个高热数据过期的瞬间,数据访问量较大,未命中redis后,发起了大量对同一数据的数据库访问,导致对数据库服务器造成压力。应对策略应该在业务数据分析与预防方面进行。

缓存穿透

缓存击穿访问了不存在的数据,跳过了合法数据的redis数据缓存阶段,每次访问数据库,导致对数据库服务器造成压力。可以通过设置黑名单解决。

Redis连接池问题

redis本身是单线程的没有问题,但这并不表示,使用连接池不能提供效率,只是不能通过多线程提高效率而已。
redis连接池较单连接的效能提高很多。要了解为什么redis连接池能够这么大幅的提高性能,就要了解单连接的性能瓶颈在哪。
单线程并不是redis性能瓶颈。对redis而言,有两个性能瓶颈所在(一个是计算性能,也就是所谓的执行命令速度,另一个是网络通信性能)。很显然,redis较执行效率而言,通信才是其瓶颈,因此,对于客户端将若干条命令传输给redis服务,命令执行时间和通信时间相比可以忽略,等待下一个命令到来的时间间隙redis没有任何命令执行,这就造成了redis闲置
综上,要提高redis的性能,可以降低单位时间内的通信成本。那么连接池就是一个不错的选择。
客户端使用连接池+多线程方案,使得使得redis服务闲置时间降低,极大地提高了服务效率。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值