Redis主从问题
主从问题
数据不一致主要原因:
主从库间的网络可能会有传输延迟,所以从库不能及时地收到主库发送的命令,从库上执行同步命令的时间就会被延后。
另一方面,即使从库及时收到了主库的命令,但是,也可能会因为正在处理其它复杂度高的命令(例如集合操作命令)而阻塞。此时,从库需要处理完当前的命令,才能执行主库发送的命令操作,这就会造成主从数据不一致。
两种方法:
在硬件环境配置方面,我们要尽量保证主从库间的网络连接状况良好。
我们还可以开发一个外部程序来监控主从库间的复制进度。
因为 Redis 的 INFO replication 命令可以查看主库接收写命令的进度信息(master_repl_offset)和从库复制写命令的进度信息(slave_repl_offset),所以,我们就可以开发一个监控程序,先用 INFO replication 命令查到主、从库的进度,然后,我们用 master_repl_offset 减去 slave_repl_offset,这样就能得到从库和主库间的复制进度差值了。
如果某个从库的进度差值大于我们预设的阈值,我们可以让客户端不再和这个从库连接进行数据读取 ...
Redis主从同步
主从同步同步流程当我们启动多个 Redis 实例的时候,它们相互之间就可以通过 replicaof(Redis 5.0 之前使用 slaveof)命令形成主库和从库的关系,之后会按照三个阶段完成数据的第一次同步。
第一阶段:是主从库间建立连接、协商同步的过程,主要是为全量复制做准备。(从库给主库发送 psync 命令,表示要进行数据同步,主库根据这个命令的参数来启动复制。psync 命令包含了主库的 runID 和复制进度 offset 两个参数。)
在第二阶段:主库将所有数据同步给从库。从库收到数据后,在本地完成数据加载。这个过程依赖于内存快照生成的 RDB 文件。(从库接收到 RDB 文件后,会先清空当前数据库,然后加载 RDB 文件)
第三个阶段:主库会把第二阶段执行过程中新收到的写命令,再发送给从库。
存在问题问题一:
一次全量复制中,对于主库来说,需要完成两个耗时的操作:生成 RDB 文件和传输 RDB 文件。如果从库数量很多,而且都要和主库进行全量复制的话,就会导致主库忙于 fork 子进程生成 RDB 文件,进行数据全量同步,导致fork操作阻塞主线程。
解决:通 ...
Redis事务
Redis事务Redis 提供了 MULTI、EXEC 两个命令来进行事务操作。
MULTI:表示一个事务的开启,之后客户端发过来的命令都会暂存到一个命令队列中,并不会立即执行。
EXEC:当服务器端收到 EXEC 命令后,才会实际执行命令队列中的所有命令。
Redis 的事务机制能保证哪些属性?原子性
没有发生错误:那操作可以保证原子性
执行发生错误:需要分3种情况
在执行 EXEC 命令前,客户端发送的操作命令本身就有错误。(例如语法错误等)
此时,我们还能继续提交命令操作。等到执行了 EXEC 命令之后,Redis 就会拒绝执行所有提交的命令操作。
在执行 EXEC 命令前,命令和操作的数据类型不匹配,但 Redis 实例没有检查出错误。
Redis会对错误命令报错,但还是会把正确的命令执行完。在这种情况下,事务的原子性就无法得到保证了。
如果有错误语句可以使用DISCAR命令来让事务放弃
在执行事务的 EXEC 命令时,Redis 实例发生了故障,导致事务执行失败。
如果 Redis 开启了 AOF 日志,使用 redis-check-aof 工具检查 AOF ...
Redis应对高并发
应对高并发我们在使用 Redis 时,不可避免地会遇到并发访问的问题。
为了保证并发访问的正确性,Redis 提供了两种方法,分别是加锁和原子操作。
加锁加锁是一种常用的方法,在读取数据前,客户端需要先获得锁,否则就无法进行操作。当一个客户端获得锁后,就会一直持有这把锁,直到客户端完成数据更新,才释放这把锁。
缺点:
如果加锁操作多,会降低系统的并发访问性能。
Redis 客户端要加锁时,需要用到分布式锁,而分布式锁实现复杂,需要用额外的存储系统来提供加解锁操作。
分布式锁
基于单个 Redis 节点实现分布式锁
用Redis存锁变量,key为变量名,value为锁的值;例如:lock_key:0
为了保证锁操作的原子性,需要使用原子操作的语句来实现加锁与释放锁。
加锁:SET key value [EX seconds | PX milliseconds] [NX]例如:SET lock_key unique_value NX PX 10000其中,unique_value 是客户端的唯一标识,可以用一个随机生成的字符串来表示,PX 10000 则表示 lock_key 会在 ...
Redis缓存与数据库一致性问题
缓存与数据库一致性问题概述这里的“一致性”包含了两种情况:
缓存中有数据,那么,缓存的数据值需要和数据库中的值相同;
缓存中本身没有数据,那么,数据库中的值必须是最新值。
不符合这两种情况的,就属于缓存和数据库的数据不一致问题了。
解决方案重试机制具体来说,可以把要删除的缓存值或者是要更新的数据库值暂存到消息队列中(例如使用 Kafka 消息队列)。当应用没有能够成功地删除缓存值或者是更新数据库值时,可以从消息队列中重新读取这些值,然后再次进行删除或更新。
两种不同顺序存在的问题:
情况一:先删除缓存,再更新数据库。
延迟双删方案:在线程 A 更新完数据库值以后,我们可以让它先 sleep 一小段时间,再进行一次缓存删除操作。
情况二:先更新数据库值,再删除缓存值。
这种情况对业务的影响较小。
总结:
Redis内存替换策略
内存替换策略策略分类Redis 4.0 之前一共实现了 6 种内存淘汰策略,在 4.0 之后,又增加了 2 种策略。
我们可以按照是否会进行数据淘汰把它们分成两类:
不进行数据淘汰的策略,只有 noeviction 这一种。
会进行淘汰的 7 种其他策略。
在设置了过期时间的数据中进行淘汰,包括 volatile-random、volatile-ttl、volatile-lru、volatile-lfu(Redis 4.0 后新增)四种。
在所有数据范围内进行淘汰,包括 allkeys-lru、allkeys-random、allkeys-lfu(Redis 4.0 后新增)三种。
策略详讲 noeviction 策略
Redis 在使用的内存空间超过 maxmemory 值时,并不会淘汰数据,也就是设定的 noeviction 策略。
对应到 Redis 缓存,也就是指,一旦缓存被写满了,再有写请求来时,Redis 不再提供服务,而是直接返回错误。
基于过期时间的四种策略
volatile-ttl:在筛选时,会针对设置了过期时间的键值对,根据过期时间的先后进行删除, ...
Redis做缓冲
Redis做缓存缓存的特征
第一个特征:在一个层次化的系统中,缓存一定是一个快速子系统,数据存在缓存中时,能避免每次从慢速子系统中存取数据。
第二个特征:缓存系统的容量大小总是小于后端慢速系统的,我们不可能把所有数据都放在缓存系统中。
Redis 缓存处理请求的两种情况
缓存命中:Redis 中有相应数据,就直接读取 Redis,性能非常快。
缓存缺失:Redis 中没有保存相应数据,就从后端数据库中读取数据,性能就会变慢。而且,一旦发生缓存缺失,为了让后续请求能从缓存中读取到数据,我们需要把缺失的数据写入 Redis,这个过程叫作缓存更新。
因为需要在应用程序新增程序代码来使用缓存,所以,Redis 并不适用于那些无法获得源码的应用。
缓存类型只读缓存当 Redis 用作只读缓存时,应用要读取数据的话,会先调用 Redis GET 接口,查询数据是否存在。而所有的数据写请求,会直接发往后端的数据库,在数据库中增删改。对于删改的数据来说,如果 Redis 已经缓存了相应的数据,应用需要把这些缓存的数据删除,Redis 中就没有这些数据了。当应用再次读取这些数据时,会发 ...
Redis缓冲区
缓冲区概述缓冲区的功能其实很简单,主要就是用一块内存空间来暂时存放命令数据,以免出现因为数据和命令的处理速度慢于发送速度而导致的数据丢失和性能问题。
Redis 是典型的client-server 架构,所有的操作命令都需要通过客户端发送给服务器端。所以,缓冲区在 Redis 中的一个主要应用场景,就是在客户端和服务器端之间进行通信时,用来暂存客户端发送的命令数据,或者是服务器端返回给客户端的数据结果。此外,缓冲区的另一个主要应用场景,是在主从节点间进行数据同步时,用来暂存主节点接收的写命令和数据。
输入缓冲区溢出可能导致溢出的情况主要是下面两种:
写入了 bigkey,比如一下子写入了多个百万级别的集合类型数据。
服务器端处理请求的速度过慢,例如,Redis 主线程出现了间歇性阻塞,无法及时处理正常发送的请求,导致客户端发送的请求在缓冲区越积越多。
要查看和服务器端相连的每个客户端对输入缓冲区的使用情况,我们可以使用 CLIENT LIST 命令:
重点关注两类信息:
一类是与服务器端连接的客户端的信息。
另一类是与输入缓冲区相关的三个参数:
cmd,表示客户端最新执行的命 ...
Redis内存碎片问题
内存碎片问题其实,内存碎片的形成有内因和外因两个层面的原因。简单来说,内因是操作系统的内存分配机制,外因是 Redis 的负载特征。
内因:内存分配器的分配策略内存分配器的分配策略就决定了操作系统无法做到“按需分配”。这是因为,内存分配器一般是按固定大小来分配内存,而不是完全按照应用程序申请的内存空间大小给程序分配。
这样的分配方式本身是为了减少分配次数。但是,如果 Redis 每次向分配器申请的内存空间大小不一样,这种分配方式就会有形成碎片的风险,而这正好来源于 Redis 的外因了。
外因:键值对大小不一样和删改操作Redis 通常作为共用的缓存系统或键值数据库对外提供服务,所以,不同业务应用的数据都可能保存在 Redis 中,这就会带来不同大小的键值对。
具体来说,一方面,如果修改后的键值对变大或变小了,就需要占用额外的空间或者释放不用的空间。另一方面,删除的键值对就不再需要内存空间了,此时,就会把空间释放出来,形成空闲空间。
如何判断是否有内存碎片?Redis 是内存数据库,内存利用率的高低直接关系到 Redis 运行效率的高低。为了让用户能监控到实时的内存使用情况,Redis ...
如何应对变慢的Redis?
如何应对变慢的Redis?如何判断 Redis 是不是真的变慢了?查看 Redis 的响应延迟当你发现 Redis 命令的执行时间突然就增长到了几秒,基本就可以认定 Redis 变慢了。
这种方法是看 Redis 延迟的绝对值,但是,在不同的软硬件环境下,Redis 本身的绝对性能并不相同。所以需要基于当前环境下的 Redis 基线性能做判断。
所谓的基线性能呢,也就是一个系统在低压力、无干扰下的基本性能,这个性能只由当前的软硬件配置决定。
从 2.8.7 版本开始,redis-cli 命令提供了–intrinsic-latency 选项,可以用来监测和统计测试期间内的最大延迟,这个延迟可以作为 Redis 的基线性能。其中,测试时长可以用–intrinsic-latency 选项的参数来指定。
例如:./redis-cli --intrinsic-latency 120该命令会打印 120 秒内监测到的最大延迟。
如果你想了解网络对 Redis 性能的影响,一个简单的方法是用 iPerf 这样的工具,测量从 Redis 客户端到服务器端的网络延迟。
如何应对 Redis 变慢?R ...