3万字聊聊什么是Redis(八)完结了

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 继上篇Redis技术总结七,我们继续聊聊Redis的相关技术!这篇主要是介绍一下Redis事务机制ACID的实现,Redis主从同步的实战细节问题,

Redis如何实现事务ACID


什么是ACID

Redis能否实现事务ACID属性呢?

我们可以先来解释一下什么是ACID

  • A原子性:要不全部成功,要不全部失败
  • C一致性:事务执行前后是一致的,不能因为事务A执行时看到的字段A是1,准备提交时,字段A已经被事务B改成了2。这样是不行的。
  • I隔离性:执行事务时,其他操作无法存取到正在执行事务访问的数据。
  • D持久性:数据库执行事务后,数据的修改要被持久化保存下来。当数据库重启后,数据的值需要是被修改后的值。

Redis如何实现事务

事务执行的过程我们可以分为三步走

  1. 客户端要下达一个命令表示一个事务的开启 MULTI
  2. 客户端把本身要执行的操作和指令发给服务器端,这些也就是读写命令。服务器接收读写命令把他暂存在命令队列中 业务代码 set get incr 等
  3. 客户端向服务器端发起一个提交事务的命令让Redis去消化刚刚命令队列里的命令。 EXEC


事务机制的ACID的分析

原子性

对于Redis的原子性操作,主要分两种情况 执行报错入队报错

执行报错:  执行报错的话,说明入队的时候是不报错的。执行过程中必然会有正确的指令,Redis在执行过程中正确的会正常执行,报错的指令会返回报错。原子性就无法保证了

入队报错:  入队报错的话,Redis就不会执行这段指令,所以直接返回错误,可以保证原子性!

扩展一下MySQL,MySQL事务中报错的话会有回滚机制,Redis中是不存在回滚机制的。一旦使用过程中Redis发生了这种情况,我们可以使用Redis提供的 redis-check-aof 工具检查 AOF 日志文件,这个工具可以把未完成的事务操作从 AOF 文件中去除。这样一来,我们使用 AOF 恢复实例后,事务操作不会再被执行,从而保证了原子性。

如果AOF,RDB都不开启就不要谈数据安全性持久化这些概念了

一致性

事务的一致性保证会受到错误命令、实例故障的影响。所以,我们按照命令出错和实例故障的发生时机,分成三种情况来看。

  1. 入队就报错,Redis会放弃执行,同时也保证了数据库的一致性。
  2. 执行就报错,有错误的命令不会被执行,正确的命令可以正常执行,也不会改变数据库的一致性。
  3. 实例故障报错,实例故障重启后我们要根据用户是否开启了AOF和RDB进行分情况讨论。

如果我们使用了 RDB 快照,因为 RDB 快照不会在事务执行时执行,所以,事务命令操作的结果不会被保存到 RDB 快照中,使用 RDB 快照进行恢复时,数据库里的数据也是一致的。

如果我们使用了 AOF 日志,而事务操作还没有被记录到 AOF 日志时,实例就发生了故障,那么,使用 AOF 日志恢复的数据库数据是一致的。如果只有部分操作被记录到了 AOF 日志,我们可以使用 redis-check-aof 清除事务中已经完成的操作,数据库恢复后也是一致的。

Redis事务机制对一致性是有保证的

隔离性

事务的隔离性主要和并发有关。并发过程中我们还可以细分两个执行阶段。EXEC执行前EXEC执行后

执行前:  我们可以通过Redis提供的watch机制来实现隔离性

执行后:  无法保证

什么是watch机制?

在事务执行前,监控一个或多个键的值变化情况,当事务调用 EXEC 命令执行时,WATCH 机制会先检查监控的键是否被其它客户端修改了。如果修改了,就放弃事务执行,避免事务的隔离性被破坏。然后,客户端可以再次执行事务,此时,如果没有并发修改事务数据的操作了,事务就能正常执行,隔离性也得到了保证。

如果在执行前我们 没有使用watch机制,同时发生了并发请求,就会对数据进行读写,隔离性就没有得到保障

