当前位置:   article > 正文

Redis常见问题汇总_单机redis性能

单机redis性能

目录

1、Redis为什么这么快

2、Redis的过期策略以及内存淘汰机制

2.1、为什么不用 定时删除 策略

2.2、定期删除+惰性删除是如何工作的

2.3、采用定期删除+惰性删除就没其他问题了么?

2.4、Redis内存淘汰机制

3、Redis并发环境下使用

3.1、如何解决redis的并发竞争key问题

3.2、MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据

4、Redis与其他缓存对比及多级缓存

4.1、redis相比memcached有哪些优势?

4.2、Redis的多级缓存

5、Redis 应用场景

5.1、普通缓存

5.2、会话缓存

5.3、消息队列/发布订阅

5.4、排行榜/计数器

5.4.1、排行榜

5.4.2、计数器

5.5、分布式锁(Redisson)

6、Redis性能优化及线上问题排查

6.1、redis优化方案

6.1.1、合理选择合适的数据结构、回收策略、过期时间、持久化配置

6.1.2、内存优化

6.1.3、批量操作选管道机制

6.1.4、使用Kubernetes 的监测工具,监控各种性能参数

6.2、redis线上问题排查

6.2.1、 redis 出现性能问题时,如何排查

6.2.2、开启 慢日志并分析(或Kubernetes分析)

6.2.3、持久化失败如何解决

6.2.4、big key排查


1、Redis为什么这么快

Redis有多快?单机可以支持约10w/s的QPS。
(1)纯内存操作

(2)5中数据类型选用的内部数据结构经过精心设计

(3)6.0以前采用单线程,省去了很多上下文切换的时间以及CPU消耗,不存在竞争条件,不用去考虑各种锁的问题

(4)基于非阻塞IO多路复用机制(select()、epoll())

通过一个线程监听多个socket的IO连接事件,从而实现在单个线程中处理多个连接的读写操作

这个线程是一个事件处理器(event loop);

该事件处理器会将每个连接对应的 文件描述符 注册到事件监听机制中,并在事件就绪时调用相应的读写函数来处理IO操作,这样就可以单线程处理多个连接IO操作


2、Redis的过期策略以及内存淘汰机制

redis采用的是定期删除+惰性删除策略。

2.1、为什么不用 定时删除 策略

定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下尤其不适用。

2.2、定期删除+惰性删除是如何工作的

(1)定期删除,redis默认每个100ms检查,检查有过期key则删除。

需要说明的是,redis不是每隔100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。

(2)于是,惰性删除派上用场。在获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了,如果过期了此时就会删除(懒汉式)。

2.3、采用定期删除+惰性删除就没其他问题了么?

不是的,如果定期删除没删除key,也没即时去请求key,也就是说惰性删除也没生效。这样,redis的内存会越来越高。那么就应该采用内存淘汰机制。在redis.conf中配置。

2.4、Redis内存淘汰机制

当Redis的内存使用达到配置的最大内存限制时,会触发内存淘汰机制来释放部分内存空间

(1)allkeys-lru(推荐)

当内存不足以容纳新写入数据时,移除最近最少使用的key

(2)allkeys-random(不推荐)

随机移除某个key

(3)volatile-lru(不推荐)

在设置了过期时间的键空间中,移除最近最少使用的key

(4)volatile-random(不推荐)

在设置了过期时间的键空间中,随机移除某个key

(5)volatile-ttl(不推荐)

3、Redis并发环境下使用

3.1、如何解决redis的并发竞争key问题

(1)事务

通过使用MULTI、EXEC和WATCH命令,可以将多个操作作为一个事务进行执行,但是生产环境redis一般是集群的,不适用。

(2)乐观锁

使用版本号(Version)来实现乐观锁。每次对键进行修改时,都会更新该键的版本号;在读取时,先获取当前版本号,然后进行操作,最后再次验证版本号是否一致,如果版本号不一致,说明该键已被其他客户端修改,需要重新尝试。

(3)分布式锁(推荐)

是一种在分布式系统中解决并发竞争的常见机制,可使用Redisson

(4)队列Queue

将需要对同一个键进行操作的请求放入队列中,然后通过一个单独的线程或来处理队列中的请求。这样可以保证对同一个键的操作按序执行,避免并发竞争。

3.2、MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据

(1)缓存淘汰策略

redis 内存大小上升到一定大小时,就会施行数据淘汰策略,可选LRU最近最少使用淘汰策略;

(2)数据预热

在系统启动时,将热点数据预先加载到Redis中。可以使用jedis的管道(Pipeline )批量初始化加载到Redis。

  1. Jedis jedis = JedisUtil.getJedis();
  2. // 管道
  3. Pipeline pipelined = jedis.pipelined();
  4. for (int i = 0; i < 10000; i++) {
  5. pipelined.set("cc_"+i, i+"");
  6. }
  7. //执行管道中的命令
  8. pipelined.sync();

