Redis基础与高级02

Redis基础与高级二

1、发布订阅模式

例子:比如说你们家有个收音机 你收听了 xxxxx 频道 那么只要你打开这个频道 你就能收听到这个频道的所有的内容

你的收音机-----------接收方(订阅方)

频道的内容发送方-------内容的发布者

subscribe 订阅的频道的名称
publish 频道名字 内容

场景:这个功能实际上就是咋们的 MQ中的功能(不用管它)

在这里插入图片描述

在这里插入图片描述

2、rdb模式实现持久化

Redis我们说是基于内存的、所以速度快、但是Redis的数据放到内存里面、当Redis重启的时候 这个数据会发生丢失

假设我们能把写入到内存的数据、持久化到硬盘 那是不是就能保证我们的数据即使发生丢失 也不会全部丢失、或者全部不丢失呢?

Redis的持久化就产生了----默认情况下 Redis本身也是有持久化策略的

我们即使不配置 那么这个Redis的持久化依然存在的

rdb是数据库默认的持久化模式-----又称为快照模式

这个模式是将内存的数据内容 直接保存到 dump.rdb这样的一个二进制文件中的

特点:因为保存的是二进制文件、所以做数据的恢复是相当的快的—适合于做数据的备份

rdb到底是如何保存我们的数据库的:rdb每一次在保存这个数据的时候、首先都会清空原有的dump.rdb文件、然后将整个内存的数据全部写入到这个文件中 rbd-------保存的是redis内存中某一个时刻的数据(适合备份、不适合开发用)

假设刚好清空dump.rdb这个文件、现在断电了------------数据全丢了

什么时候 rdb模式会触发内存的数据和硬盘进行同步呢?

save 900 1900秒的时间内如果有1和key发生改变 那么将触发内存和硬盘同步
save 300 10300秒的事件内如果有10个key发生改变  那么将会触发内存和硬盘同步
save 60 1000060秒的时间类假设有10000个key发生改变那么也变触发内存和硬盘同步

rdb模式是不用开启的、这个模式的redis自动开启的

3、持久化

3.1 aof实现持久化

aof模式是在redis1.1的版本的时候、才增加的一种持久化模式

aof模式在使用的时候 保存的不是数据 是我们操作的时候的一条一条的命令

只要调用了Redis 那么只要有命令的使用那么都会被记录到aof文件中

aof---------------记录的是操作的命令 不记录实际的数据

aof模式如果是在数据恢复还原的时候 效率并不高 数据恢复的话采用rdb文件恢复是最快的

aof模式如何使用

appendonly yes :表示的是开启aof的模式

*3  *代表的是命令的开始   3 :这个表示的是命令中一共有3块内容
$3 $使用修饰命令中的每一个参数的 3代表的是下面的这个命令一共有3个字符
set
$5
email
$5
xxxxx

rdb 存在 aof 现在也存在 ? 你们觉得会以谁优先 这里如果是开启了aof模式 那么会以aof模式为优先

aof模式是否有触发策略?

appendfsync always  :只要有键发生改变  立马同步(每一次都触发IO操作、速度就慢下来、这种情况是不会丢数据)-----一般不用(效率太低了)
appendfsync everysec :每一秒钟进行数据同步一次(开发的时候一般选用他----速度上也比较快   即使出现数据的丢失也只会丢失1秒钟的数据)
appendfsync no :永远不同步、数据只是放到缓存里面 速度快 但是数据容易丢失

aof模式是如何同步数据的呢?

每一次在进行数据同步的时候 使用的是 追加的模式 以前的数据不用删除 只需要追加新的操作即可

aof模式消息的重写

no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100  (这个表示的是必须达到100%的增加才重写  64M+64M=128M )
auto-aof-rewrite-min-size 64mb   aof文件(简单的说就是至少aof文件达到64M才重写)

手动重写
bgrewriteaof :这个命令就是手动重写 
重写的好处是对aof文件进行优化(最终的结果都是一样的)

