一、 redis的简介与安装

引用:https://www.cnblogs.com/ysocean/tag/Redis%E8%AF%A6%E8%A7%A3/

二、 redis的配置文件介绍

引用:https://www.cnblogs.com/ysocean/tag/Redis%E8%AF%A6%E8%A7%A3/

三、redis的五大数据类型详细用法

引用:https://www.cnblogs.com/ysocean/tag/Redis%E8%AF%A6%E8%A7%A3/

四、redis的底层数据结构

引用:https://www.cnblogs.com/ysocean/tag/Redis%E8%AF%A6%E8%A7%A3/

五、 redis的五大数据类型实现原理

引用:https://www.cnblogs.com/ysocean/tag/Redis%E8%AF%A6%E8%A7%A3/

六、 持久化

RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持
久化过程分为手动触发和自动触发。

配置引用: https://www.cnblogs.com/ysocean/tag/Redis%E8%AF%A6%E8%A7%A3/

RDB的优缺点
优点:

  1. RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每6小时执行bgsave备份,并把RDB文件拷贝到远程机器或者文件系统中(如hdfs),用于灾难恢复。
  2. Redis加载RDB恢复数据远远快于AOF的方式。

缺点:

  1. RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运

行都要执行fork操作创建子进程,属于重量级操作,频繁执行成本过高。

  1. RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题。

针对RDB不适合实时持久化的问题,Redis提供了AOF持久化方式来解决。

AOF持久化

AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。
AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式

配置引用: https://www.cnblogs.com/ysocean/tag/Redis%E8%AF%A6%E8%A7%A3/

AOF的工作流程如下图:

1)所有的写入命令会追加到aof_buf(缓冲区)中。
2)AOF缓冲区根据对应的策略向硬盘做同步操作。
3)随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的。
4)当Redis服务器重启时,可以加载AOF文件进行数据恢复。

更详细的工作原理可以参考书籍【Redis开发与运维(付磊)】
或者参考这篇文章:
https://redisbook.readthedocs...

温馨提示
场景:AOF文件可能存在结尾不完整的情况,比如机器突然掉电导致AOF尾部文件命令写入不全。

解决方法:

  1. 对于错误格式的AOF文件,先进行备份,然后采用redis-check-aof --fix命令进行修复,修复后使用diff-u对比数据的差异,找出丢失的数据,有些可以人工修改补全。
  2. Redis为我们提供了aof-load-truncated配置来兼容这种情况,默认开启。加载AOF时,当遇到此问题时会忽略并继续启动,同时打印如下警告日志:
# !!! Warning: short read while loading the AOF file !!!
# !!! Truncating the AOF at offset 397856725 !!!
# AOF loaded anyway because aof-load-truncated is enabled

持久化的优化

Redis持久化功能一直是影响Redis性能的高发地。主要有以下方面

1. fork操作
起因:对于高流量的Redis实例OPS可达5万以上,如果fork操作耗时在秒级别将拖慢Redis几万条命令执行,对线上应用延迟影响非常明显。正常情况下fork耗时应该是每GB消耗20毫秒左右。可以在info stats统计中查latest_fork_usec指标获取最近一次fork操作耗时,单位微秒。

优化
1)优先使用物理机或者高效支持fork操作的虚拟化技术,避免使用Xen。
2)控制Redis实例最大可用内存,fork耗时跟内存量成正比,线上建议每个Redis实例内存控制在10GB以内。
3)合理配置Linux内存分配策略,避免物理内存不足导致fork失败。
4)降低fork操作的频率,如适度放宽AOF自动触发时机,避免不必要的全量复制等。

2. CPU
CPU开销分析。子进程负责把进程内的数据分批写入文件,这个过程属于CPU密集操作,通常子进程对单核CPU利用率接近90%。
CPU消耗优化。Redis是CPU密集型服务,不要做绑定单核CPU操作。由于子进程非常消耗CPU,会和父进程产生单核资源竞争。
不要和其他CPU密集型服务部署在一起,造成CPU过度竞争。如果部署多个Redis实例,尽量保证同一时刻只有一个子进程执行重写工作。

3. 内存
内存消耗优化:
1)同CPU优化一样,如果部署多个Redis实例,尽量保证同一时刻只有一个子进程在工作。
2)避免在大量写入时做子进程重写操作,这样将导致父进程维护大量页副本,造成内存消耗。

