Redis相关知识

Redis 怎么保证高可用

数据持久化

Redis持久化方式有两种 RDB和AOF

AOF 文件的内容是操作命令;RDB 文件的内容是二进制数据(实际的数据)

RDB的实现方式为,在指定时间将当前时刻内存中的数据生成一个快照文件(.rdb文件,默认为dump.rdb),并将这个快照文件保存到磁盘上。这样,即使redis宕机了,下次重启时也可以通过读取这个快照文件来恢复数据。

Redis中的rdb快照是全量快照,也就是说每次执行快照,都是把内存中的「所有数据」都记录到磁盘中。 执行快照是一个比较重的操作,如果频率太频繁,可能会对 Redis 性能产生影响。如果频率太低,服务器故障时,丢失的数据会更多。

rdb快照文件的方式主要有:

配置文件(自动触发) : save 300 100 -> 300秒内有100个key被修改,则触发RDB 至少 5 分钟才保存一次快照

执行save命令 : save命令是一个同步操作,执行该命令后,RDB持久化是在主进程中进行的,这样会阻塞当前redis服务,直到RDB持久化完成后,客户端才能正常连接redis服务

执行bgsave命令(手动触发) : bgsave命令是一个异步操作。执行该命令后,redis主进程会通过fork操作创建一个子进程,RDB持久化是由子进程操作,完成后自动结束。这个过程中,主进程不阻塞,可以继续接收客户端的访问

写时复制技术: 执行 bgsava 命令的时候,会通过 fork() 创建子进程,此时子进程和父进程是共享同一片内存数据

的,因为创建子进程的时候,会复制父进程的页表,但是页表指向的物理内存还是一个。只有在发生修改内存数据的情况

时,物理内存才会被复制一份。

AOF: 以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录), 只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

AOF持久化功能的实现可以分为命令追加(append)、文件写入、文件同步(sync)三个步骤。

AOF的三种写入策略:

appendfsync always:客户端对redis服务器的每次写操作都写入AOF日志文件。但每次写操作都进行一次磁盘IO

appendfsync everysec:每秒刷新一次缓冲区中的数据到AOF文件 redis默认使用的策略 这种方式最多只会丢失1秒内的数据。

appendfsync no:redis服务器不负责将数据写入到AOF文件中,而是直接交给操作系统去判断

AOF重写原理:Redis 会fork出一条新进程,读取内存中的数据,并重新写到一个临时文件中。并没有读取旧文件。最后替换旧的aof文件。

重写的流程:

1.随着 Redis 不断接受命令,每个写命令都被添加到 AOF 文件,AOF 文件膨胀到需要 rewrite 阈值时又或者接收到客

户端的 bgrewriteaof 命令。

2.fork 出一个子进程进行 rewrite,而父进程继续接受命令,现在的写操作命令都会被额外添加到一个

aof_rewrite_buf_blocks 缓冲中。

3.当子进程 rewrite 结束后,父进程收到子进程退出信号,把 aof_rewrite_buf_blocks 的缓冲添加到 rewrite 后的文件

中,然后切换 AOF 的文件 fd。(此部分过程需要阻塞)

重写的类型:

Rewrite: 在主线程中重写 AOF,会阻塞工作线程,在生产环境中很少使用,处于废弃状态;

bgRewrite: 在后台(子进程)重写 AOF, 不会阻塞工作线程,能正常服务,此方法最常

触发机制:当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。这里的“一倍”和“64M” 可以通过配置文件修改

RDB-AOF混合持久化: 把基于aof重写机制中 增量数据写入AOF文件。也就是说AOF文件的前半段是 RDB格式的全量数据后半段是redis命令格式的增量数据。

redis集群类型

1 主从数据同步(主从复制)

主从模式就是一个主节点和多个一级从节点, 主从模式可以提高 Redis 的整体运行速度,因为使用主从模式就可以实现数据的读写分离,把写操作的请求分发到主节点上,把其他的读操作请求分发到从节点上,这样就减轻了 Redis 主节点的运行压力,并且提高了 Redis 的整体运行速度。
不但如此使用主从模式还实现了 Redis 的高可用,当主服务器宕机之后,可以很迅速的把从节点提升为主节点,为 Redis 服务器的宕机恢复节省了宝贵的时间。
并且主从复制还降低了数据丢失的风险,因为数据是完整拷贝在多台服务器上的,当一个服务器磁盘坏掉之后,可以从其他服务器拿到完整的备份数据。

