09 06 2022

Reids数据库基础知识


一、Redis高级

            1.1 通用命令

            1.1.1、key通用指令

            key特征:key是一个字符串,通过key获取redis中保存的数据

            key应该设计哪些操作?

            对于key自身的状态相关操作,例如:删除,判定存在,获取类型等

            对于key有效性相关操作,例如:有效期设定,判定是否有效,有效状态的切换等

            对于key快速查询操作,例如:按指定策略查询key

            

            key基本操作:

            a、删除指定key:del  key

            image.png

            b、获取key是否存在:exists  key 

            image.png

            c、获取key的类型:type  key

            image.png


            key扩展操作(时效性):

            a、为指定key设置有效期:expire  key  seconds

            image.png

            b、为指定key设置有效期:pexpire  key  milliseconds

            image.png

            c、为指定key设置有效期:expireat   key  timestamp

            image.png

            d、为指定key设置有效期:pexpireat   key  milliseconds-timestamp

            e、获取key的有效时间:ttl  key

            image.png

            ttl获取key过期时间,如果一个key不存在,则返回-2;如果一个key存在,则返回-1;如果一个设置了有效期,则返回剩余有效时间

            f、获取key的有效时间:pttl  key

            image.png

            g、切换key从时效性转换为永久性:persist  key

            image.png


            key通用操作:

            a、查询key:keys  pattern(匹配的语法格式)

            image.png

            image.png

            image.png

            image.png


            key其他操作:

            a、为key改名:rename  key  newkey

            image.png

            b、如果key不存在则为key改名:renamenx  key  newkey

            image.png

            image.png

            c、对所有key排序,只是排了序,没有动原来数据:sort  key  

            image.png


            1.2 数据库通用指令

            1.2.1、看如下问题

            image.png

            1.2.2、db基本操作

            a、切换数据库:select  index

            image.png

            b、控制台打印:echo   xxx

            image.png

            c、测试客户端与服务端连通性:ping

            image.png

            d、移动数据:move  key  db

            image.png

            数据清除操作(谨慎、小心操作):

            e、清除当前数据库:flushdb

            f、清除所有数据库:flushall  不要用这个指令,0-15号库数据全部干掉...

            g、查看数据容量:dbsize

            image.png


