目 录CONTENT

文章目录

redis运维

简中仙
2023-01-31 / 0 评论 / 0 点赞 / 46 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
本文最后更新于2024-02-08,若内容或图片失效,请留言反馈。 本文如有错误或者侵权的地方,欢迎您批评指正!

redis运维主要是对redis的性能进行监控、导出数据、测试性能

一、性能监控指标

1、性能指标:Performance

NameDescription
latencyRedis响应一个请求的时间
instantaneous_ops_per_sec平均每秒处理请求总数
hi rate(calculated)缓存命中率(计算出来的)

2、内存指标:Memory

NameDescription
used_memory已使用内存
mem_fragmentation_ratio内存碎片率
evicted_keys由于最大内存限制被移除的key的数量
blocked_clients由于BLPOP,BRPOP,or BRPOPLPUSH而备阻塞的客户端

3、基本活动指标:Basic activity

NameDescription
connected_clients客户端连接数
conected_lavesslave数量
master_last_io_seconds_ago最近一次主从交互之后的秒数
keyspace数据库中的key值总数

4、持久性指标:Persistence

NameDescription
rdb_last_save_time最后一次持久化保存磁盘的时间戳
rdb_changes_sice_last_save自最后一次持久化以来数据库的更改数

5、错误指标: Error

NameDescription
rejected_connections由于达到maxclient限制而被拒绝的连接数
keyspace_misseskey值查找失败(没有命中)次数
master_link_down_since_seconds主从断开的持续时间(以秒为单位)

监控方式

redis-benchmark

redis-stat

redis-faina

redislive

redis-cli

monitor

showlog

1)get:获取慢查询日志

2)len:获取慢查询日志条目数

3)reset:重置慢查询日志

相关配置:

slowlog-log-slower-than 1000 # 设置慢查询的时间下线,单位:微秒

slowlog-max-len 100 # 设置慢查询命令对应的日志显示长度,单位:命令数

info(可以一次性获取所有的信息,也可以按块获取信息)

1)server:服务器运行的环境参数

2)clients:客户端相关信息

3)memory:服务器运行内存统计数据

4)persistence:持久化信息

5)stats:通用统计数据

6)Replication:主从复制相关信息

7)CPU:CPU使用情况

8)cluster:集群信息

9)Keypass:键值对统计数量信息

终端info命令使用

./redis-cli info 按块获取信息 | grep 需要过滤的参数
./redis-cli info stats | grep ops

交互式info命令使用

#./redis-cli 
> info server

性能监控:

redis-cli info | grep ops # 每秒操作数

内存监控:

# ./redis-cli info | grep used | grep human       
used_memory_human:2.99M  # 内存分配器从操作系统分配的内存总量
used_memory_rss_human:8.04M  #操作系统看到的内存占用,top命令看到的内存
used_memory_peak_human:7.77M # redis内存消耗的峰值
used_memory_lua_human:37.00K   # lua脚本引擎占用的内存大小

由于BLPOP,BRPOP,or BRPOPLPUSH而备阻塞的客户端

# ./redis-cli info | grep blocked_clients
blocked_clients:0  

由于最大内存限制被移除的key的数量

# ./redis-cli info | grep evicted_keys
evicted_keys:0

内存碎片率

# ./redis-cli info | grep mem_fragmentation_ratio
mem_fragmentation_ratio:2.74 

已使用内存

# ./redis-cli info | grep used_memory:
used_memory:3133624  

基本活动指标:

redis连接了多少客户端

通过观察其数量可以确认是否存在意料之外的连接。如果发现数量不对劲,就可以使用lcient list指令列出所有的客户端链接地址来确定源头。

# ./redis-cli info | grep connected_clients
connected_clients:1
# ./redis-cli info | grep connected
connected_clients:1   # 客户端连接数量
connected_slaves:1   # slave连接数量

持久性指标:

# ./redis-cli info | grep rdb_last_save_time
rdb_last_save_time:1591876204  # 最后一次持久化保存磁盘的时间戳
# ./redis-cli info | grep rdb_changes_since_last_save
rdb_changes_since_last_save:0   # 自最后一次持久化以来数据库的更改数

错误指标

由于超出最大连接数限制而被拒绝的客户端连接次数,如果这个数字很大,则意味着服务器的最大连接数设置得过低,需要调整maxclients

# ./redis-cli info | grep connected_clients
connected_clients:1

key值查找失败(没有命中)次数,出现多次可能是被黑客攻击