如果你要去手动重写(需要关闭混合持久化的开关才能看到功能)
aof-use-rdb-preamble no

3.2 AOF 重写流程

aof实现持久化流程:

在这里插入图片描述

aof 重写流程:

在这里插入图片描述

3.3 RDB与AOF的区别

在这里插入图片描述

3.4、混合持久化的问题

我们在开发的时候到底是选择 rdb 还是aof呢?

如果你关心的是你的数据、但是任然可以接受在一段时间内依然可以接受一些数据的丢失 那么你可以使用rdb(速度快)

我们以前开发的时候基本上都使用aof模式来做开发、如果你用的版本是4.0以前的版本那么建议你呢还是使用aof

在4.0以后 就出现了一种新的持久化模式(混合持久化)
这个混合持久化 就集成了 rdb的有点和aof所有的有点

画图:理解混合持久化

在这里插入图片描述

3.5 持久化应用场景

 Tips 1: redis用于控制数据库表主键id,为数据库表主键提供生成策略,保障数据库表的主键唯一性
结论:容易出现id 不连续问题:pass掉。

 Tips 3: redis应用于各种结构型和非结构型高热度数据访问加速
结论: 这种数据来源于数据库 没必要在redis 中记性持久化操作: pass掉。

 Tips 4: redis 应用于购物车数据存储设计
结论:pass 掉。

 Tips 5: redis 应用于抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计

 Tips 6: redis 应用于具有操作先后顺序的数据控制

 Tips 7: redis 应用于最新消息展示

 Tips 9: redis 应用于同类信息的关联搜索,二度关联搜索,深度关联搜索
结论: 数据库中查询,pass掉

 Tips 12: redis 应用于基于黑名单与白名单设定的服务控制

 Tips 13: redis 应用于计数器组合排序功能对应的排名

 Tips 15: redis 应用于即时任务/消息队列执行管理
 Tips 16: redis 应用于按次结算的服务控制
结论:pass掉,可以使用各种mq

3.6、缓存的淘汰策略

什么是缓存淘汰策略、简单的说就是咋们的redis中的内存已经满了、现在要保证内存中的Redis的数据 一定是最新的、那么这个时候就需要配置缓存的淘汰策略了

noeviction:只要缓存满了、那么就不继续服务器里面的写的请求、读的请求是可以完成的、这种模式缓存里面的所有数据 都不会丢失、这种情况会导致参与Redis的业务会失败
volatile-lru:他会优先淘汰掉 设置了过期时间的这个key、然后第二步才淘汰掉使用的比较少的key 假设我们的key没有设置过期时间的话 那么不会优先淘汰
这种模式也是咋们在开发中使用的比较多的一种缓存策略模式
allkeys-lfu:和lru是有区别的、这个在淘汰的时候、淘汰的是全体key的集合、不是过期的key的集合(过期这一说法没有)、这就意味着你没有设置过期时间的key 只要使用的比较少那么依然会被淘汰
volatile-ttl:这个淘汰策略不是LRU 、而是key剩余的寿命的ttl值  ttl值越小  越先被淘汰
allkeys-random:使用这个淘汰策略的时候  淘汰的是随机的key

maxmemory-policy volatile-lru  这个就是配置缓存的淘汰策略的
maxmemory <bytes> :这个是配置Redis的缓存的大小

4 redis 事务

简述:

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

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

​    **事务的基本操作**
​	 开启事务: multi
​	 	作用:设定事务的开启位置,此指令执行后,后续的所有指令均加入到事务中

​	 执行事务: 	exec
​		作用:	设定事务的结束位置,同时执行事务。与multi成对出现,成对使用
​		注意: 加入事务的命令暂时进入到任务队列中,并没有立即执行,只有执行exec命令才开始执行

​    取消事务: discard
​		 作用:	终止当前事务的定义,发生在multi之后, exec之前

4.1 事务的工作流程

在这里插入图片描述

4.2 事务的注意事项

