不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • Langchain
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • Langchain
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • MySQL

  • Redis

    • 01.Redis安装
    • 02.Redis基础
      • 01.Redis简介
        • 1、什么是Redis?
        • 2、Redis特点
      • 02.Redis内存碎片
        • 1、内存碎片化的成因
        • 2、内存碎片化影响
        • 3、检测 内存碎片化
        • 4、Redis 内存碎片化的优化方法
      • 03.Redis 阻塞
      • 04.Redis大key
        • 1、大 key 问题的影响
        • 2、大 key 的分片
        • 3、持久化大 key 的优化
        • 4、监控大 key
    • 03.Redis底层存储 ✅
    • 04.各种数据类型操作
    • 05.Redis连接和基本操作
    • 06.Redis线程模型 ✅
    • 07.Redis持久化 ✅
    • 08.Redis集群 ✅
    • 09.雪崩穿透击穿
    • 10.Redis锁代码
    • 11.Redis缓存
    • 12.部署Redis主从
    • 13.Redis的cluster配置
    • 14.Redis哨兵模式
    • 15.Redis淘汰策略 ✅
    • 16.CAP ✅
  • Elasticsearch

  • Kafka

  • Etcd

  • MongoDB

  • TiDB

  • RabbitMQ

  • 数据库
  • Redis
xiaonaiqiang
2024-03-14
目录

02.Redis基础

# 01.Redis简介

# 1、什么是Redis?

  • Redis本质上是一个Key-Value类型的内存数据库,很像memcached

  • 整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存

  • 因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB

# 2、Redis特点

  • Redis比memcached优点

    • 数据类型:Redis支持五中数据类型, memcached所有的值均是简单的字符串
    • value大小限制:Redis单个value的最大限制是512M,memcached只能保存1MB的数据
    • 持久化:Redis可以持久化,memcached不支持持久化
  • Redis为什么快?

    • 纯内存操作
    • 单线程避免上下文切换
    • 非阻塞IO多路复用机制
    • 高效的数据结构,这些结构经过优化,能够快速完成各种操作
  • Redis缺点

    • 内存限制,不能用作海量数据存储
    • 注:如果需要存储海量数据,可以使用MongoDB

# 02.Redis内存碎片

# 1、内存碎片化的成因

  • Redis 中的内存碎片化指的是由于频繁的内存分配和释放操作
  • 导致内存被分割成无法连续使用的小块,从而影响 Redis 的内存利用率和性能碎片化的内存块虽小且无法被利用
  • 对象的频繁创建和销毁: 频繁的插入和删除操作会导致小块内存频繁被分配和释放

  • 变长数据结构的使用:

    • Redis 中一些数据结构如 list、set、hash、zset 是变长结构,随着数据的增删,内存分配会动态扩展或收缩
    • 如果这些数据结构频繁扩展和收缩,可能导致无法连续使用的内存块残留,形成碎片
  • 大对象的删除或修改:

    • Redis 使用内存管理库(如 jemalloc)对内存块进行分配
    • 假如删除或修改了大对象,释放的内存块可能会被分割成多个小块,这些小块无法被有效利用

# 2、内存碎片化影响

  • 内存浪费:
    • 虽然 Redis 的进程看似占用大量内存,但因为碎片化,Redis 实际可以利用的内存可能较少
    • 随着碎片化的加剧,系统会出现内存不足的假象,而 Redis 进程占用的内存实际没有减少
  • 性能下降:
    • 碎片化的内存难以高效利用,可能导致 Redis 的性能下降
    • 例如,在进行大数据插入时,Redis 可能频繁进行内存分配和整理,增加 CPU 的负载
  • 可能导致 OOM(Out Of Memory):
    • 当系统报告有足够内存可用,但实际因为碎片化无法分配足够的连续内存时
    • 可能导致 Redis 进程无法分配所需的内存,从而导致 OOM