2 Redis 哨兵模式(Sentinel)

Redis 哨兵模式就是用来监视 Redis 主从服务器的,有了哨兵功能之后,就再也不怕 Redis 主从服务器宕机了。哨兵的工作原理是每个哨兵会以每秒钟 1 次的频率,向已知的主服务器和从服务器,发送一个 PING 命令。如果最后一次有效回复 PING 命令的时间,超过了配置的最大下线时间时,默认是 30s,那么这个实例会被哨兵标记为主观下线。
如果一个主服务器被标记为主观下线,那么正在监视这个主服务器的所有哨兵节点,要以每秒 1 次的频率确认主服务器是否进入了主观下线的状态。如果有足够数量的哨兵证实该主服务器为主观下线,那么这个主服务器被标记为客观下线。此时所有的哨兵会按照规则(协商)自动选出新的主节点服务器,并自动完成主服务器的自动切换功能,而整个过程都是无须人工干预的。

跟主数据库建立连接后会定时执行:

1每隔 10s 向 master 和 slave 发送 info 命令。作用是获取当前数据库信息,比如发现新增从节点时,会建立连接,并加入到监控列表中,当主从数据库的角色发生变化进行信息更新。

2每隔 1s 向所有主从节点和所有哨兵节点发送 ping 命令,作用是监控节点是否存活。

当主节点客观下线时就需要进行主从切换,主从切换的步骤为:

1选出领头哨兵。
2领头哨兵所有的 slave 选出优先级最高的从数据库。优先级可以通过 slave-priority 选项设置。
3如果优先级相同,则从复制的命令偏移量越大(即复制同步数据越多,数据越新),越优先。
如果以上条件都一样,则选择 run ID 较小的从数据库。
选出一个从数据库后,哨兵发送命令升级为主数据库,

3 RedisCluster 的集群模式

Redis Cluster如何做到高可用

通过reshard(重新分片)来实现 假设我们需要向集群中加入一个D节点,而此时集群内已经有A、B、C三个节点了。Redis内部是由redis-trib负责执行的

此时redis-trib会向A、B、C三个节点发送迁移出槽位的请求,同时向D节点发送准备导入槽位的请求,做好准备之后A、B、C这三个源节点就开始执行迁移,将对应的slot所对应的键值对迁移至目标节点D。最后redis-trib会向集群中所有主节点发送槽位的变更信息。

而对于Redis Cluster,某个key它其实并不关心它最终要去到哪个节点,他只关心他最终落到哪个slot上,无论你节点怎么去迁移,最终还是只需要找到对应的slot,然后再找到slot关联的节点,最终就能够找到最终的Redis实例了。

Redis 删除过期键的策略

三种删除策略
定时删除:在设置键的过期时间时,创建一个定时器,当到达键过期时间时通过定时器去删除键。
惰性删除:惰性删除并不是当到达过期时间时去删除,而是每次获取键时,会判断是否过期,如

果过期则删除,并返回空;没过期,就返回键值。
定期删除:每隔一段时间,就对数据库中的键进行检查,如果过期则删除。至于要删除多少什么

时候删除,则是通过具体程序决定。

Redis 的内存淘汰策略 8种

volatile-lru,针对设置了过期时间的key,使用lru算法进行淘汰。
allkeys-lru,针对所有key使用lru算法进行淘汰。
volatile-lfu,针对设置了过期时间的key,使用lfu算法进行淘汰。
allkeys-lfu,针对所有key使用lfu算法进行淘汰。
volatile-random,从所有设置了过期时间的key中使用随机淘汰的方式进行淘汰。
allkeys-random,针对所有的key使用随机淘汰机制进行淘汰。
volatile-ttl,针对设置了过期时间的key,越早过期的越先被淘汰。
noeviction(默认),不会淘汰任何数据,当使用的内存空间超过 maxmemory 值时,再有写请求来时返回错误。

LRU算法(以时间维度去算):

在redis3.0之前 采用随机采集淘汰key 每次随机选出5个key 然后淘汰这5个key最少使用的key

在redis3,0之后 进行了优化Redis中维护一个大小为16的候选池,当第一次随机选取采用数据时,会把数据放入到候选池中,并且候选池中的数据会根据key的空闲时间进行排序。

 回收池满了,并且当前插入的key的空闲时间最小(也就是回收池中的所有key都比当前插入的key的空闲时间都要大),则不作任何操作。