# ./redis-cli info | grep keyspace
keyspace_misses:0   

主从断开的持续时间(以秒为单位)

# ./redis-cli info | grep rdb_changes_since_last_save
rdb_changes_since_last_save:0  

复制积压缓冲区如果设置得太小,会导致里面的指令被覆盖掉找不到偏移量,从而触发全量同步

# ./redis-cli info | grep backlog_size
repl_backlog_size:1048576

通过查看sync_partial_err变量的次数来决定是否需要扩大积压缓冲区,它表示主从半同步复制失败的次数

# ./redis-cli info | grep sync_partial_err
sync_partial_err:1

二、命令工具

1、redis-cli命令行工具

# redis-cli
127.0.0.1:6379> ping             //连接本机上的 Redis 数据库,检测 Redis 服务是否启动
PONG
127.0.0.1:6379> info             //查看 Redis 服务的统计信息
127.0.0.1:6379> help @list             //查看所有与List数据类型相关的命令
127.0.0.1:6379> help set             //查看set命令的命令帮助
127.0.0.1:6379> exit             //退出数据库,或者quit
通讯消息类型说明
meet用于通知新节点加入,消息发送者通知接受者加入到当前集群,meet 消息通信正常完成后,接收节点会加入到集群中并进行ping、 pong 消息交换
ping集群内交换最频繁的消息,集群内每个节点每秒想多个其他节点发送 ping 消息,用于检测节点是否在线和交换彼此信息
Pong当接收到 ping,meet 消息时,作为相应消息回复给发送方确认消息正常通信,节点也可以向集群内广播自身的 pong 消息来通知整个集群对自身状态进行更新
fail当节点判定集群内另一个节点下线时,回向集群内广播一个fail 消息,其他节点收到 fail 消息之后把对应节点更新为下线状态

连接指定远程主机的 Redis 数据库

# redis-cli -h 127.0.0.1 -p 6379             //-h指定远程主机,-p指定Redis服务的端口号,-a指定密码(无密码可省略)

2、redis-benchmark 测试工具

基本命令语法如下:

redis-benchmark [option] [option value]

可选参数如下所示:

选项描述默认值
-h指定服务器主机名127.0.0.1
-p指定服务器端口6379
-s指定服务器 socket
-c指定并发连接数50
-n指定请求数10000
-d以字节的形式指定 SET/GET 值的数据大小2
-k1=keep alive 0=reconnect1
-rSET/GET/INCR 使用随机 key, SADD 使用随机值
-P通过管道传输请求1
-q强制退出 redis。仅显示 query/sec 值
--csv以 CSV 格式输出
-l生成循环,永久执行测试
-t仅运行以逗号分隔的测试命令列表。
-IIdle 模式。仅打开 N 个 idle 连接并等待。

1、向IP地址为192.168.1.20,端口为 6379 的Redis服务器发送100个并发连接与10000个请求测试性能

# redis-benchmark -h 192.168.1.20 -p 6379 -c 100 -n 100000
====== PING_INLINE ======
  100000 requests completed in 3.00 seconds
  100 parallel clients
  3 bytes payload
  keep alive: 1

0.01% <= 1 milliseconds
94.63% <= 2 milliseconds
99.63% <= 3 milliseconds
99.93% <= 4 milliseconds
99.97% <= 5 milliseconds
99.99% <= 6 milliseconds
100.00% <= 6 milliseconds
33311.12 requests per second
......

2、测试存取大小为100B的数据包的性能

# redis-benchmark -h 192.168.1.20 -p 6379 -q -d 100
PING_INLINE: 34071.55 requests per second
PING_BULK: 33990.48 requests per second
SET: 34059.95 requests per second
GET: 34083.16 requests per second
INCR: 34013.61 requests per second
LPUSH: 34364.26 requests per second
RPUSH: 35473.57 requests per second
LPOP: 35523.98 requests per second
RPOP: 35625.22 requests per second
SADD: 34094.78 requests per second
HSET: 33288.95 requests per second
SPOP: 33760.97 requests per second
LPUSH (needed to benchmark LRANGE): 33355.57 requests per second
LRANGE_100 (first 100 elements): 33932.81 requests per second
LRANGE_300 (first 300 elements): 34293.55 requests per second
LRANGE_500 (first 450 elements): 33658.70 requests per second
LRANGE_600 (first 600 elements): 33534.54 requests per second
MSET (10 keys): 32819.17 requests per second

