一、 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,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。

最新文章

  1. Flyout中ComboBox失效
  2. iScroll4下表单元素聚焦及键盘的异常问题
  3. Android MimeType的用法和几种类型
  4. Java zip and unzip demo
  5. Android sdk 镜像服务器资源
  6. air 移动开发配置文件详解
  7. Java程序员的10道XML面试题
  8. codeforces 592B The Monster and the Squirrel
  9. wpf 9张图片的连连看
  10. 201521123077 《Java程序设计》第6周学习总结
  11. kali下的webshell工具-Weevely
  12. xlrd模块;xlwt模块使用,smtp发送邮件
  13. [游戏开发日志]Windows下Cocos2d-x 3.14环境搭建
  14. [原]Jenkins(十一)---jenkins使用管理员admin创建用户和分配权限
  15. nodejs发送邮件
  16. Seletct2
  17. Codeforces 978E:Bus Video System
  18. win10更改hosts文件
  19. ajax请求是参数问题
  20. eclipse 中 import sun.misc.BASE64Decoder; 报错

热门文章

  1. 2019.9.27PHP基础
  2. 三,k8s集群的应用入门
  3. **JAVA参数传递方式 (按值传递与引用传递区别)
  4. Memcached安装部署
  5. Linux设备驱动学习笔记
  6. mysql之单表条件查询
  7. Session中的方法
  8. fetch 写法
  9. Springboot设置session超时时间
  10. StreamWriter、StreamReader