4. 硬盘
优化方法如下:
a)不要和其他高硬盘负载的服务部署在一起。如:存储服务、消息队列服务等。
b)AOF重写时会消耗大量硬盘IO,可以开启配置no-appendfsync-on-rewrite,默认关闭。表示在AOF重写期间不做fsync操作。
c)当开启AOF功能的Redis用于高流量写入场景时,如果使用普通机械磁盘,写入吞吐一般在100MB/s左右,这时Redis实例的瓶颈主要在AOF同步硬盘上。
d)对于单机配置多个Redis实例的情况,可以配置不同实例分盘存储AOF文件,分摊硬盘写入压力。

注:配置no-appendfsync-on-rewrite=yes时,在极端情况下可能丢失整个AOF重写期间的数据,需要根据数据安全性决定是否配置。

5.AOF追加阻塞
当开启AOF持久化时,常用的同步硬盘的策略是everysec,用于平衡性能和数据安全性。对于这种方式,Redis使用另一条线程每秒执行fsync同步硬盘。当系统硬盘资源繁忙时,会造成Redis主线程阻塞,

阻塞流程分析:
1)主线程负责写入AOF缓冲区。
2)AOF线程负责每秒执行一次同步磁盘操作,并记录最近一次同步时间。
3)主线程负责对比上次AOF同步时间:如果距上次同步成功时间在2秒内,主线程直接返回。如果距上次同步成功时间超过2秒,主线程将会阻塞,直到同步操作完成。

优化AOF追加阻塞问题主要是优化系统硬盘负载,优化方法参考第4点

七、事务

为了保证多条命令组合的原子性,Redis提供了简单的事务功能以及集成Lua脚本来解决这个问题。简单介绍Redis中事务的使用方法以及它的局限性。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> sadd user:a:follow user:b
QUEUED
127.0.0.1:6379> zadd user:b:fans 1 user:a
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> sismember user:a:follow user:b
(integer) 1

Redis提供了简单的事务功能,**将一组需要一起执行的命令放到multi和
exec两个命令之间**。

multi命令代表事务开始
exec命令代表事务结束
它们之间的命令是原子顺序执行的。
不支持事务中的回滚特性

Lua脚本

基本语法教程可参考下面这个网址:
https://www.runoob.com/lua/lu...

在Redis中执行Lua脚本有两种方法:eval和evalsha。

八、发布订阅

Redis提供了基于“发布/订阅”模式的消息机制,此种模式下,消息发布
者和订阅者不进行直接通信,发布者客户端向指定的频道(channel)发布消息,订阅该频道的每个客户端都可以收到该消息。

  1. 发布消息
publish channel:sports "Tim won the championship"
  1. 订阅消息
subscribe channel:sports

有关订阅命令有两点需要注意

  • 客户端在执行订阅命令之后进入了订阅状态,只能接收subscribe、

psubscribe、unsubscribe、punsubscribe的四个命令。

  • 新开启的订阅客户端,无法收到该频道之前的消息,因为Redis不会对

发布的消息进行持久化。

Redis发布订阅与成熟MQ的比较

(1)MQ支持多种消息协议,包括AMQP,MQTT,Stomp等,并且支持JMS规范,但Redis没有提供对这些协议的支持; 
(2)MQ提供持久化功能,但Redis无法对消息持久化存储,一旦消息被发送,如果没有订阅者接收,那么消息就会丢失; 
(3)MQ提供了消息传输保障,当客户端连接超时或事务回滚等情况发生时,消息会被重新发送给客户端,Redis没有提供消息传输保障。

总之,MQ所提供的功能远比Redis发布订阅要复杂,毕竟Redis不是专门做发布订阅的,但是如果系统中已经有了Redis,并且需要基本的发布订阅功能,就没有必要再安装MQ了,因为可能MQ提供的功能大部分都用不到,而且你可以容忍redis发布订阅的缺点的话,可以考虑用它。

九、主从复制及哨兵模式

配置引用:https://www.cnblogs.com/ysocean/tag/Redis%E8%AF%A6%E8%A7%A3/

主节点Master 只有一个,一旦主节点挂掉之后,从节点没法担起主节点的任务,那么整个系统也无法运行。如果主节点挂掉之后,从节点能够自动变成主节点,那么问题就解决了,于是哨兵模式诞生了。