如果在EXEC执行后,虽然无法保证,但是Redis的单线程的。按照入队的先后顺序执行,所以后一个请求不会排的前面一个请求。于是 也不会破坏事务的隔离性

持久化

Redis 是内存数据库,所以,数据是否持久化保存完全取决于 Redis 的持久化配置模式。

  • 如果 Redis 没有使用 RDB 或 AOF,那么事务的持久化属性肯定得不到保证。
  • 如果 Redis 使用了 RDB 模式,那么,在一个事务执行后,而下一次的 RDB 快照还未执行前,如果发生了实例宕机,这种情况下,事务修改的数据也是不能保证持久化的。
  • 如果 Redis 采用了 AOF 模式,因为 AOF 模式的三种配置选项 no、everysec 和 always 都会存在数据丢失的情况,所以,事务的持久性属性也还是得不到保证。


Redis主从同步的那些问题


主从数据不一致

  1. 主从同步时,采用的是异步同步。所以无法保证主从库数据的实时一致性。
  2. 主从同步时,网络因素导致主从数据实时性的延迟
  3. 主从同步时,从库接收到了主库的命令。但是从库正在处理其他复杂度过高的命令而阻塞,从库只有处理完当前任务后才能处理主库的新命令。这就造成了主从延迟

解决方案

  1. 在硬件方面,我们要尽量保证主从库间的网络连接状况良好。例如,我们要避免把主从库部署在不同的机房,或者是避免把网络通信密集的应用和Redis 主从库部署在一起。
  2. 监控主从库间的复制差值,如果主从库差值过大我们就可以通过设置阈值的方式。干预解决主从同步的延迟问题

Redis 的 INFO replication 命令可以查看主库接收写命令的进度信息(master_repl_offset)和从库复制写命令的进度信息(slave_repl_offset),所以,我们就可以开发一个监控程序,先用 INFO replication 命令查到主、从库的进度,然后,我们用 master_repl_offset 减去 slave_repl_offset,这样就能得到从库和主库间的复制进度差值了

读到过期数据

平时应用中读到过期数据是比较常见的,我们分析一下为什么会读到过期数据。

假如一个key的过期时间是19:51:49,刚好有个请求访问了这个key,访问时间是19:51:50。

key过期了正等待被回收,但是还没有回收这段期间就被读取了。这主要是由Redis的过期策略引起的。

过期策略分 惰性删除定期删除

惰性删除。当一个数据的过期时间到了以后,并不会立即删除数据,而是等到再有请求来读写这个数据时,对数据进行检查,如果发现数据已经过期了,再删除这个数据。

这个策略的好处是尽量减少删除操作对 CPU 资源的使用,对于用不到的数据,就不再浪费时间进行检查和删除了。但是,这个策略会导致大量已经过期的数据留存在内存中,占用较多的内存资源。所以,Redis 在使用这个策略的同时,还使用了第二种策略:定期删除策略。

定期删除策略 是指Redis 每隔一段时间(默认 100ms),就会随机选出一定数量的数据,检查它们是否过期,并把其中过期的数据删除,这样就可以及时释放一些内存。

清楚了这两个删除策略,我们再来看看它们为什么会导致读取到过期数据。

首先,虽然定期删除策略可以释放一些内存,但是,Redis 为了避免过多删除操作对性能产生影响,每次随机检查数据的数量并不多。如果过期数据很多,并且一直没有再被访问的话,这些数据就会留存在 Redis 实例中。业务应用之所以会读到过期数据,这些留存数据就是一个重要因素。

其次,惰性删除策略实现后,数据只有被再次访问时,才会被实际删除。如果客户端从主库上读取留存的过期数据,主库会触发删除操作,此时,客户端并不会读到过期数据。但是,从库本身不会执行删除操作,如果客户端在从库中访问留存的过期数据,从库并不会触发数据删除。那么,从库会给客户端返回过期数据吗?这就和版本有关了!

