Redis五大影响性能原因(三四五):慢操作

一、慢操作排查处理步骤

  • 判断当前情况是否属于慢操作(基线性能)
  • 系统性排查慢操作的原因(Redis本身、AOF文件操作磁盘IO、操作系统内存swap磁盘IO);
  • 应对方案中选择合适的方法加快Redis响应速度。

二、 如何判断是否是慢操作:

用指令查询当前环境下Redis的基线性能,再查询当前应用Redis的延迟,如果达到两倍以上基线性能说明当前是慢操作。

三、 排查慢操作

3.1 针对Redis本身

A) sql语句慢造成延迟:

可以用 Redis日志查看sql语句的执行情况,判断是否变慢了(类似于Mysql的explain);

解决方法:

  • 查询Set集合中所有元素时用 SSCAN分批次返回数据给客户端

  • 在客户端进行集合的聚合操作,避免使用SORT,SUNION,SINTER等命令;

  • 不建议使用KEYS命令来遍历查询所有满足要求的key(可以用SCAN命令代替);

B) 过期key自动删除阻塞Redis:

Redis默认每隔100ms删除指定个数过期key,重复删除直到过期key占所有key的比例低于25%(大量key过期Redis就会一直在这执行删除操作,影响主线程),原因是程序一次性给大量key设置了同样的过期时间,同一刻大量key过期(会造成雪崩)。

解决方法:

  • 尽量 给key设置不同的过期时间,可以在过期时间上加一个随机数。

3.2 针对文件系统(AOF写入磁盘,产生磁盘IO,RDB读写复制时fork拷贝内存页过大)

A) AOF日志:

主线程调用子线程按照三种策略进行AOF写操作,会产生磁盘IO(每执行一个操作就记录到AOF中,每秒记录一次AOF,间隔一定时间记录一次AOF);

在子进程中AOF会进行重写,会产生磁盘IO,会和子线程中的AOF写入操作竞争磁盘资源

主线程阻塞过程:如果AOF重写操作占据了磁盘IO,导致主线程上一次执行的AOF写操作阻塞,那么当主线程再次执行AOF写入操作时,会阻塞等待子线程执行完成上一次AOF写入才能将其交由子线程执行(fsnyc操作: 主线程在此处等待将第二次AOF交由子线程执行)本次AOF写入。

请添加图片描述

解决方法:

  • 根据业务需求选择主线程 多久进行一次AOF文件写入

  • 考虑主线程不使用fsync操作,每次都直接将AOF写入请求交给子线程,这样主线程不会阻塞,但是AOF文件中可能有数据丢失

  • 采用高速固态硬盘存储AOF日志文件。

B) RDB快照:

如果操作系统采用的是 大内存页机制(内存被分配成2MB每份,常规是4kB),当RDB持久化时,主线程会fork子线程,此时子线程要拷贝一份和主线程一样的内存,那么必须以2MB为单位拷贝内存页,当主线程中内存一页中只占用了几kB,却要 花更多的时间浪费在拷贝空数据页上,导致fork过程影响主线程执行

解决方法:

  • 关闭大内存页机制

3.3 操作系统Swap操作(数据在内存和磁盘之间来回传输)

当Redis所需的内存空间不够时, 数据会在内存页和磁盘中来回移动,极大提高磁盘IO,影响Redis主线程。

产生原因:

  1. Redis实例存储占用过多内存
  2. 其他应用程序进行大量文件读写占用内存,导致Redis可用内存变少。

解决方法:

  • 增加机器内存
  • 采用Redis集群减少redis所需的内存空间。

参考文章:

https://time.geekbang.org/column/article/287819

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis 五大数据类型: 1. String:用于存储字符串、整数或者浮点数等类型的值,可以对字符串进行一些操作,如追加、截取等。 2. List:用于存储一个有序的字符串列表,可以对列表进行插入、删除、修改、查找等操作,还可以通过下标来访问列表中的元素。 3. Hash:用于存储一个字符串字段和字符串值之间的映射关系,可以对哈希表进行添加、删除、修改、查找等操作。 4. Set:用于存储一组字符串元素,可以对集合进行添加、删除、查找、交集、并集、差集等操作。 5. Sorted Set:用于存储一组有序的字符串元素,每个元素都有一个对应的分数,可以对有序集合进行添加、删除、查找、排序等操作。 下面是一个简单的Python代码示例,实现了一个旁路缓存功能,即在访问某个数据时,先在 Redis 中查找,如果 Redis 中不存在该数据,则从本地缓存中获取,如果本地缓存也不存在,则从数据库中获取,并将数据同时保存到本地缓存和 Redis 中: ```python import redis class Cache(object): def __init__(self, redis_client, local_cache): self.redis_client = redis_client self.local_cache = local_cache def get(self, key): value = self.redis_client.get(key) if value is not None: return value else: value = self.local_cache.get(key) if value is not None: self.redis_client.set(key, value) return value else: value = self.get_from_database(key) self.local_cache.set(key, value) self.redis_client.set(key, value) return value def get_from_database(self, key): # 查询数据库并返回数据 pass if __name__ == '__main__': redis_client = redis.Redis(host='localhost', port=6379, db=0) local_cache = {} cache = Cache(redis_client, local_cache) value = cache.get('key') ``` 持久化是指将 Redis 中的数据存储到磁盘中,以便在服务重启后可以恢复数据。Redis 支持两种持久化方式: 1. RDB:在指定的时间间隔内,将 Redis 中的数据集快照写入磁盘中,即生成一个 RDB 文件。RDB 文件是一个二进制文件,包含了 Redis 数据库的所有键值对。使用 RDB 持久化可以快速恢复大型数据集。可以通过配置文件中的 save 和 bgsave 指令来设置 RDB 持久化的规则。 2. AOF:将 Redis 中的写命令追加到 AOF 文件中,以便在服务重启后重放这些写命令,从而恢复 Redis 数据库中的数据。AOF 文件是一个文本文件,其内容为 Redis 的写命令。使用 AOF 持久化可以确保数据的完整性和可靠性。可以通过配置文件中的 appendonly 指令来开启 AOF 持久化,并通过 appendfsync 指令来设置 AOF 文件的同步策略。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值