哨兵模式就是不时地监控redis是否按照预期良好地运行(至少是保证主节点是存在的),若一台主机出现问题时,哨兵会自动将该主机下的某一个从机设置为新的主机,并让其他从机和新主机建立主从关系。

十、redis雪崩、击穿、穿透

https://www.toutiao.com/i6755313319684342276/?tt_from=weixin&utm_campaign=client_share&wxshare_count=1&from=singlemessage&timestamp=1572913492&app=news_article&utm_source=weixin&utm_medium=toutiao_android&req_id=2019110508245201000804313323AE21C8&group_id=6755313319684342276

1、redis雪崩效应

由于redis设置失效时间,当所有key在同一时间失效,并发直接打入DB,导致DB崩溃。

举个简单的例子:如果所有首页的Key失效时间都是12小时,中午12点刷新的,我零点有个秒杀活动大量用户涌入,假设当时每秒 6000 个请求,本来缓存在可以扛住每秒 5000 个请求,但是缓存当时所有的Key都失效了。此时 1 秒 6000 个请求全部落数据库,数据库必然扛不住,它会报一下警,真实情况可能DBA都没反应过来就直接挂了。此时,如果没用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。这就是我理解的缓存雪崩。

我刻意看了下我做过的项目感觉再吊的都不允许这么大的QPS直接打DB去,不过没慢SQL加上分库,大表分表可能还还算能顶,但是跟用了Redis的差距还是很大。

解决:

处理缓存雪崩简单,在批量往Redis存数据的时候,把每个Key的失效时间都加个随机值就好了,这样可以保证数据不会在同一时间大面积失效,我相信,Redis这点流量还是顶得住的。

如果Redis是集群部署,将热点数据均匀分布在不同的Redis库中也能避免全部失效的问题,不过本渣我在生产环境中操作集群的时候,单个服务都是对应的单个Redis分片,是为了方便数据的管理,但是也同样有了可能会失效这样的弊端,失效时间随机是个好策略。

或者设置热点数据永远不过期,有更新操作就更新缓存就好了(比如运维更新了首页商品,那你刷下缓存就完事了,不要设置过期时间),电商首页的数据也可以用这个操作,保险。

2、缓存穿透

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,我们数据库的 id 都是1开始自增上去的,如发起为id值为 -1 的数据或 id 为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大,严重会击垮数据库。

解决:

接口层增加校验,比如用户鉴权校验,参数做校验,不合法的参数直接代码Return

3、缓存击穿

这个跟缓存雪崩有点像,但是又有一点不一样,缓存雪崩是因为大面积的缓存失效,打崩了DB,而缓存击穿不同的是缓存击穿是指一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞。

解决:

从缓存取不到的数据,在数据库中也没有取到,这时也可以将对应Key的Value对写为null、位置错误、稍后重试这样的值具体取啥问产品,或者看具体的场景,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。

这样可以防止攻击用户反复用同一个id暴力攻击,但是我们要知道正常用户是不会在单秒内发起这么多次请求的,那网关层Nginx本渣我也记得有配置项,可以让运维大大对单个IP每秒访问次数超出阈值的IP都拉黑。

总结:

  • 事前:Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。
  • 事中:本地 ehcache 缓存 + Hystrix 限流+降级,避免MySQL 被打死。
  • 事后:Redis 持久化 RDB+AOF,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。

