当前位置:   article > 正文

redis笔记_crossslot keys

crossslot keys

Redis 简介

key-value存储形式的非关系型数据库。

三大特点:

  • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。

优点:

  • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets
    数据类型操作。
  • 原子 –
    Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
  • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

redis常用数据结构以及应用场景

Redis支持五种数据类型:

  • string(字符串) 适用于简单的键值类型、常规计数(微博数,粉丝数等)
  • hash(哈希):是一个键值(key=>value)对集合,一个 string 类型的 field(字段) 和 value(值)
    的映射表。 适用于存储读取修改信息等
  • list(列表):简单的字符串列表,按照插入顺序排序。
    微博的关注列表,粉丝列表,最新消息排行等功能都可以用Redis的list结构来实现。
  • set(集合): string 类型的无序集合,不可插入重复元素。 实现如共同关注、共同喜好、二度好友等功能
  • zset(sorted set:有序集合):有序的set。 sortset的使用场景一般是排行榜之类的场景。

Redis事务跟Mysql事务有什么区别

Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

批量操作在发送 EXEC 命令前被放入队列缓存。
收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
Redis以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令。
单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

MySQL:

  • BEGIN:显式地开启一个事务;
  • COMMIT:提交事务,将对数据库进行的所有修改变成为永久性的;
  • ROLLBACK:结束用户的事务,并撤销正在进行的所有未提交的修改;

Redis:

  • MULTI:标记事务的开始;
  • EXEC:执行事务的commands队列;
  • DISCARD:结束事务,并清除commands队列;

MySQL会默认开启一个事务,且缺省设置是自动提交,即,每成功执行一个SQL,一个事务就会马上 COMMIT。所以不能Rollback。
Redis默认不会开启事务,即command会立即执行,而不会排队。并不支持Rollback。

redis中删除过期key的策略

Redis可以设置过期时间,至于过期键什么时候删除有三种策略

  • 定时删除 : 创建过期时间,同时会创建一个定时器,计算时间,到达过期时间自动删除。过期key较多时会消耗较多的CPU资源
  • 惰性删除 : 放任键过期不管,只有在下次查询该键时,进行时间比对,如果过期则删除,否则返回。适用于CPU资源紧张,内存资源不紧张
  • 定期删除 : 定期对整个Redis进行一次检测,然后删除过期键。

redis的雪崩、穿透、击穿,以及对应的策略

缓存雪崩

指缓存中的数据大批量的过期甚至是缓存服务器宕机,而查询数据量过大,引起数据库压力过大或导致宕机。

解决方法:

  • 将缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值;
  • 在发生雪崩前对缓存集群实现高可用,如果是使用 Redis,可以使用 主从+哨兵 ,Redis Cluster 来避免 Redis全盘崩溃的情况。
  • Hystrix是一款开源的“防雪崩工具”,它通过 熔断、降级、限流三个手段来降低雪崩发生后的损失。
缓存穿透

业务系统要查询的数据根本就不存在!当业务系统发起查询时,首先会前往缓存中查询,由于缓存中不存在,然后再前往数据库中查询。由于该数据压根就不存在,因此数据库也返回空。这就是缓存穿透。

产生原因:恶意攻击;代码逻辑错误。

解决方法:

  • 将查询为空的key直接放在缓存上,同时将值标记为null,但是需要设置过期时间,防止期间出现数据库增添该数据的情况造成缓存不一致的情况。
  • 使用BloomFilter。它需要在缓存之前再加一道屏障,里面存储目前数据库中存在的所有key,如图所示

在这里插入图片描述

空数据的key各不相同、key重复请求概率低的场景而言,应该选择第二种方案。而对于空数据的key数量有限、key重复请求概率较高的场景而言,应该选择第一种方案。

缓存击穿(热点数据集中失效)

热点数据,在缓存中失效了,数据库中有,大量线程/进程访问数据库,导致数据库压力过大或者崩溃。

解决方法:

使用互斥锁重建缓存;
当第一个数据库查询请求发起后,就将缓存中该数据上锁;此时到达缓存的其他查询请求将无法查询该字段,从而被阻塞等待;当第一个请求完成数据库查询,并将数据更新值缓存后,释放锁;此时其他被阻塞的查询请求将可以直接从缓存中查到该数据。
当某一个热点数据失效后,只有第一个数据库查询请求发往数据库,其余所有的查询请求均被阻塞,从而保护了数据库。但是,由于采用了互斥锁,其他请求将会阻塞等待,此时系统的吞吐量将会下降。这需要结合实际的业务考虑是否允许这么做。
设置热点数据永不过期(从功能上看一发生逻辑过期,就使用单独的线程重建缓存);
但唯一不足的就是重构缓存期间,会出现数据不一致的情况,这取决于应用方是否容忍这种不一致。

redis高可用

在 Redis 中,实现 高可用 的技术主要包括 持久化、复制、哨兵 和 集群,下面简单说明它们的作用,以及解决了什么样的问题:

  • 持久化:持久化是 最简单的 高可用方法。它的主要作用是 数据备份,即将数据存储在 硬盘,保证数据不会因进程退出而丢失。
  • 复制:复制是高可用 Redis 的基础,哨兵 和 集群 都是在 复制基础
    上实现高可用的。复制主要实现了数据的多机备份以及对于读操作的负载均衡和简单的故障恢复。缺陷是故障恢复无法自动化、写操作无法负载均衡、存储能力受到单机的限制。
  • 哨兵:在复制的基础上,哨兵实现了 自动化 的 故障恢复。缺陷是 写操作 无法 负载均衡,存储能力 受到 单机 的限制。
  • 集群:通过集群,Redis 解决了 写操作 无法 负载均衡 以及 存储能力 受到 单机限制 的问题,实现了较为 完善 的 高可用方案。