3、测试本机上Redis服务在进行set与Ipush操作时的性能

# redis-benchmark -t set,lpush -n 100000 -q
SET: 71787.51 requests per second
LPUSH: 73637.70 requests per second

三、运维工具

1、数据导入导出工具

# git clone  https://github.com/vipshop/redis-migrate-tool.git
# cd redis-migrate-tool/
# autoreconf -fvi
# ./configure && make && make install
cat > redis_6379_to_6380.conf << EOF   
[source]
type: single
servers:
- 192.168.1.10:6379
 
[target]
type: redis cluster
servers:
- 192.168.1.10:6380 
 
[common]
listen: 0.0.0.0:8888
source_safe: true
EOF
# redis-migrate-tool -c redis_6379_to_6380.conf      //导入数据
# redis-migrate-tool -c redis_6379_to_6380.conf -C redis_check     //数据校验

2、分析键值大小

# yum -y install epel-release
# yum -y install python-pip gcc python-devel
# cd /opt/
# git clone https://github.com/sripathikrishnan/redis-rdb-tools
# cd redis-rdb-tools
# python setup.py install
# cd /opt/redis_cluster/redis_6379/
# ls
conf  logs  pid  redis.aof  redis.rdb
# rdb -c memory redis.rdb -f redis.rdb.csv
# awk -F ',' '{print $4,$2,$3,$1}' redis.rdb.csv |sort  > 6380.txt
# ls
6380.txt  conf  logs  pid  redis.aof  redis.rdb  redis.rdb.csv

3、监控过期键

cat 01get_key.sh 
#!/bin/bash
key_num=0
> key_name.log
for line in $(cat key_list.txt)
do
    while true
    do
        scan_num=$(redis-cli -h 192.168.47.75 -p 6380 SCAN ${key_num} match ${line}\* count 1000|awk 'NR==1{print $0}')
        key_name=$(redis-cli -h 192.168.47.75 -p 6380 SCAN ${key_num} match ${line}\* count 1000|awk 'NR>1{print $0}')
        echo ${key_name}|xargs -n 1 >> key_name.log
        ((key_num=scan_num))
        if [ ${key_num} == 0 ]
           then
           break
        fi
    done
done

4、动态调整内存

127.0.0.1:6379> CONFIG SET maxmemory 0      //不限制内存

5、内存分配策略

# vim /opt/redis_cluster/redis_6379/conf/6379.conf
vm.overcommit_memory = 0
参数说明
0(默认)表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。0 即是启发式的overcommitting handle,会尽量减少swap的使用,root可以分配比一般用户略多的内存
1表示内核允许分配所有的物理内存,而不管当前的内存状态如何,允许超过CommitLimit,直至内存用完为止。
2表示不允许超过CommitLimit值

四、影响Redis 性能的因素

1、网络带宽和延迟

网络带宽和延迟通常是最大短板。建议在基准测试之前使用 ping 来检查服务端到客户端的延迟。根据带宽,可以计算出最大吞吐量。 比如将 4 KB 的字符串塞入 Redis,吞吐量是 100000 q/s,那么实际需要 3.2 Gbits/s 的带宽,所以需要 10 GBits/s 网络连接, 1 Gbits/s 是不够的。 在很多线上服务中,Redis 吞吐会先被网络带宽限制住,而不是 CPU。 为了达到高吞吐量突破 TCP/IP 限制,最后采用 10 Gbits/s 的网卡, 或者多个 1 Gbits/s 网卡。

2、CPU

由于Redis是单线程模型,Redis 更喜欢大缓存快速 CPU, 而不是多核。

3、连接方式

如果服务器和客户端都运行在同一个机器上面,那么 TCP/IP loopback 和 unix domain sockets 都可以使用。对 Linux 来说,使用 unix socket 可以比 TCP/IP loopback 快 50%。 默认 redis-benchmark 是使用 TCP/IP loopback。 当大量使用 pipelining 时候,unix domain sockets 的优势就不那么明显了。

4、部署环境

Redis 在 VM 上会变慢。虚拟化对普通操作会有额外的消耗,Redis 对系统调用和网络终端不会有太多的 overhead。建议把 Redis 运行在物理机器上, 特别是当你很在意延迟时候。在最先进的虚拟化设备(VMWare)上面,redis-benchmark 的测试结果比物理机器上慢了一倍,很多 CPU 时间被消费在系统调用和中断上面。

五、缓存穿透和缓冲