回收池未满,并且插入的位置x没有键,则直接插入即可
回收池未满,且插入的位置x原本已经存在要淘汰的键,则把第x个以后的元素都往后挪一个位置,然后再执行插入操作。
回收池满了,将当前第x个以前的元素往前挪一个位置(实际就是淘汰了),然后执行插入操作。

LRU算法有一个弊端,假如一个key值访问频率很低,但是最近一次被访问到了,那LRU会认为它是热点数据,不会被淘汰。同样,经常被访问的数据,最近一段时间没有被访问,这样会导致这些数据被淘汰掉,导致误判而淘汰掉热点数据,于是在Redis 4.0中,新加了一种LFU算法

LFU算法(以频次维度去算): 根据key最近被访问的频率进行淘汰,比较少访问的key优先淘汰,反之则保留

LFU的原理是使用计数器来对key进行排序,每次key被访问时,计数器会增大

RDB 和 AOF 的优缺点

RDB的优点:

1.体积更小:相同的数据量rdb数据比aof的小,因为rdb是紧凑型文件

2.恢复更快:因为rdb是数据的快照,基本上就是数据的复制,不用重新读取再写入内存

3.性能更高:父进程在保存rdb时候只需要fork一个子进程,无需父进程的进行其他io操作,也保证了服务器的性能。

缺点:

1.故障丢失:因为rdb是全量的,我们一般是使用shell脚本实现30分钟或者1小时或者每天对redis进行rdb备份,(注,也可以是用自带的策略),但是最少也要5分钟进行一次的备份,所以当服务死掉后,最少也要丢失5分钟的数据。

2.耐久性差:相对aof的异步策略来说,因为rdb的复制是全量的,即使是fork的子进程来进行备份,当数据量很大的时候对磁盘的消耗也是不可忽视的,尤其在访问量很高的时候,fork的时间也会延长,导致cpu吃紧,耐久性相对较差。

AOF的优点

1.数据保证:我们可以设置fsync策略,一般默认是everysec,也可以设置每次写入追加,所以即使服务死掉了,咱们也最多丢失一秒数据

2.自动缩小:当aof文件大小到达一定程度的时候,后台会自动的去执行aof重写,此过程不会影响主进程,重写完成后,新的写入将会写到新的aof中,旧的就会被删除掉。但是此条如果拿出来对比rdb的话还是没有必要算成优点,只是官网显示成优点而已。

缺点:

1.性能相对较差:它的操作模式决定了它会对redis的性能有所损耗

2.体积相对更大:尽管是将aof文件重写了,但是毕竟是操作过程和操作结果仍然有很大的差别,体积也毋庸置疑的更大。

3.恢复速度更慢:

使用缓存时,先操作数据库还是先操作缓存

查询:程序先从cache中获取数据,有数据直接返回,没有得到,则去数据库中取数据,成功后更新到缓存中

更新:先把数据存到数据库中,成功后,再让缓存失效

为什么是让缓存删除,而不是更新缓存

因为很多时候,复杂点的缓存的场景,因为缓存有的时候,不简单是数据库中直接取出来的值

删除缓存,而不是更新缓存,就是一个lazy计算的思想,不要每次都重新做复杂的计算,不管它会不会用到,而是让它到需要被使用的时候再重新计算

缓存穿透、缓存击穿、缓存雪崩

缓存穿透:是用户访问的数据既不在缓存当中,也不在数据库中。当高并发或有人利用不存在的Key频繁攻击时,数据库 的压力骤增,甚至崩溃,这就是缓存穿透问题

解决方案: 1缓存空值(null)或默认值、2业务逻辑前置校验、3使用布隆过滤器请求白名单、4用户黑名单限制

缓存雪崩:当缓存中大量热点缓存采用了相同的失效时间,就会导致缓存在某一个时刻同时失效,请求全部转发到数据库,从而导致数据库压力骤增,甚至宕机。从而形成一系列的连锁反应,造成系统崩溃等情况

解决方案: 1构建缓存高可用集群(针对缓存服务故障情况) 2当缓存雪崩发生时,服务熔断、限流、降级等措施保障

  3将key的过期时间后面加上一个随机数(比如随机1-5分钟),让key均匀的失效(常用)