redis中两种持久化方式

RDB(Redis DataBase)持久化(原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化)

优点:

  • 该方式Redis数据库中只有一个文件,方便备份。
  • 适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心
  • 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。

劣势:

  • 系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
  • 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。

AOF持久化(Append Only File) (原理是将Reids的操作日志以追加的方式写入文件)可采用每秒同步、每修改同步策略。

优点:

  • AOF数据安全性高,每秒同步,宕机时失去的只是这一秒的修改,写入时宕机,不会对已存在的内容造成影响

缺点:

  • 通常AOF文件比RDB文件大,AOF恢复大数据集时的速度要比RDB慢,AOF运行效率也往往低于RDB

二者选择的标准,如果你非常关心你的数据,但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化;如果系统是愿意牺牲一些性能,换取更高的缓存一致性,可以选用AOF。

Redis宕机怎么解决数据丢失问题(RDB,AOF,主从复制)

主从复制

Redis主从复制的配置和实现原理

为一个主服务器设置多个从服务器,从服务器从主服务器中复制内容。
主服务器master可以进行读写操作,当主服务器的数据发生变化,master会发出命令流来保持对salve的更新,而从服务器slave通常是只读的(可以通过slave-read-only指定),在主从复制模式下,即便master宕机了,slave是不能变为主服务器进行写操作的。

主从复制的好处:

  • 数据冗余,实现数据的热备份
  • 故障恢复,避免单点故障带来的服务不可用
  • 读写分离,负载均衡。主节点负载读写,从节点负责读,提高服务器并发量
  • 高可用基础,是哨兵机制和集群实现的基础

Redis的主从复制过程大体上分3个阶段:建立连接、数据同步、命令传播

Redis哨兵

https://juejin.cn/post/6844903663362637832

它可以实现对 Redis的监控、通知、自动故障转移。主要作用:
1.通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
2.当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。

然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。

Sentinel的工作方式:

  • 1):每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令
  • 2):如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds
    选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。
  • 3):如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel
    要以每秒一次的频率确认Master的确进入了主观下线状态。
  • 4):当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态,
    则Master会被标记为客观下线
  • 5):在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO
    命令。当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO
    命令的频率会从 10 秒一次改为每秒一次
  • 6):Sentinel 和其他 Sentinel 协商 主节点 的状态,如果 主节点 处于 SDOWN 状态,则投票自动选出新的
    主节点。将剩余的 从节点 指向 新的主节点 进行 数据复制。
  • 7):若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。
    若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。

Redis-Cluster集群

在3.0版本及以后才支持集群

  • redis集群采用P2P模式,是完全去中心化的,不存在中心节点或者代理节点;
  • redis集群是没有统一的入口的,客户端(client)连接集群的时候连接集群中的任意节点(node)即可,集群内部的节点是相互通信的(PING-PONG机制),每个节点都是一个redis实例;
  • 为了实现集群的高可用,即判断节点是否健康(能否正常使用),redis-cluster有这么一个投票容错机制:如果集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的方法;
  • 那么如何判断集群是否挂了呢? ->
    如果集群中任意一个节点挂了,而且该节点没有从节点(备份节点),那么这个集群就挂了。这是判断集群是否挂了的方法;
  • 那么为什么任意一个节点挂了(没有从节点)这个集群就挂了呢? ->
    因为集群内置了16384个slot(哈希槽),并且把所有的物理节点映射到了这16384[0-16383]个slot上,或者说把这些slot均等的分配给了各个节点。当需要在Redis集群存放一个数据(key-value)时,redis会先对这个key进行crc16算法,然后得到一个结果。再把这个结果对16384进行求余,这个余数会对应[0-16383]其中一个槽,进而决定key-value存储到哪个节点中。所以一旦某个节点挂了,该节点对应的slot就无法使用,那么就会导致集群无法正常工作。
  • 每个Redis集群理论上最多可以有16384个节点。

如何保证redis和mysql中的数据一致性

数据库和缓存更新,就容易出现缓存和数据库间的数据一致性问题。不管是先写数据库,再删除缓存;还是先删除缓存,再写库,都有可能出现数据不一致的情况。
1.如果删除了缓存Redis,还没有来得及写库MySQL,另一个线程就来读取,发现缓存为空,则去数据库中读取数据写入缓存,此时缓存中为脏数据。
2.如果先写了库,在删除缓存前,写库的线程宕机了,没有删除掉缓存,则也会出现数据不一致情况。

解决办法:

  • 延时双删策略
    1.先删除缓存
    2.再写数据库
    3.休眠500毫秒(根据具体的业务时间来定)
    4.再次删除缓存。
  • 设置缓存的过期时间
    所有的写操作以数据库为准,只要到达缓存过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。

Redis会不会变慢?怎么解决这个问题

情况1:确认下是否采用了复杂度高的慢查询命令
解决方法:用其他高效命令代替。

情况2:过期 key 操作(如果超过 25% 的 key 过期了,Redis 的线程就会一直执行删除,这样一来,就没办法正常服务其他的键值操作了,就会进一步引起其他键值操作的延迟增加,Redis 就会变慢。)
解决方法:将过期时间分散开。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/794064
推荐阅读
相关标签
  

闽ICP备14008679号