1、缓存穿透(查不到)

缓存穿透:用户想要查询一个数据,发现 redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库査询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中(秒杀),于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。

解决方案:

布隆过滤器:布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。

1、布隆过滤器的起源,用途

布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

2、布隆过滤器的概念

如果想要判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定。链表,树等等数据结构都是这种思路. 但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢(O(n),O(logn))。不过世界上还有一种叫作散列表(又叫哈希表,Hash table)的数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了。这就是布隆过滤器的基本思想。

Hash面临的问题就是冲突。假设Hash函数是良好的,如果我们的位阵列长度为m个点,那么如果我们想将冲突率降低到例如 1%, 这个散列表就只能容纳m / 100个元素。显然这就不叫空间效率了(Space-efficient)了。解决方法也简单,就是使用多个Hash,如果它们有一个说元素不在集合中,那肯定就不在。如果它们都说在,虽然也有一定可能性它们在说谎,不过直觉上判断这种事情的概率是比较低的。

3、布隆过滤器的优缺点

1、优点

相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常数。另外, Hash函数相互之间没有关系,方便由硬件并行实现。布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。

布隆过滤器可以表示全集,其它任何数据结构都不能。

2、缺点

但是布隆过滤器的缺点和优点一样明显。误算率是其中之一。随着存入的元素数量增加,误算率随之增加。常见的补救办法是建立一个小的白名单,存储那些可能被误判的元素。但是如果元素数量太少,则使用散列表足矣。

另外,一般情况下不能从布隆过滤器中删除元素。我们很容易想到把位列阵变成整数数组,每插入一个元素相应的计数器加1, 这样删除元素时将计数器减掉就可以了。然而要保证安全的删除元素并非如此简单。首先我们必须保证删除的元素的确在布隆过滤器里面. 这一点单凭这个过滤器是无法保证的。另外计数器回绕也会造成问题。

在降低误算率方面,有不少工作,使得出现了很多布隆过滤器的变种。

4、应用场景

  • 网页URL 去重
  • 垃圾邮件识别
  • 黑名单
  • 查询加速【比如基于KV结构的数据】
  • 集合元素重复的判断
  • 缓存穿透

5、布隆过滤器的工作原理

布隆过滤器本身是一个很长的二进制向量,既然是二进制的向量,那么显而易见的,存放的不是0,就是1。

新建一个16位的布隆过滤器,如图

在这里插入图片描述

有一个对象,我们通过

  • 方式一计算他的hash值,得到hash = 2
  • 方式二计算他的hash值,得到hash = 9
  • 方式三计算他的hash值,得到hash = 5

通过三个方法计算得到三个数值,我们把这三个数值对应的布隆过滤器向量值改为1,表明该位置有值。

第二个对象,加入得到值1 6 3,就把1 6 3 改为1

对于布隆过滤器本身来说,并没有存储任何数据,只是计算该数据的位置,然后存储向量值

那么,如果需要判断某个数据是否存在于布隆过滤器,就只需要判断计算出来的所有向量值是否都为1即可

但是:

当存储的数据向量不断增多,就可能会出现,2 9 5 向量值都为1,但是实际上没有这个数据的情况,这样就导致了,布隆过滤器只能判断某个数据一定不存在,但是不能保证某个数据一定存在。

另外,因为一个向量位置可能被多个对象映射,所以,布隆过滤器无法删除数据

6、布隆过滤器的设计

布隆过滤器思路比较简单,但是对于布隆过滤器的随机映射函数设计,需要计算几次,向量长度设置为多少比较合适,这个才是需要认真讨论的。

如果向量长度太短,会导致误判率直线上升。
如果向量太长,会浪费大量内存。
如果计算次数过多,会占用计算资源,且很容易很快就把过滤器填满。

2、缓存缓冲(量太大)

这里需要注意和缓存击発的区別,缓存击穿,是指一个key非常热点,在不停的扛着大井发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来査询最新数据,并且回写缓存,会导使数据库瞬间压力过大。

解决方案

设置热点数据永不过期

从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题。

加互斥锁

分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。

3、缓存雪崩

缓存雪崩:是指在某一个时可段,缓存集中过期失效。 Redis宕机

产生雪崩的原因之ー,比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。

解决方案

redis高可用

这个思想的含义是,既然 redis有可能挂掉,那我多増设几台 redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群限流降级,这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

数据预热

数据加热的含义就是在正式部署之前,先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

0

评论区