redis详解及应用(雪崩、击穿、穿透)的更多相关文章

  1. Redis详解(八)——企业级解决方案

    Redis详解(八)--企业级解决方案 缓存预热 缓存预热就是系统上线后,提前将相关的缓存数据直接加载到缓存系统.避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓 ...

  2. 基础拾遗------redis详解

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  3. Spring Data操作Redis详解

    Spring Data操作Redis详解 Redis是一种NOSQL数据库,Key-Value形式对数据进行存储,其中数据可以以内存形式存在,也可以持久化到文件系统.Spring data对Redis ...

  4. .Net使用Redis详解之ServiceStack.Redis(七) 转载https://www.cnblogs.com/knowledgesea/p/5032101.html

    .Net使用Redis详解之ServiceStack.Redis(七)   序言 本篇从.Net如何接入Reis开始,直至.Net对Redis的各种操作,为了方便学习与做为文档的查看,我做一遍注释展现 ...

  5. Redis详解入门篇

    Redis详解入门篇 [本教程目录] 1.redis是什么2.redis的作者3.谁在使用redis4.学会安装redis5.学会启动redis6.使用redis客户端7.redis数据结构 – 简介 ...

  6. .Net使用Redis详解之ServiceStack.Redis(7)

    Net使用Redis详解之ServiceStack.Redis(七) 序言 本篇从.Net如何接入Reis开始,直至.Net对Redis的各种操作,为了方便学习与做为文档的查看,我做一遍注释展现,其中 ...

  7. Redis详解入门篇(转载)

    Redis详解入门篇(转载) [本教程目录] 1.redis是什么2.redis的作者3.谁在使用redis4.学会安装redis5.学会启动redis6.使用redis客户端7.redis数据结构 ...

  8. Redis详解(二)——AOF

    Redis详解(二)--AOF 前言 RDB 持久化存在一个缺点是一定时间内做一次备份,如果redis意外down掉的话,就会丢失最后一次快照后的所有修改(数据有丢失).对于数据完整性要求很严格的需求 ...

  9. Redis详解(一)——RDB

    Redis详解(一)--RDB 前言 由于 Redis 是一个内存数据库,所谓内存数据库,就是将数据库中的内容保存在内存中,这与传统的MySQL,Oracle等关系型数据库直接将内容保存到硬盘中相比, ...

  10. Redis详解(四)——删除策略

    Redis详解(四)--删除策略 Redis中的数据特征 Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令来获取其状态,当 key 不存在时,返回 -2 . 当 k ...

随机推荐

  1. (转)通过反编译深入理解Java String及intern

    原文链接:https://www.cnblogs.com/paddix/p/5326863.html 一.字符串问题 字符串在我们平时的编码工作中用的非常多,并且用起来非常简单,所以很少有人对其做特别 ...

  2. java并发编程:锁的相关概念介绍

    理解同步,最好先把java中锁相关的概念弄清楚,有助于我们更好的去理解.学习同步.java语言中与锁有关的几个概念主要是:可重入锁.读写锁.可中断锁.公平锁 一.可重入锁 synchronized和R ...

  3. navicat for mysql 12 的破解安装和基本操作

    需要安装Navicat软件 可以复制百度云链接,若失效,请联系我,我会尽快回复 将链接中的破解文件复制到软件安装的位置即完成破解 链接:https://pan.baidu.com/s/1sIkjsd3 ...

  4. 服务命令(systemctl的使用)

    常用的service与systemctl命令的对比 应用举例: ●start:开启服务 ●stop:停止服务 ●status:参数来查看服务运行情况 ●restart:重新加载服务 应用举例·: #启 ...

  5. c++ 实现https网页上的图片爬取

    一.主要的原理 我们通过发送一个http请求,获得目标网页的html源代码,然后通过正则表达式获取到图片的URL,把该网页的所有的图片都保存到一个文件夹,这就是整个软件的流程. 二.具体的实践 现在很 ...

  6. ASP.NET c# 实验日记(1)

    第一次写有一些紧张,以前学过html,c语言,vb,c#等语言.也自己翻过有关javascript的书,现在的目的是怎么把学习经验写的更具结构化和条理化,大佬勿喷. 在一个集成开发平台里第一步就是新建 ...

  7. 使用Pechkin与CPechkin生成PDF

    1. Pechkin     从NuGet程序管理器中获得Pechkin,代码示例如下:             GlobalConfig config = new GlobalConfig();   ...

  8. 【vuex状态管理】使用步骤

    https://www.jianshu.com/p/33e5fb3f3a86 https://segmentfault.com/a/1190000015782272 写在前面: 1.创建一个store ...

  9. 小程序UI设计(1)-布局

    工欲善其事必先利其器.下面为大家介绍一款工具软件,如何做到轻松布局. 工具简介:小程序layout设计工具,可视化方式进行小程序UI设计.通过鼠标拖拽组件方式进行UI布局.工具提供符合微信视觉统一的模 ...

  10. 微信小程序 canIUse

    wx.canIUse(); 微信文档中定义在API中,可以理解为一个函数. 返回值: true 或者 false 示例: // 在JS文件的函数中进行使用 console.log(wx.canIUse ...