定义事务的过程中,命令格式输入错误怎么办?
	语法错误:指命令书写格式有误
	处理结果:如果定义的事务中所包含的命令存在语法错误,整体事务中所有命令均不会执行。包括那些语法正确的命令。

定义事务的过程中,命令执行出现错误怎么办?
	运行错误:指命令格式正确,但是无法正确的执行。例如对list进行incr操作
	处理结果:能够正确运行的命令会执行,运行错误的命令不会被执行
	注意:已经执行完毕的命令对应的数据不会自动回滚,需要程序员自己在代码中实现回滚。
	

4.3 事务 锁

1. **基于特定条件的事务执行**
	天猫双11热卖过程中,对已经售罄的货物追加补货, 4个业务员都有权限进行补货。补货的操作可能是一系
	列的操作,牵扯到多个连续操作,如何保障不会重复操作?
**业务场景**
	 多个客户端有可能同时操作同一组数据,并且该数据一旦被操作修改后,将不适用于继续操作
	 在操作之前锁定要操作的数据,一旦发生变化,终止当前操作
  **基于特定条件的事务执行——锁**
	**解决方案**
		对 key 添加监视锁,在执行exec前如果key发生了变化,终止事务执行
		取消对所有 key 的监视:watch key1 [key2……]
 		redis 应用基于状态控制的批量任务执行: unwatch
  1. 业务场景:
    天猫双11热卖过程中,对已经售罄的货物追加补货,且补货完成。客户购买热情高涨, 3秒内将所有商品购买完毕。本次补货已经将库存全部清空,如何避免最后一件商品不被多人同时购买? 【超卖问题】
      业务分析:使用watch监控一个key有没有改变已经不能解决问题,此处要监控的是具体数据,虽然redis是单线程的,但是多个客户端对同一数据同时进行操作时,如何避免不被同时修改?
  解决方案:使用 setnx 设置一个公共锁
	setnx lock-key value
 利用setnx命令的返回值特征,有值则返回设置失败,无值则返回设置成功
 	  对于返回设置成功的,拥有控制权,进行下一步的具体业务操作
	  对于返回设置失败的,不具有控制权,排队或等待
 	操作完毕通过del操作释放锁
 
注意:上述解决方案是一种设计概念,依赖规范保障,具有风险性
  1. 业务场景: 依赖分布式锁的机制,某个用户操作时对应客户端宕机,且此时已经获取到锁。

     业务分析:	由于锁操作由用户控制加锁解锁,必定会存在加锁后未解锁的风险。 
      需要解锁操作不能仅依赖用户控制,系统级别要给出对应的保底处理方案
    
解决方案	
使用 expire 为锁key添加时间限定,到时不释放,放弃锁
	expire lock-key second
	pexpire lock-key milliseconds
由于操作通常都是微秒或毫秒级,因此该锁定时间不宜设置过大。具体时间需要业务测试后确认。
	例如:持有锁的操作最长执行时间127ms,最短执行时间7ms。
	测试百万次最长执行时间对应命令的最大耗时,测试百万次网络延迟平均耗时
	锁时间设定推荐:最大耗时*120%+平均网络延迟*110%
	如果业务最大耗时<<网络平均延迟,通常为2个数量级,取其中单个耗时较长即可

5、删除策略

5.1 简述

redis 中的数据特征:

 Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态
 redis有四种命令可以用于设置键的生存时间和过期时间:
	EXPIRE <KEY> <TTL> : 将键的生存时间设为 ttl 秒
	PEXPIRE <KEY> <TTL> :将键的生存时间设为 ttl 毫秒
	EXPIREAT <KEY> <timestamp> :将键的过期时间设为 timestamp 所指定的秒数时间戳
	PEXPIREAT <KEY> <timestamp>: 将键的过期时间设为 timestamp 所指定的毫秒数时间戳.
	
	XX :具有时效性的数据
	-1 :永久有效的数据
	-2 :已经过期的数据 或 被删除的数据 或 未定义的数据

过期的数据真的立刻删除了吗?