# 3、检测 内存碎片化

  • Redis 提供了 INFO memory 命令来查看内存使用情况
  • 其中 mem_fragmentation_ratio 参数可以反映 Redis 的内存碎片化情况
127.0.0.1:6379> INFO memory
# Memory
used_memory:1024000           # Redis 实际使用的内存
used_memory_human:1000K
used_memory_rss:2048000       # Redis 进程从操作系统申请的物理内存
used_memory_rss_human:2M
mem_fragmentation_ratio:2.00    # 内存碎片率
1
2
3
4
5
6
7
  • mem_fragmentation_ratio:
    • 内存碎片率,表示 used_memory_rss / used_memory
    • 如果该值大于 1,则表明有内存碎片,理想状态下,这个值应接近 1
    • 当 mem_fragmentation_ratio > 1.5 时,说明 Redis 出现较为严重的内存碎片化

# 4、Redis 内存碎片化的优化方法

  • 使用 Jemalloc:

    • Redis 默认使用 jemalloc 作为内存分配器,它比系统默认的 malloc 更高效,尤其在管理小对象和避免内存碎片方面有显著优势

    • jemalloc 的内存池管理机制可以减少碎片化的产生,推荐在生产环境中使用

    • 检查 Redis 是否在使用 jemalloc: Redis-server --version

  • 定期进行内存整理:

    • 如果发现 Redis 内存碎片化比较严重,可以尝试通过重启 Redis 进程来整理内存
    • 不过,重启 Redis 会中断服务,因此不适合在高并发的生产环境下使用
    • 另一种方式是将数据持久化后,采用以下步骤:
      • 执行 BGSAVE 将数据保存到磁盘
      • 使用 SHUTDOWN SAVE 命令关闭 Redis 实例
      • 再次启动 Redis 实例,Redis 会从持久化的文件中加载数据,此时会重新分配内存,有效减少内存碎片
  • 合理配置 Redis 的 maxmemory 策略:

    • Redis 提供了内存淘汰策略,通过合理配置 maxmemory 参数和淘汰策略

    • volatile-lru:只对设置了过期时间的 key 进行 LRU 淘汰

    • allkeys-lru:对所有 key 进行 LRU 淘汰

    • volatile-random:随机淘汰设置了过期时间的 key

    • volatile-ttl:根据 key 的剩余 TTL 值淘汰

  • 减少对象的频繁创建和销毁:

    • 避免在 Redis 中频繁创建和销毁对象,可以通过优化业务逻辑来减少这种操作
    • 比如减少不必要的 SET、DEL 操作,或者批量处理数据而不是逐条处理
  • 使用适当的数据结构:

    • 根据数据的实际用途,选择适合的数据结构
    • 比如,尽量避免使用过长的 list 或 hash,因为这些变长数据结构在增长和收缩时容易导致内存碎片
    • 可以尝试将较大的对象分割成小块进行存储,避免内存块的不连续分配
  • 升级 Redis 版本:

    • Redis 的不同版本在内存管理方面的表现有所不同,新版本往往包含更好的内存管理机制和优化
    • 如果你使用的 Redis 版本较老,可以考虑升级到较新版本以获得更好的内存管理效果

# 03.Redis 阻塞

  • 1)O(n)复杂度命令

    • Redis 中的大部分命令都是 O(1)时间复杂度,但也有少部分 O(n) 时间复杂度的命令

    • KEYS *:会返回所有符合规则的 key

    • HGETALL:会返回一个 Hash 中所有的键值对

    • LRANGE:会返回 List 中指定范围内的元素

    • SMEMBERS:返回 Set 中的所有元素

    • SINTER/SUNION/SDIFF:计算多个 Set 的交集/并集/差集

  • 2)SAVE 创建 RDB 快照

    • save : 同步保存操作,会阻塞 Redis 主线程;

    • bgsave : fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项

      • 默认情况下,Redis 默认配置会使用 bgsave 命令

      • 如果手动使用 save 命令生成 RDB 快照文件的话,就会阻塞主线程

  • 3)AOF 日志记录阻塞Redis

    • AOF 持久化机制是在执行完命令之后再记录日志
  • 4)大 Key

    • 如果一个 key 对应的 value 所占用的内存比较大,那这个 key 就可以看作是 bigkey

    • 具体多大才算大呢?有一个不是特别精确的参考标准

      • string 类型的 value 超过 1MB

      • 复合类型(列表、哈希、集合、有序集合等)的 value 包含的元素超过 5000 个

    • 大 key 造成的阻塞问题如下

      • 客户端超时阻塞

      • 引发网络阻塞:如果一个 key 的大小是 1 MB,每秒访问量为 1000,那么每秒会产生 1000MB 的流量

      • 阻塞工作线程:如果使用 del 删除大 key 时,会阻塞工作线程

