0
点赞
收藏
分享

微信扫一扫

【Linux网络编程】网络基础 | Socket 编程基础

爱我中华8898 2024-10-14 阅读 10
Spring-data-redis

说明: 在 SpringBoot2.x 之后,原来使用的jedis 被替换为了 lettuce

jedis : 采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用 jedis pool 连接池

lettuce : 采用netty,实例可以再多个线程中进行共享,不存在线程不安全的情况!可以减少线程数据了

序列化策略

Redis持久化

Redies是内存数据库,如果不将内存中的数据库状态保存到磁盘, 那么一旦服务器进程退出,服务器中的数据库状态也会小时。所以Redis提供了持久化功能!

持久化过程保存什么

  1. 将当前数据状态进行保存,快照形式,存储数据结果,存储格式简单,关注点在数据(PDB
  2. 将数据的操作过程进行保存,日志形式,存储操作过程,关注点在数据的操作过程(AOF
RDB方式
 RDB手动

save指令

命令:save

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

save指令相关配置

dbfilename dump.rdb

说明:设置本地数据库文件名,默认值为dump.rdb

经验:通常设置成存储空间较大的目录中,目录名称data

dir

说明:设置存储.rdb文件的路径

经验:通常设置成存储空间较大的目录中,目录名称data

rdbcompression yes

说明:设置存储至本地数据库时是否压缩数据,默认为yes,采用LZF算法压缩

经验:通常默认为开启状态,如果设置为no,可以节省 CPU 运行时间,但会使存储的文件变大(巨 大)

rdbchecksum yes

说明:设置是否进行CRC64算法RDB文件格式校验, 该校验过程在写文件和读文件过程均进行

经验:通常默认为开启状态,如果设置为no,可以节约读写性过程约10%时间消耗,但是存储一定的数 据损坏风险

RDB自动

配置 :save second changes

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

参数 :

second:监控时间范围

changes:监控key的变化量

位置 : 在conf文件中进行配置

注意:

RDB优点
RDB缺点
AOF方式
AOF执行过程
AOF写数据三种策略(appendfsync)
AOF相关配置
AOF重写
 AOF重写作用
AOF重写规则
AOF重写方式
RDB与AOF区别 

 总结

 Redis 删除策略
1.过期数据

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

  • XX :具有时效性的数据
  • -1 :永久有效的数据

    -2 :已经过期的数据或被删除的数据或未定义的数据

2.数据删除策略

    数据删除策略的目标

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

2.1定时删除
2.2 惰性删除
2.3 定期删除

 定期删除:周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度。

优点1:CPU性能占用设置有峰值,检测频度可自定义设置

优点2:内存压力不是很大,长期占用内存的冷数据会被持续清理

总结:周期性抽查存储空间 (随机抽查,重点抽查)

删除策略比对

1. 定时删除 节约内存,无占用 不分时段占用CPU资源,频度高 拿时间换空间

2. 惰性删除 内存占用严重 延时执行,CPU利用率高 拿空间换时间

3. 定期删除 内存定期随机清理 每秒花费固定的CPU资源维护内存 随机抽查,重点抽查

逐出算法

   当新数据进入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)达到最大内存后的,对被挑选出来的数据进行删除的策略

企业级解决方案

 3.缓存预热

   问题排查:
  1. 请求数量较高:当系统刚启动时,由于缓存为空,所有请求都回落到后端数据库上,这可能导致数据库负载激增,影响响应时间。

  2. 主从之间数据吞吐量较大:在分布式系统中,如果主节点更新了数据,那么需要将这部分数据同步到从节点。如果没有缓存预热机制,在系统启动初期,大量的数据更新操作可能会导致主从之间的数据同步变得非常频繁,增加网络负载。 

准备工作:
  1. 日常例行统计数据访问记录:通过历史访问数据的统计,可以找出那些数据是高频访问的,从而确定哪些数据需要在系统启动时预热。

  2. 将统计结果中的数据分类:根据数据的重要性和访问频率对其进行分类,对于重要性高且访问频率的数据,应该优先进行预热。

解决方案
  1. 使用脚本程序固定触发数据预热过程:可以通过编写脚本来实现数据预热,该脚本可以部署阶段或定期运行,将关键数据加载进缓存。

  2. 使用CDN(内容分发网络):对于静态资源或者分布广泛的用户群,使用CDN可以进一步减少延迟,提高用户体验。虽然CDN主要用于静态文件的分发,但它也可以作为缓存的一部分减轻服务器压力。

  3. 定期刷新缓存:设置一个定时任务来定期刷新缓存中的数据,确保缓存中的数据是最新的,同时也要注意不要过于频繁刷新,以避免增加不必要的开销。

总结

   4.缓存雪崩

 解决方案

  • 给不同的key的TTL添加随机值:为了避免所有的缓存键同时失效,可以在设置键的有效期(TTL) 时加入一定的随机值,使得它们不会在同一时间过期。

  • 利用Redis集群提高服务的可用性:通过搭建Redis集群,可以提高缓存服务的可用性,即使单个节点发生故障,集群中的其他节点仍能提供服务。

  • 给缓存业务添加降级限流策略:在缓存服务不可用时,可以采用降级处理,返回一些默认的、不依赖实时性的数据,或者限制请求的速率,防止数据库被压垮。

  • 给业务添加多级缓存:例如,可以先使用本地缓存(如GuavaCache),再使用远程缓存(如Redis),这样即使远程缓存出现问题,还有本地缓存作为缓冲。

5.缓存击穿

解决方案:

  1. 互斥锁:当一个键失效后,多个并发请求同时达到时,可以使用互斥锁来确保只有一个请求去加载数据并写入缓存。其他请求则等待所释放后在尝试从缓存中获取数据。
  2. 逻辑过期:为了避免缓存键正好在某一时刻过期,可以设置一个“逻辑过期”时间,即在缓存键中存储一个过期时间戳,每次访问时检查这个时间戳来决定是否需要更新缓存。

 解决方案一:使用锁来解决

因为锁能实现互斥性。假设线程过来,只能一个人一个人的来访问数据库,从而避免对于数据库访问压力过大,但这也会影响查询的性能,因为此时会让查询的性能从并行变成了串行,我们可以采用tryLock方法 + double check来解决这样的问题。

假设现在线程1过来访问,他查询缓存没有命中,但是此时他获得到了锁的资源,那么线程1就会一个人去执行逻辑,假设现在线程2过来,线程2在执行过程中,并没有获得到锁,那么线程2就可以进行到休眠,直到线程1把锁释放后,线程2获得到锁,然后再来执行逻辑,此时就能够从缓存中拿到数据了。

解决方案二、逻辑过期方案

方案分析:我们之所以会出现这个缓存击穿问题,主要原因是在于我们对key设置了过期时间,假设我们不设置过期时间,其实就不会有缓存击穿的问题,但是不设置过期时间,这样数据不就一直占用我们内存了吗,我们可以采用逻辑过期方案。

我们把过期时间设置在 redis的value中,注意:这个过期时间并不会直接作用于redis,而是我们后续通过逻辑去处理。假设线程1去查询缓存,然后从value中判断出来当前的数据已经过期了,此时线程1去获得互斥锁,那么其他线程会进行阻塞,获得了锁的线程他会开启一个 线程去进行 以前的重构数据的逻辑,直到新开的线程完成这个逻辑后,才释放锁, 而线程1直接进行返回,假设现在线程3过来访问,由于线程线程2持有着锁,所以线程3无法获得锁,线程3也直接返回数据,只有等到新开的线程2把重建数据构建完后,其他线程才能走返回正确的数据。

这种方案巧妙在于,异步的构建缓存,缺点在于在构建完缓存之前,返回的都是脏数据。

6.缓存穿透

 解决方案
举报

相关推荐

0 条评论