如果Redis的一个键是过期的,那它到了过期时间之后并不是马上就从内存中被删除,而是采用了三种不同的删除策略:

1. 定时删除
2. 惰性删除
3. 定期删除

首先看下: 时效性数据的存储结构

在这里插入图片描述

注意: 数据删除策略的目标
在内存占用与CPU占用之间寻找一种平衡,顾此失彼都会造成整体redis性能的下降,甚至引发服务器宕机或
内存泄露。

5.2 定时删除

创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作
	优点:节约内存,到时就删除,快速释放掉不必要的内存占用
	
	缺点: CPU压力很大,无论CPU此时负载量多高,均占用CPU,会影响redis服务器响应时间和指令吞吐量
	
	总结:用处理器性能换取存储空间(拿时间换空间)

在这里插入图片描述

5.3 惰性删除

 数据到达过期时间,不做处理。等下次访问该数据时
	如果未过期,返回数据
	发现已过期,删除,返回不存在
	优点:节约CPU性能,发现必须删除的时候才删除
	缺点:内存压力很大,出现长期占用内存的数据
	总结:用存储空间换取处理器性能(拿时间换空间)

在这里插入图片描述

5.4 定期删除

周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度
	特点1: CPU性能占用设置有峰值,检测频度可自定义设置
	特点2:内存压力不是很大,长期占用内存的冷数据会被持续清理
	总结:周期性抽查存储空间
	
	expireIfNeeded()  (随机抽查,重点抽查)

在这里插入图片描述

5.5 对比

定时删除 节省内存,无占用 不分时段占用cpu资源,频度高 拿时间换空间
惰性删除 内存占用严重 延时执行,cpu利用率高 拿空间换时间
定期删除 内存定期随机清理 每秒花费固定的CPU资源维护内存 随机抽查,重点抽查

5.6 逐出算法

问题: 当新数据进入redis时,如果内存不足怎么办?

Redis使用内存存储数据,在执行每一个命令前,会调用freeMemoryIfNeeded()检测内存是否充足。
如果内存不满足新加入数据的最低存储要求, redis要临时删除一些数据为当前指令清理存储空间。
清理数据的策略称为逐出算法。
	注意:逐出数据的过程不是100%能够清理出足够的可使用的内存空间,如果不成功则反复执行。当对所
有数据尝试完毕后,如果不能达到内存清理的要求,将出现错误信息。

错误信息: (error) OOM command not allowed when used memory >'maxmemory'

影响数据逐出的相关配置

最大可使用内存 :maxmemory
 占用物理内存的比例,默认值为0,表示不限制。生产环境中根据需求设定,通常设置在50%以上。
 
每次选取待删除数据的个数:maxmemory-samples
选取数据时并不会全库扫描,导致严重的性能消耗,降低读写性能。因此采用随机获取数据的方式作为待检测删除数据

删除策略: maxmemory-policy
达到最大内存后的,对被挑选出来的数据进行删除的策略



检测易失数据(可能会过期的数据集server.db[i].expires )
	① volatile-lru:挑选最近最少使用的数据淘汰
	② volatile-lfu:挑选最近使用次数最少的数据淘汰
	③ volatile-ttl:挑选将要过期的数据淘汰
	④ volatile-random:任意选择数据淘汰
检测全库数据(所有数据集server.db[i].dict )
	⑤ allkeys-lru:挑选最近最少使用的数据淘汰
	⑥ allkeys-lfu:挑选最近使用次数最少的数据淘汰
	⑦ allkeys-random:任意选择数据淘汰
放弃数据驱逐
	⑧ no-enviction(驱逐):禁止驱逐数据( redis4.0中默认策略),会引发错误OOM( Out Of Memory)
	
数据逐出策略配置依据
	使用INFO命令输出监控信息,查询缓存 hit 和 miss 的次数,根据业务需求调优Redis配置

待续。。。。下一篇

发布了50 篇原创文章 · 获赞 21 · 访问量 3701

猜你喜欢

转载自blog.csdn.net/wmlwml0000/article/details/104724075