redis阻塞问题

以下是学习笔记

  • 出现cpu过高的原因有:
    1、连接数过多,通过info clients查看
    2、慢查询,因为redis是单线程,如果有慢查询的话,会阻塞住之后的操作,通过redis日志查 待补充
    3、value值过大?比如value几十兆,当然这种情况比较少,其实也可以看做是慢查询的一种
    4、aof重写/rdb fork发生?瞬间会堵一下Redis服务器
# 修改慢查询时间与队列长度

# 方式一
修改配置文件
# The following time is expressed in microseconds, so 1000000 is equivalent
# to one second. Note that a negative number disables the slow log, while
# a value of zero forces the logging of every command.
# 这里默认是10ms 10毫秒
slowlog-log-slower-than 10000

# There is no limit to this length. Just be aware that it will consume memory.
# You can reclaim memory used by the slow log with SLOWLOG RESET.
# 慢日志队列长度
slowlog-max-len 128

# 方式二
config set slowlog-log-slower-than 20000
config set slowlog-max-len 1000
config rewrite
# 查看命令
# 显示队列长度
127.0.0.1:6379> SLOWLOG LEN
128

# 默认显示队列尾部的10个
127.0.0.1:6379> SLOWLOG GET

# 默认显示队列尾部的最后一个
127.0.0.1:6379> slowlog get 1
71057             // slowlog唯一编号id
1574822285        // 查询的时间戳
10184             // 查询的耗时(微秒),如表示本条命令查询耗时47微秒
KEYS              // 查询命令,完整命令为 KEYS history_1_*,slowlog最多保存前面的31个key和128字符
history_1_*
  • 对应解决方案:
    1、连接数过多解决:
    1.1 关闭僵尸连接
    采用redi-cli登录,采用client kill ip:port(redis远程连接的ip和端口)。
    需要采用脚本批量删除多个连接
    1.2 修改redis timeout参数
    采用redis-cli登录,采用config set timeout xx 设置redis的keepalive时间
    1.3 修改redis进程的文件数限制
    echo -n "Max open files 3000:3000" > /proc/PID/limits
    1.4 修改系统参数的最大文件数限制
    /etc/security/limits.conf
    2、对慢查询进行持久化,比如定时存放到mysql之类。(redis的慢查询只是一个list,超过list设置的最大值,会清除掉之前的数据,也就是看不到历史)
    3、限制key的长度和value的大小

  • 使用redis的注意事项:
    1、Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化。
    2、如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。
    3、为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内。
    4、尽量避免在压力较大的主库上增加从库
    5、为了Master的稳定性,主从复制不要用图状结构,用单向链表结构更稳定,即主从关系为:Master<--Slave1<--Slave2<--Slave3.......,这样的结构也方便解决单点故障问题,实现Slave对Master的替换,也即,如果Master挂了,可以立马启用Slave1做Master,其他不变
    6、使用Redis负载监控工具:redis-monitor,它是一个Web可视化的 redis 监控程序

针对keys*的解决方案

方案一:初步方案采用scan,一个基于游标的迭代器,进行处理

// jedis.jar的版本为3.1.0
ScanParams scanParams = new ScanParams();
scanParams.match(patternKey);
scanParams.count(1000);
ScanResult scanResult = jedis.scan(cursor, scanParams);

Redis的SCAN操作由于其整体的数据设计,无法提供特别准的scan操作,仅仅是一个“can't guarantee,just do my best”的实现:

  • 提供键空间的遍历操作,支持游标,复杂度O(1), 整体遍历一遍只需要O(N);
    提供结果模式匹配;
  • 支持一次返回的数据条数设置,但仅仅是个hints,有时候返回的会多;
  • 弱状态,所有状态只需要客户端需要维护一个游标;
  • 无法提供完整的快照遍历,也就是中间如果有数据修改,可能有些涉及改动的数据遍历不到;
  • 每次返回的数据条数不一定,极度依赖内部实现;
  • 返回的数据可能有重复,应用层必须能够处理重入逻辑;上面的示例代码中, redisTemplate.execute方法是个Set,相当于已经对于返回的key去重
  • count是每次扫描的key个数,并不是结果集个数。count要根据扫描数据量大小而定,Scan虽然无锁,但是也不能保证在超过百万数据量级别搜索效率;count不能太小,网络交互会变多,count要尽可能的大。在搜索结果集1万以内,建议直接设置为与所搜集大小相同。

方案二:主从集群,进行分离 待补充……

方案三:在放入之前想策略 待补充……

Redis 如何高效安全删除大 Hash Key

Redis 如何高效安全删除大 Hash Key

Redis删除大的集合键的耗时, 测试估算,可参考;和硬件环境、Redis版本和负载等因素有关

Key类型 Item数量 耗时
Hash ~100万 ~1000ms
List ~100万 ~1000ms
Set ~100万 ~1000ms
Sorted Set ~100万 ~1000ms

参看资料
redis cpu占用过高排查
SCAN 命令的基本用法

你可能感兴趣的:(redis阻塞问题)