redis小结

Redis缓存更新怎么保证⼀致性?

删缓存->更新db->再删缓存

更新db->删缓存

第一种方案:

使用阿里的canal将binlog日志采集发送到MQ队列里面,然后通过ACK机制确认处理 这条更新消息,删除缓存,保证数据缓存一致性

(1)读取缓存中是否有相关数据
(2)如果缓存中有相关数据value,则返回
(3)如果缓存中没有相关数据,则从数据库读取相关数据放入缓存中key->value,再返回
(4)如果有更新数据,则先更新数据,再删除缓存
(5)为了保证第四步删除缓存成功,使用binlog异步删除
(6)如果是主从数据库,binglog取自于从库
(7)如果是一主多从,每个从库都要采集binlog,然后消费端收到最后一台binlog数据才删除缓存

高并发环境下,先操作数据库还是先操作缓存

第二种方案:

使用一致性算法: paxos

Redis分布式锁原理?会有什么问题

redis分布式锁的实现主要是基于redis的setnx 命令

第一种情况:业务逻辑执行时间超出锁的超时限制,其他客户端得到锁之后,被超时客户端删除锁

一个客户端拿到了锁,被某个操作阻塞了很长时间,过了超时时间后自动释放了
这个锁,然后这个客户端之后又尝试删除这个其实已经被其他客户端拿到的锁。
所以单纯的用DEL指令有可能造成一个客户端删除了其他客户端的锁,
通过校验这个值保证每个客户端都用一个随机字符串’签名’了,
这样每个锁就只能被获得锁的客户端删除了。

第二种情况:业务逻辑执行时间超出锁的超时限制导致两个客户端同时持有锁的问题

如果在加锁和释放锁之间的逻辑执行得太长,以至于超出了锁的超时限制,
就会出现问题。因为这时候第一个线程持有的锁过期了,临界区的逻辑还没有
执行完,这个时候第二个线程就提前重新持有了这把锁,导致临界区代码不能
得到严格的串行执行

如果在执行计算期间发现锁快要超时了,客户端可以给redis服务实例发送一个
Lua脚本让redis服务端延长锁的时间,只要这个锁的key还存在而且值还等于
客户端设置的那个值    

if  redis.call("get",KEYS[1]) == ARGV[1] then 
        redis.call("set",KEYS[1],ex=3000)
else 
        getDLock();//重新获取锁

第三种: redis的单点故障主从切换带来的两个客户端同时持有锁的问题

生产中redis一般是主从模式,主节点挂掉时,从节点会取而代之,
客户端上却并没有明显感知。原先第一个客户端在主节点中申请成功了一把锁,
但是这把锁还没有来得及同步到从节点,主节点突然挂掉了。
然后从节点变成了主节点,这个新的节点内部没有这个锁,
所以当另一个客户端过来请求加锁时,立即就批准了。
这样就会导致系统中同样一把锁被两个客户端同时持有

不过这种不安全也仅仅是在主从发生 failover 的情况下才会产生,
而且持续时间极短,业务系统多数情况下可以容忍

RedLock算法

使用N个完全独立、没有主从关系的Redis master节点以保证他们大多数情况下都不会同时宕机,N一般为奇数。一个客户端需要做如下操作来获取锁:

  • 1.获取当前时间(单位是毫秒)。
  • 2.轮流用相同的key和随机值在N个节点上请求锁,在这一步里,客户端在每个master上请求锁时,会有一个和总的锁释放时间相比小的多的超时时间。比如如果锁自动释放时间是10秒钟,那每个节点锁请求的超时时间可能是5-50毫秒的范围,这个可以防止一个客户端在某个宕掉的master节点上阻塞过长时间,如果一个master节点不可用了,我们应该尽快尝试下一个master节点。
  • 3.客户端计算第二步中获取锁所花的时间,只有当客户端在大多数master节点上成功获取了锁((N/2) +1),而且总共消耗的时间不超过锁释放时间,这个锁就认为是获取成功了。
  • 4.如果锁获取成功了,那现在锁自动释放时间就是最初的锁释放时间减去之前获取锁所消耗的时间。
  • 5.如果锁获取失败了,不管是因为获取成功的锁不超过一半(N/2+1)还是因为总消耗时间超过了锁释放时间,客户端都会到每个master节点上释放锁,即便是那些他认为没有获取成功的锁。