二、Redis持久化

            2.1 意外的断电

            image.png

            2.2 自动备份

            image.png

            2.3 什么是持久化

            利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化

            2.4 为什么要持久化

            防止数据的意外丢失,确保数据的安全性

            2.5 持久化过程保存什么

            image.png

            2.6 持久化方案一 ,RDB启动方式--save指令

            image.png

            持久化的命令:save

            作用:手动执行一次,保存一次

            image.png

            2.6.1 RDB相关配置

            RDB启动方式----save指令相关配置

            image.png

            1、设置dbfilename

            image.png

            2、设置rdbcompression 值为yes

            image.png


            2.6.2 数据恢复过程演示

            image.png

            杀掉进程后再启动,上图的3420进程,redis又重新运行

            image.png

            数据已经恢复

            image.png

            2.6.3 save指令工作原理

            1、假如4个指令都要执行,并且按照客户端1--4的顺序先后到达并执行

            image.png

            2、到达以后假如是下面的指令排序

            image.png

            3、指令执行

            image.png

            4、save指令有可能造成阻塞,拉低服务器性能,线上环境不建议使用save指令

            image.png

            

            2.7 持久化方案二 ,RDB启动方式--bgsave指令

            数据量过大,单线程方式造成效率过低如何处理?

            image.png

            2.7.1 持久化命令

            指令:bgsave

            作用:手动启动后台保存操作,但不是立即执行

            操作:

            image.png

            执行bgsave命令前

            image.png

            执行bgsave命令后,文件大小已经变了

            image.png

            查看文件内容,已经增加了addr值chengdu

            image.png

            2.7.2 bgsave指令工作原理

            1、下达指令

            image.png

            2、调用linux的fork函数,生成子进程,由子进程去完成

            image.png

            在日志文件去查看这个过程

            image.png

            注意:bgsave命令是针对save命令阻塞问题做的优化,save命令是立马执行,并且加入到任务执行序列中,bgsave采用的是fork创建的子进程来完成的这个过程;redis内部所有涉及到RDB操作都采用bgsave方式,save命令可以放弃使用

            2.7.3 bgsave指令相关配置

            image.png

            image.png


            2.8 持久化方案三 ,RDB启动方式--自动执行

            image.png

            2.8.1 配置

            指令配置:save  second  changes

            作用:满足限定时间范围内key的变化数量达到指定数量即进行持久化

            参数:second -- 监控时间范围    changes -- 监控key的变化

            位置:在conf文件中进行配置,不要乱设置,设置不合理也是灾难性的;second和changes一般遵循前面大后面小,前面小后面大

            image.png

            范例:

            image.png

            注意:只要是在设定的时间范围内,满足条件的key数量发生变化(包括添加、修改),就会自动保存数据

            2.8.2 RDB启动方式save配置原理

            image.png

            2.9 RDB三种启动方式对比

            image.png

            image.pngimage.png

            2.10 RDB特殊启动方式

            image.png

            2.11 RDB的优点与缺点

            image.png


            2.12 AOF简介

            RDB的弊端:

            1、存储数据量较大,效率较低,基于快照的思想,每次读写都是全部数据,当数据量巨大时,侠侣非常低

            2、大数据量下的IO性能较低

            3、基于fork创建子进程,内存产生额外消耗

            4、宕机带来的数据丢失,快照思想存储是基于某个时间点的数据,无法做到即时的数据存储

            解决思路:

            1、不写全数据,仅记录部分数据

            2、改记录数据为记录操作过程

            3、对所有操作均进行记录,排除丢失数据的风险

            AOF概念:

            1、AOF(append  only  file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的,与RDB相比,可以简单的描述为:改记录数据为记录数据产生的过程

            2、AOF主要作用是解决了数据持久化的实时性,目前已经是redis持久化的主流方式,优先使用AOF方式

            

            2.13 AOF写数据过程

            image.png

            2.14 AOF写数据的三种策略

            image.png

            2.15 AOF功能开启

            配置:appendonly   yes|no,默认是no

            作用:是否开启AOF持久化功能,默认为不开启状态

            image.png

            配置AOF策略:appendfsync   always | everysec | no

            作用:AOF写数据策略

            image.png

            案例演示:

            image.png

            image.png

            image.png

            AOF其它相关配置:

            image.png

            2.16 AOF写数据遇到的问题

            image.png

            AOF重写:

            随着命令不断写入AOF,文件会越来越大,为了解决这个问题,redis引入了AOF重写机制压缩文件体积。AOF文件重写是将redis进程内的数据转化为写命令同步到新AOF文件的过程。简单说就是将对同一个数据的若干个命令执行结果转化成最终结果数据对应的指令进行记录

            AOF重写的作用:

            降低磁盘占用量,提高磁盘利用率

            提高持久化效率,降低持久化写时间,提高IO性能

            降低数据恢复用时,提高数据恢复效率

            AOF重写的规则:

            image.png

            AOF重写的方式:

            1、手动重写:bgrewriteaof 

            案例演示:

            第一步、

            image.png

            第二步、

            image.png

            第三步、重写

            image.png

            第四步、

            image.png

            

            AOF手动重写---bgrewriteaof指令工作原理

            image.png

            2、自动重写:

            auto-aof-rewrite-min-size   size

            auto-aof-rewrite-percentage   percentage  

            image.png

            注意:info指令,查看当前redis运行属性值!!!

            AOF工作流程:

            image.png

            基于everysec开启重写

            image.png

            2.17 RDB和AOF的区别

            image.png

            image.png

            2.18 持久化应用场景

            image.png

            

三、Redis事务

            3.1 事务简介

            redis事务就是一个命令执行的队列,将一系列预定义命令包装成一个整体(一个队列)。当执行时,一次性按照添加顺序依次执行,中间不会被打断或者干扰;在开发中一般不使用redis事务,作为一个了解就好。

            一个队列,一次性、顺序性、排他性的执行一系列命令

            image.png

            3.2 事务的基本操作

            开启事务:multi 

            作用:设定事务的开始位置,此指令执行后,后续的所有指令均加入到事务中

            执行事务:exec

            作用:设定事务的结束位置,同时执行事务。与multi成对出现,成对使用

            image.png

            注意:加入事务的命令暂时进入到任务队列中,并没有立即执行,只有执行exec命令才开始执行

            3.3 事务定义过程中发现问题了怎么处理?

            取消事务:discard

            作用:终止当前事物的定义,发生在multi命令之后,exec命令之前

            image.png

            3.4 事务的工作流程

            set指令:

            image.png

            multi开启事务:

            image.png

            来一个set指令加入队列:

            image.png

            再来一个del指令加入队列:

            image.png

            来一个exec指令:执行了exec指令以后,队列消失

            image.png

            来一个discard指令:直接销毁掉队列里面的指令集

            image.png

            3.5 事务定义过程中,命令格式输入错误怎么办

            image.png

            image.png

            

            image.png

            image.png

            3.6 事务-锁

            一、业务场景一介绍

            image.png

            解决方案:

            对key添加监视,在执行exec前如果key发生了变化,终止事务执行

            watch   key1   [key2,...]

            image.png

            注意:开启watch监控要在开启事务之前,开启watch指令监控的东西如果发生改变,定义的事务将不会执行 ,返回一个nil

            image.png

            image.png

            取消对key的所有监视:

            unwatch

            image.png

            image.png


            二、业务场景二介绍

            image.png

            基于特定条件的事务执行--分布式锁:

            1、使用setnx设置一个公共锁,不存在key才能设置成功,存在则不能设置也不能替换   setnx   lock-key   value

            image.png

            利用setnx命令返回值的特征,有值则返回设置失败,无值则返回设置成功

            对于返回设置成功的,拥有控制权,进行下一步的具体业务操作;对于返回设置失败的,不具有控制权,排队或等待

            image.png

            2、操作完毕使用del释放锁

            image.png


            3.7 事务-死锁

            一、业务场景一介绍

            image.png

            解决方案:

            使用expire为锁key添加时间限定,到时不释放,放弃锁

            expire   lock-key   second

            image.png


            image.png

            image.png

            pexpire   lock-key   milliseconds

            

            由于操作通常都是微妙或毫秒级,因此该锁定时间不宜设置过大,具体时间需要业务测试后确定

            image.png

            注意这个参数选择!!!

            image.png


四、删除策略

            4.1 redis数据特征

            redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过ttl指令获取其状态

            image.png

            image.png

            image.png


            4.2 redis数据删除策略

            数据删除策略的目标:

            在内存占用与CPU占用之间寻找一种平衡,顾此失彼都会造成redis性能下降,甚至引发服务器宕机或者是内存泄漏

            

            数据删除的方式:

            定时删除:

            image.png

            惰性删除:

            image.png

            定期删除:

            image.png

            image.png

            image.png

            4.3 redis逐出算法

            image.png

            image.png

            image.png

            image.png

            image.png

            4.4 服务器配置

            服务器端基础配置:

            image.png

            日志配置:

            image.png

            注意:日志级别开发期设置为verbose,生产环境中设置为notice,简化日志输出量,降低写日志IO频度

            客户端配置:

            image.png

            多服务器快捷配置:

            image.png

五、高级数据类型

            5.1 搁置

            

六、主从复制

            6.1 互联网“三高”架构

            高并发

            高性能

            高可用

            image.png

            image.png

            多台服务器连接方案:

            image.png

            image.png

            主从复制:

            image.png

            高可用集群:

            image.png

            主从复制的作用:

            image.png

            主从复制工作流程:

            image.png

            1、建立连接工作流程

            image.png

            2、实现连接

            方式一、客户端发送命令

            image.png

            master端

            image.png

            image.png

            image.png

            image.png

            image.png


            slave端

            image.png

            image.png

            image.png

            image.png

            image.png


            方式二、启动服务器参数

            image.png

            master端:

            image.png

            

            slave端:

            image.png

            image.png


            方式三、服务器配置

            image.png

            master端:

            image.png

            

            slave端:

            image.png

            image.png

            image.png

            image.png

            image.png

            3、主从断开连接

            image.png

            master端:

            image.png


            slave端:先执行下面命令

            image.png

            image.png

            4、授权访问

            image.png

七、哨兵

            7.1 待完善


八、集群

            8.1 待完善


九、企业级解决方案

            9.1 缓存预热

            宕机:服务器启动后迅速宕机

            问题排查:

            1. 请求数量较高 

            2. 主从之间数据吞吐量较大,数据同步操作频度较高

            解决方案:

            前置准备工作:

            1. 日常例行统计数据访问记录,统计访问频度较高的热点数据

            2. 利用LRU的数据删除策略,构建数据留存队列,列如:storm与kafka配合

            准备工作:

            3. 将统计结果中的数据进行分类,根据级别,redis优先加载级别较高的热点数据

            4. 利用分布式多服务器同时进行数据读取,提速数据加载过程

            实施:

            1. 使用脚本程序固定触发数据预热过程

            2. 如果条件允许,使用了CDN(内容分发网络)效果会更好

            总结:缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统,避免用户在请求的时候先请求数据库然后再缓存的问题,用户直接查询事先预热的缓存数据!

            

            9.2 缓存雪崩

            数据库服务器崩溃(1)

            1. 系统平稳运行过程中,忽然数据库连接量激增

            2. 应用服务器无法及时处理请求

            3. 对外响应408超时,或者响应500错误页面

            4. 用户得不到反馈数据,反复刷新页面

            5. 请求量越来越大,数据库崩溃

            6. 应用服务器崩溃

            7. 重启应用服务器无效

            8. redis服务器开始崩溃

            9. redis集群崩溃

            10. 重启数据库后再次被瞬间流量放倒

            问题排查:

            1. 在一个较短的时间内“缓存中较多的key集中过期”

            2. 在此周期内请求访问过期数据,redis未命中,redis向数据库获取数据

            3. 数据库同时接收到大量请求无法及时处理

            4. redis大量请求被积压,开始出现超时现象

            5. 数据库流量增大,数据库崩溃

            6. 重启后依然面对缓存中无数据可用

            7. redis服务器资源被严重占用,redis服务器崩溃

            8. redis集群呈现崩塌,集群瓦解

            9. 应用服务器无法及时得到数据响应请求,客户端用户继续刷新,来自客户端的请求数量越来越多,应用服务器崩溃

            10. 应用服务器、redis、数据库全部重启,效果依然不理想(重启只是给自己一个心理安慰罢了,redis缓存依然没有数据,必崩)

            分析问题

            1. 短时间内

            2. 大量key集中过期

            解决方案(道):

            1. 更多的页面静态化处理 (原因是页面过多的数据从缓存取)

            2. 构建多级缓存结构:Nginx缓存 + redis缓存 + ehcache缓存(纯Java的进程内缓存框架

            3. 检测mysql严重耗时业务进行优化,对数据库的瓶颈排查:列如超时查询、耗时较高事务等

            4. 灾难预警机制,监控redis服务器性能指标

                CPU占用,CPU使用率 (雪崩的典型现象CPU比较忙)

                内存容量

                查询平均响应时间

                线程数

            5. 限流、降级

            短时间内牺牲一些客户体验,限制一部分请求访问,降低应用服务器压力,待业务低速运转后再逐步放开访问

            解决方法(术):

            1. LRU与LFU切换

            2. 数据有效期策略调整

                根据业务数据有效期进行错峰,假如A类90分钟,B类80分钟,C类70分钟

                过期时间使用固定时间 + 随机值形式,稀释集中到期的key的数量,比如A类某某key90.1,A类另一key90.5等

            3. 超热数据使用永久key(区分超热普通热点)

            4. 定期维护(自动 + 人工)

                对即将过期数据做访问量分析,确认是否延时,配合访问量统计,做热点数据延时

            5. 加锁(慎用)

                拿到锁的干活,拿不到锁的就拿不到数据

            总结:

            1. 不管是道的层面还是术的层面,都要去做监控预防,道的话就是平时该怎么去设计,术的话就是出现问题要知道该去动哪些东西

            2. 缓存雪崩就是瞬间过期数据量太大,导致对数据库服务器造成压力。如果能有效避免过期时间集中,可以有效解决雪崩现象的出现(约40%),配合其他策略一起使用,并监控服务器的运行数据,根据运行记录做快速调整

            image.png

            

            9.3 缓存击穿

            数据库服务器崩溃(2)

            1. 系统平稳运行过程中

            2. 数据库连接量瞬间激增

            3. redis服务器内key无大量过期

            4. redis内存平稳,无波动

            5. redis服务器CPU正常

            6. 数据库崩溃


            问题排查:

            1. redis中某个key过期,该key访问量巨大

            2. 多个数据请求从服务器直接压到redis后,均未命中

            3. redis在短时间内发起了大量对数据库中同一数据的请求

            问题分析:

            1. 单个key高热数据

            2. key过期
            解决方案(术):

            1. 预先设定:

                以电商为例,每个商家根据店铺等级,指定若干款主打产品,在购物节期间,加大此类信息key的时长

            注意:不仅仅是购物街当天,以及后续若干天,访问峰值呈现主键降低的趋势

            2. 现场调整:

                监控访问量,对自然流量激增的数据延长过期时间,或者设置为永久性key

            3. 后台刷新数据:

                启动定时任务,高峰期来临之前,刷新数据有效期,确保不丢失

            4. 二级缓存:

                设置不同的失效时间,保障不会同时失效就行 (还是尽量分类设置过期时间,同类的商品key过期时间都加随机值浮动)

            5. 加锁:

                分布式锁,防止被击穿,但是要注意也是性能瓶颈,慎重! (不太推荐,实在没有办法的时候考虑使用)

            总结:

            缓存击穿就是单个高热数据过期的瞬间,数据访问量较大,未命中redis后,发起了大量对同一数据的数据库访问,导致对数据库服务器造成压力。应对策略应该在业务数据分析与预防方面进行,配合运行监控测试与及时调整策略,毕竟单个key的过期监控难度较高,配合雪崩处理策略即可。

            

            9.4 缓存穿透

            数据库服务器崩溃(3)

            1. 系统平稳运行过程中

            2. 应用服务器流量随时间增量较大

            3. redis服务器命中率随时间逐步降低 (redis命中率降低,对应数据库服务压力变大)

            4. redis内存平稳,内存无压力

            5. redis服务器CPU占用激增

            6. 数据库服务器压力激增

            7. 数据库崩溃


            问题排查:

            1. redis中大面积出现未命中

            2. 出现非正常的URL访问

            a、假设百度搜索redis关键字

            image.png

            b、点击关键字

            image.png

            c、得到正常的URL访问结果

            image.png

            image.png

            d、假设随意修改URL的文章id编号进行访问

            image.png

            e、得到这么个结果,redis未命中,直接进到数据库查询

            image.png

            问题分析:

            1. 获取的数据在数据库中也不存在,数据库查询未得到对应的数据

            2. redis获取到null数据未进行持久化,直接返回

            3. 下次此类数据到达,重复上述过程

            4. 出现黑客攻击   (黑客想办法在穿透redis来对数据库进行攻击,这种攻击不是为了搞数据,通过大量无效URL访问让服务器无法命中,然而给数据库带来较大的流量,导致数据库被整崩掉)

            解决方案(术):

            1. 缓存null

                对查询结果为null的数据进行缓存(长期使用,定期清理),设定短时限,例如30秒-60秒,最高5分钟,时间太久就导致内存泄露 (不是一个有效的解决方案,要是一下来几十万个数据,内存占用短时间瞬间起来)

            内存泄露:程序在申请内存后无法释放已经申请的内存空间,一次性内存泄露可以忽略,但内存泄露堆积后果很严重,memory leak(内存泄露)最终会导致 out of memory(内存不足) ,这块内存不释放,就不能再使用了,就叫这块内存泄露了。

            内存溢出:是程序在申请内存时,没有足够的内存空间供其使用。比如你需要10M的内存空间,内存空间只剩8M,这就会出现内存溢出。就是说分配的内存不足以放下数据项序列,称为内存溢出。

            2. 白名单策略

                提前预热各种分类数据id对应bitmaps,id作为bitmaps的offset,相当于设置了数据白名单。当加载正常数据时放行,加载异常数据时直接拦截(效率偏低)。

                使用布隆过滤器

            3. 实施监控

                实时监控redis命中率(业务正常范围时,通常会有一个波动值)与null数据的占比

                    非活动时段波动:通常检测3-5倍,超过5倍纳入重点排查对象

                    活动时段波动:通常检测10-50倍,超过50倍纳入重点排查对象

                根据倍数不同,启动不同的排查流程,然后使用黑名单进行防控

            4. key加密

                问题出现后,临时启动防灾业务key,对key进行业务层传输加密服务,设定校验程序,过来的key校验

                列如每天随机分配60个加密串,挑选2到3个,混淆到页面数据id中,发现key不满足访问规则,驳回数据访问

            总结:

            1. 缓存击穿访问了不存在的数据,跳过了合法数据的redis数据缓存阶段,每次访问数据库,导致对数据库服务器造成压力。通常此类数据的出现量是一个较低的值,当出现此类情况以毒攻毒,及时报警。应对策略应该在临时预案防范方面多做文章

            2. 无论是白名单还是黑名单,都是对整体系统的压力,警报解除后尽快移除


            9.5 性能指标监控

            监控指标

            image.png

            1. 性能指标

            image.png

            2. 内存指标

            image.png

            3. 基本活动指标

            image.png

            4. 基本活动指标

            image.png

            5. 基本活动指标

            image.png

            监控方式:

            image.png

            命令:

            benchmark

            image.png

            image.png

            monitor命令:打印服务器调试信息

            slowlog命令:

            image.png