4、Redis与其他缓存对比及多级缓存

4.1、redis相比memcached有哪些优势?

(1)memcached只支持字符串,redis支持更为丰富的数据类型

(2)redis的速度比memcached快很多

(3)redis可以持久化数据到磁盘,memcached只能存在内存中

4.2、Redis的多级缓存

优先顺序:本地内存(咖啡因)-->redis(回填内存)--->数据库(回填内存、redis)

5、Redis 应用场景

5.1、普通缓存

5.2、会话缓存

将用户会话信息存储在Redis中,实现分布式会话管理

5.3、消息队列/发布订阅

list/set的lpush/rpop实现消息队列。

(1)将消息推入队列

使用lpush命令将消息推入队列的左侧(头部);

(2) 队列中取出消息

使用rpop命令从队列的右侧(尾部)弹出消息,List结构的话可实现先进先出的消息处理。

实现消息队列中list和set区别:

  • list可实现消息的顺序性保证FIFO先进先出,set无序;
  • list允许存储重复数据set不行;

5.4、排行榜/计数器

5.4.1、排行榜

(1)常见排行榜需求

  • 添加一条记录:将一个用户或商品的得分添加到排行榜中;
  • 更新一条记录:更新某个用户或商品的得分;
  • 删除一条记录:将某个用户或商品从排行榜中删除;
  • 查询排名:查询某个用户或商品的排名;
  • 查询得分:查询某个用户或商品的得分;
  • 查询排行榜:按照得分从高到低查询排行榜前N个用户或商品。

(2)实现原理(Sorted Set)

有序集合(Sorted Set)中的每个元素都有一个分值(score),可根据分值进行排序。

因此,我们可以将用户或商品的得分作为有序集合中的分值,将用户或商品的唯一标识作为有序集合中的成员。

(3)具体实现

  • 添加/修改一条记录:redis.zadd("leaderboard", {"user1": 100});
  • 删除一条记录:redis.zrem("leaderboard", "user1");
  • 查询排名:redis.z revrank("leaderboard", "user1");
  • 查询得分:redis.zscore("leaderboard", "user1");
  • 查询排行榜:redis.zrevrange("leaderboard", 0, 9)

5.4.2、计数器

(1)String可变字符串实现

incry指令增加计数器的值

  1. Jedis jedis = new Jedis("localhost");
  2. // 存储计数值
  3. jedis.set("counter", "0");
  4. // 增加计数值
  5. jedis.incrBy("counter", 5);
  6. // 获取计数值
  7. String counterValue = jedis.get("counter");

(2)Redisson的RAtomicLong原子类 实现

  1. RedissonClient redisson = Redisson.create(config);
  2. // 获取或创建计数器对象
  3. RAtomicLong counter = redisson.getAtomicLong("counter");
  4. counter.incrementAndGet(); // 增加计数值1
  5. long counterValue = counter.get(); // 获取计数值

5.5、分布式锁(Redisson)


6、Redis性能优化及线上问题排查

6.1、redis优化方案

性能瓶颈:内存、网络贷款、CPU、持久化配置、锁竞争、阻塞操作、数据结构选择

6.1.1、合理选择合适的数据结构、回收策略、过期时间、持久化配置

6.1.2、内存优化

避免存储不必要的数据、大型数据。可通过压缩数、设置过期策略实现

6.1.3、批量操作选管道机制

批量操作或者数据预热时,使用java的客户端Jedis的Pipeline管道机制(redis没有该命令但是Jedis有)。

6.1.4、使用Kubernetes 的监测工具,监控各种性能参数

6.2、redis线上问题排查

6.2.1、 redis 出现性能问题时,如何排查

(1)监控系统

(2)慢查询日志

(3)内存分析

使用info命令来查看内存使用情况,包括内存占用情况、内存碎片、内存淘汰策略。

(4)配置分析、网络分析、命中率分析

6.2.2、开启 慢日志并分析(或Kubernetes分析)

config配置开启慢日志记录,例如设置阈值为5则保利最近500条记录。

可查看哪些命令执行耗时、哪些频繁、哪些消耗资源多。

6.2.3、持久化失败如何解决

(1) 立即停止写入操作

(2)检查持久化配置、分析原因

(3)手动持久化

RDB失败,手动执行SAVE或BGSAVE命令来进行持久化;AOF失败,手动执行BGREWRITEAOF生成新AOF

(4)数据备份和恢复

(5)数据一致性检查

(6)定期备份、监控报警

6.2.4、big key排查

(1)命令bigkeys(4.0)、SCAN扫描大键

(2)分析大键类型

根据扫描结果,确定大键的类型,是字符串、哈希、列表、集合还是有序集合等

(3)GET命令查看大键的具体数据

(4)分析大建产生原因、优化存储数据结构

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/656577
推荐阅读
相关标签
  

闽ICP备14008679号