使用Redis的分布式锁

Redis集群⽅案?新增节点后如何进⾏数据迁移。

Redis Cluster

添加一个空节点,然后将一些数据移入该节点(如果它是新的主节点),或者告诉它设置为已知节点的副本(如果它是从节点的话)

redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
add-node命令将新节点的地址指定为第一个参数,并将集群中随机存在的节点的地址指定为第二个参数.
与其他master节点相比:

由于没有分配的`hash slots`,因此不保存任何数据。(可以使用的重新分片功能为此节点分配`hash slots`)
因为它是没有分配`slots`的主机,所以当从机要成为主机时,它不会参与选举过程。

添加一个新的节点

新增节点后如何进⾏数据迁移没有找到相关资料。。。

Redis持久化机制?RDB、AOF,最新的默认⽅案是什么?

RDB的优点:

  • RDB是Redis数据的非常紧凑的单文件时间点表示。RDB文件非常适合备份。例如,您可能希望在最近的24小时内每小时存档一次RDB文件,并在30天之内每天保存一次RDB快照。这使您可以在发生灾难时轻松还原数据集的不同版本。
  • RDB对于灾难恢复非常有用,它是一个紧凑的文件,可以传输到远程数据中心或Amazon S3(可能已加密)上。
  • RDB最大限度地提高了Redis的性能,因为Redis父进程为了持久化所需要做的唯一工作就是分叉一个孩子,其余的都将做。父实例将永远不会执行磁盘I / O或类似操作。
  • 与AOF相比,RDB允许大型数据集更快地重启。

RDB的缺点:

  • 如果您需要在Redis停止工作(例如断电后)的情况下最大程度地减少数据丢失的机会,则RDB不好。您可以在生成RDB的位置配置不同的保存点(例如,在至少五分钟之后,对数据集进行100次写入,但是您可以有多个保存点)。但是,通常会每隔五分钟或更长时间创建一次RDB快照,因此,如果Redis出于任何原因在没有正确关闭的情况下停止工作,则应该准备丢失最新的数据分钟。
  • RDB需要经常使用fork()才能使用子进程将其持久化在磁盘上。如果数据集很大,Fork()可能很耗时,并且如果数据集很大且CPU性能不佳,则可能导致Redis停止为客户端服务几毫秒甚至一秒钟。AOF还需要fork(),但您可以调整要重写日志的频率,而无需在持久性上进行权衡。

AOF的优点:

  • 使用AOF Redis更加持久:您可以有不同的fsync策略:完全没有fsync,每秒fsync,每个查询fsync。使用默认策略fsync时,每秒的写入性能仍然很好(fsync是使用后台线程执行的,并且在没有进行fsync的情况下,主线程将尽力执行写入操作。)但是您只能损失一秒钟的写入时间。
  • AOF日志仅是一个追加日志,因此,如果断电,也不会出现寻道或损坏问题。即使由于某种原因(磁盘已满或其他原因)以半写命令结束日志,redis-check-aof工具也可以轻松修复它。
  • Redis太大时,Redis可以在后台自动重写AOF。重写是完全安全的,因为Redis继续追加到旧文件时,会生成一个全新的文件,其中包含创建当前数据集所需的最少操作集,一旦准备好第二个文件,Redis会切换这两个文件并开始追加到新的那一个。
  • AOF以易于理解和解析的格式包含所有操作的日志。您甚至可以轻松导出AOF文件。例如,即使您使用FLUSHALL命令刷新了所有错误文件,如果在此期间未执行任何日志重写操作,您仍然可以保存数据集,只是停止服务器,删除最新命令并重新启动Redis。