# 04.Redis大key

  • 在 Redis 中,大 key(即数据量很大的键)会对系统性能和稳定性造成一定影响
  • 大 key 可能是一个包含大量元素的复杂数据结构(如 list、hash、set、zset),或者是一个非常长的字符串
  • 如果不加控制,大 key 会导致一些操作(如删除、迁移、备份)耗时过长,甚至阻塞 Redis 线程,影响系统整体性能

# 1、大 key 问题的影响

  • 阻塞 Redis 线程:
    • Redis 是单线程处理请求的,因此如果一个大 key 的操作(如删除、迁移等)需要很长时间,会阻塞其他客户端的请求,导致延迟变大
  • 网络传输耗时:
    • 如果大 key 占用大量的网络带宽,传输大 key 时会导致 Redis 客户端和服务器之间的传输延迟
  • 内存使用问题:
    • 大 key 占用的内存较多,容易导致 Redis 的内存消耗过高,并可能引发 Redis 的内存淘汰机制,导致不必要的 key 被删除
  • 持久化和恢复:
    • Redis 持久化机制如 RDB 和 AOF 可能需要大量时间来保存或恢复大 key,影响 Redis 的持久化效率

# 2、大 key 的分片

  • 对大 key 进行分片存储是避免创建大 key 的有效方法

  • 可以通过一定的规则将数据拆分为多个小 key 存储

  • 时间分片:

    • 根据时间戳将数据分散到不同的 key 上
    • 例如,将每天的用户日志记录存储在 user_logs:20231008、user_logs:20231009 这样的 key 上
  • 哈希分片:

    • 对 key 的一部分进行哈希运算,存储到多个 Redis key 上

    • 例如,将用户数据根据用户 ID 进行分片

    • user:1234 -> shard1
      user:5678 -> shard2
      
      1
      2
    • 通过哈希分片可以将大数据量分散存储到多个 key 中,避免形成单个大 key

# 3、持久化大 key 的优化

Redis 的持久化操作会扫描和保存所有的 key,如果存在大 key,持久化过程会变慢可以采取以下优化措施:

  • 持久化策略调整:
    • 对于需要持久化的大 key,可以适当延长持久化周期
    • 或者只对重要的小 key 进行持久化,将不重要的大 key 设置为不持久化(通过调整 RDB 和 AOF 策略)
    • 使用 SAVE 或者 BGSAVE 配合 EXCLUDE 将某些不需要持久化的 key 排除在外
  • AOF 文件压缩:
    • AOF 方式可以在重写时将大 key 分批重写,避免一次性重写全部内容
    • Redis 6.0 及以后版本的 AOF 重写机制已经优化过这类问题

# 4、监控大 key

  • 定期运行 Redis 的 bigkeys 脚本,获取实例中的大 key
  • 设置合理的告警阈值,当某个 key 的大小超过阈值时,触发告警,及时处理
01.Redis安装
03.Redis底层存储 ✅

← 01.Redis安装 03.Redis底层存储 ✅→

最近更新
01
05.快递Agent智能体
06-04
02
200.AI Agent核心概念
06-04
03
105.Agent智能体梳理
06-04
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式