缓存击穿:如果是单个热点key,在不停的扛着大并发,在这个key失效的瞬间,持续的大并发请求就会击破缓存,直接请求到数据库

解决方案: 1 使用用互斥锁,只让一个线程构建缓存,其他线程等待构建缓存执行完毕,重新从缓存中获取数据。单机通过synchronized或lock来处理,分布式环境采用分布式锁。
2 ”提前“使用互斥锁(Mutex Key):在value内部设置一个比缓存(Redis)过期时间短的过期时间标识,当异步线程发现该值快过期时,马上延长内置的这个时间,并重新从数据库加载数据,设置到缓存中去。

更新缓存的几种设计模式

Cache aside常用: 查询:程序先从cache中获取数据,有数据直接返回,没有得到,则去数据库中取 数据,成功后更新到缓存中。

更新:先把数据存到数据库中,成功后,再让缓存失效。

Read/Write Through: 这个模式其实就是将 缓存服务 作为主要的存储,应用的所有读写请 求都是直接与缓存服务打交道,而不管最后端的数据库了,数据库的数据由缓存服务来维护和更新。不过缓存中数据变更的时候是同步去更新数据库的,在应用的眼中只有缓存服务。

Write Behind Caching:在更新数据的时候,只更新缓存,不更新数据库,而缓存会异步地批 量更新数据库。这个设计的好处是让数据的I/O操作可以很快,异步的操作还可以合并对同一个数据的多次操作,性能上是非常可观的。是数据的一致性比较差,还可能会有数据的丢失情况

Redis和MySQL保持数据一致性

设置缓存的过期时间是保证数据保持一致性的关键操作(重点)

先删除缓存
1、如果先删除Redis缓存数据,然而还没有来得及写入MySQL,另一个线程就来读取
2、这个时候发现缓存为空,则去Mysql数据库中读取旧数据写入缓存,此时缓存中为脏数据。
3、然后数据库更新后发现Redis和Mysql出现了数据不一致的问题

后删除缓存
1、如果先写了库,然后再删除缓存,不幸的写库的线程挂了,导致了缓存没有删除
2、这个时候就会直接读取旧缓存,最终也导致了数据不一致情况
3、因为写和读是并发的,没法保证顺序,就会出现缓存和数据库的数据不一致的问题

解决方案:

延时双删策略:(设置缓存过期时间是关键点)

1、 先删除缓存 2、再写数据库 3、休眠500毫秒 4、再次删除缓存

缺点:
结合双删策略+缓存超时设置,这样最差的情况就是:
1、在缓存过期时间内发生数据存在不一致
2、同时又增加了写请求的耗时。

异步更新缓存策略(基于Mysql binlog的同步机制)

1、涉及到更新的数据操作,利用Mysql binlog 进行增量订阅消费
2、将消息发送到消息队列
3、通过消息队列消费将增量数据更新到Redis上

Redis更新过程:一种是全量(所有数据一次性写入) 一种是增量(实时更新)

Redis五大基本数据类型

1.字符串
2.列表List
3.集合Set
4.哈希Hash
5.Zset

Redis 与 memcached 相比有哪些优势?

1、memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类型
2、redis 的速度比 memcached 快很多 redis 的速度比 memcached 快很多
3、redis 可以持久化其数据 redis 可以持久化其数据

Redis 如何做内存优化?

   尽可能使用散列表(hash),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。
比如你的 web 系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的 key,而是应该把这个用户的所有信息存储到一张散列表里面。


Redis 回收进程如何工作的?

     一个客户端运行了新的命令,添加了新的数据。Redis检查内存使用情况,如果大于 maxmemory 的限制,则根据设定好的策略进行回收。一个新的命令被执行,等等。所以我们不断地穿越内存限制的边界,通过不断达到边界然后不断地回收回到边界以下。
如果一个命令的结果导致大量内存被使用(例如很大的集合的交集保存到一个新的键),不用多久内存限制就会被这个内存使用量超越。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。 Redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。 Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。   本课程主要讲解以下内容:1. Redis的基本使用2. Redis数据库的数据类型3. Redis数据库数据管理4. Redis的主从复制5. Redis数据库的持久性6. Redis的高可靠性和集群7. Redis的优化和性能测试8. Redis服务器的维护和管理9. Redis服务器的常见问题排错 

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值