AOF的缺点:

  • 对于相同的数据集,AOF文件通常大于等效的RDB文件。
  • 根据确切的fsync策略,AOF可能比RDB慢。通常,在将fsync设置为每秒的情况下,性能仍然很高,并且在禁用fsync的情况下,即使在高负载下,它也应与RDB一样快。即使在巨大的写负载情况下,RDB仍然能够提供有关最大延迟的更多保证。
  • 过去,我们在特定命令中遇到过罕见的错误(例如,其中一个涉及阻止命令,例如BRPOPLPUSH),导致生成的AOF在重载时无法重现完全相同的数据集。这些错误很少见,我们在测试套件中进行了测试,自动创建了随机的复杂数据集,然后重新加载它们以检查一切是否正常。但是,RDB持久性几乎是不可能的。为了更清楚地说明这一点:Redis AOF通过像MySQL或MongoDB那样增量更新现有状态来工作,而RDB快照一次又一次地创建所有内容,从概念上讲,它更健壮。但是-1)请注意,每次Redis重写AOF时,都会从数据集中包含的实际数据开始重新创建AOF,与始终附加AOF文件(或重写为读取旧AOF而不是读取内存中的数据)相比,提高了对错误的抵抗力。2)我们从未收到过有关真实环境中检测到的AOF损坏的用户报告。
    Redis持久化机制

redis持久化深入

Redis缓存过期与淘汰机制是什么?

  • volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  • volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  • volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  • allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
  • allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  • no-enviction(驱逐):禁止驱逐数据

Redis的缓存穿透、缓存击穿是否了解?业界会使⽤什么⽅案?如果缓存⼤规模失效,怎么办?

缓存穿透,即黑客故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。

解决方案:
(一)利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试
(二)采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。
(三)提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。

redis bloom

使⽤Redis的场景

签到,报名,投票: 位图

位图是一个byte数组,可以使用get/set直接设置跟读取整个位图的值,
也可以使用位图操作getbit/setbit等将byte数组当做位数组来处理。
Redis的位数组是自动扩展的,如果设置了阈值且当前超出了阈值会自动将数组进行扩充,
还可以使用bitcount实现快速统计,使用位图查找指令bitpos查找某范围的位图值,
两个指令也可以组合使用对某个范围的位图值进行统计。比如查找一个用户一年中每周末签到数总和。 

地理位置GEO模块:附近人功能

ZSet底层是如何实现的

ZSet底层是如何实现的

HashSet是如何实现的?

HashSet不能保证元素的顺序,TreeSet中的元素可以按照某个顺序排列。他们的元素都不能重复

HashSet是如何实现的

redis和zookeeper做分布式锁各有什么优缺点?

Redis 分布式锁,其实需要自己不断去尝试获取锁,比较消耗性能。

Zookeeper分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小。

Redis有什么缺点?

(一)缓存和数据库双写一致性问题
(二)缓存雪崩问题
(三)缓存击穿问题
(四)缓存的并发竞争问题

redis_cluster 不同的key的 set集合数据是在⼀个node还是多个node

为什么说redis能够快速执行

绝大部分请求是纯粹的内存操作(非常快速)
采用单线程,避免了不必要的上下文切换和竞争条件
非阻塞IO - IO多路复用

Redis常见性能问题和解决方案?

  • (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
  • (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
  • (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内
  • (4) 尽量避免在压力很大的主库上增加从库
  • (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3…这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。

为什么Redis不支持回滚

Redis命令在事务期间可能会失败,但Redis仍将执行事务的其余部分而不是回滚

  • 仅当使用错误的语法(并且在命令队列期间无法检测到该问题)或针对持有错误数据类型的键调用Redis命令时,该命令才能失败:这实际上意味着失败的命令是编程错误的结果,还有一种很可能在开发过程中而不是生产过程中发现的错误。
  • Redis在内部得到了简化和更快,因为它不需要回滚的能力。

为什么Redis不支持回滚

Redis使用epoll异步非阻塞模型 ,Redis自身实现了事件处理模型将epoll中的链接、读写、关闭都转换为事件,不在网络IO上浪费过多的事

redis使用epoll

升级redis集群节点

升级从节点:

停止节点并使用更新版本的Redis重新启动它即可。
如果存在使用从属节点扩展读取的客户端,则在给定的从属节点不可用时,
它们应该能够重新连接到其他从属节点

升级master节点:

  • 使用CLUSTER FAILOVER触发主服务器到其从服务器之一的手动故障转移。
  • 等待主机变成从机。
  • 最后,像对从属服务器一样升级节点。
  • 如果要将主节点作为刚刚升级的节点,请触发新的手动故障转移,以将升级后的节点转换回主节点。

升级redis集群节点

参考资料:

redis常用命令解析

redis_commands_list

redis-FAQ

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值