版本问题

  • 3.2 之前的版本,从库在服务读请求时,并不会判断数据是否过期,而是会返回过期数据。
  • 3.2 版本后,如果读取的数据已经过期了,从库虽然不会删除,但是会返回空值,这就避免了客户端读到过期数据

除了版本的问题还有设置过期时间的命令有关,有些命令给数据设置的过期时间在从库上可能会被延后,导致应该过期的数据又在从库上被读取到了。

当主从库全量同步时,如果主库接收到了一条 EXPIRE 命令,那么,主库会直接执行这条命令。这条命令会在全量同步完成后,发给从库执行。而从库在执行时,就会在当前时间的基础上加上数据的存活时间,这样一来,从库上数据的过期时间就会比主库上延后了。

为了避免这种情况,我给你的建议是,在业务应用中使用 EXPIREAT/PEXPIREAT 命令,把数据的过期时间设置为具体的时间点,避免读到过期数据


结尾


大概总结了

  1. Redis在事务机制ACID的相关实现保证
  2. 分析了使用Redis时,Redis主从同步的那些问题

由主从同步问题展开了主从数据不一致的原因以及解决方案,过期数据的原因以及解决方案。

这篇文章大概算是Redis第二阶段的一个收尾吧。下面将从RocketMQ或者Mybatis进行技术的分享!


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
8月前
|
缓存 NoSQL Java
【Redis从头学-完结】Redis全景思维导图一览!耗时半个月专为Redis初学者打造!
【Redis从头学-完结】Redis全景思维导图一览!耗时半个月专为Redis初学者打造!
133 0
|
存储 缓存 监控
Redis学习笔记(五)完结
Redis的发布与订阅 Redis的主从复制 Redis的缓存穿透和雪崩
124 0
|
23天前
|
存储 NoSQL 算法
09- Redis分片集群中数据是怎么存储和读取的 ?
Redis分片集群使用哈希槽分区算法,包含16384个槽(0-16383)。数据存储时,通过CRC16算法对key计算并模16383,确定槽位,进而分配至对应节点。读取时,根据槽位找到相应节点直接操作。
54 12
|
23天前
|
NoSQL Linux Redis
06- 你们使用Redis是单点还是集群 ? 哪种集群 ?
**Redis配置:** 使用哨兵集群,结构为1主2从,加上3个哨兵节点,总计分布在3台Linux服务器上,提供高可用性。
334 0
|
1月前
|
负载均衡 监控 NoSQL
Redis的集群方案有哪些?
Redis集群包括主从复制(基础,手动故障恢复)、哨兵模式(自动高可用)和Redis Cluster(官方分布式解决方案,自动分片和容错)。此外,还有如Codis、Redisson和Twemproxy等第三方工具用于代理和负载均衡。选择方案需考虑应用场景、数据规模和并发需求。
276 2
|
2月前
|
NoSQL Redis
Redis集群(六):集群常用命令及说明
Redis集群(六):集群常用命令及说明
233 0
|
3月前
|
运维 NoSQL 算法
Redis-Cluster 与 Redis 集群的技术大比拼
Redis-Cluster 与 Redis 集群的技术大比拼
121 0
|
8天前
|
存储 NoSQL 算法
Redis 搭建分片集群
Redis 搭建分片集群
18 2
|
1月前
|
NoSQL Java 测试技术
面试官:如何搭建Redis集群?
**Redis Cluster** 是从 Redis 3.0 开始引入的集群解决方案,它分散数据以减少对单个主节点的依赖,提升读写性能。16384 个槽位分配给节点,客户端通过槽位信息直接路由请求。集群是无代理、去中心化的,多数命令直接由节点处理,保持高性能。通过 `create-cluster` 工具快速搭建集群,但适用于测试环境。在生产环境,需手动配置文件,启动节点,然后使用 `redis-cli --cluster create` 分配槽位和从节点。集群动态添加删除节点、数据重新分片及故障转移涉及复杂操作,包括主从切换和槽位迁移。
34 0
面试官:如何搭建Redis集群?
|
2月前
|
存储 NoSQL 前端开发
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群指令分析—实战篇)
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(集群指令分析—实战篇)
11 0