Redis二

小功能大用处

·慢查询分析:通过慢查询分析,找到有问题的命令进行优化。
·Redis Shell:功能强大的Redis Shell会有意想不到的实用功能。
·Pipeline:通过Pipeline(管道或者流水线)机制有效提高客户端性能。
·事务与Lua:制作自己的专属原子命令。
·Bitmaps:通过在字符串数据结构上使用位操作,有效节省内存,为开发提供新的思路。
·HyperLogLog:一种基于概率的新算法,难以想象地节省内存空间。
·发布订阅:基于发布订阅模式的消息通信机制。
·GEO:Redis3.2提供了基于地理位置信息的功能。

慢查询分析

慢查询日志就是系统在命令执行前后计算每条命令的执行时间,当超过预设阀值,就将这条命令的相关信息(例如:发生时间,耗时,命令的详细信息)记录下来
img
慢查询只统计<执行命令>的时间,所以没有慢查询并不代表客户端没有超时问题。

慢查询的两个配置参数

·预设阀值怎么设置?
·慢查询记录存放在哪?

slowlog-log-slower-than # 预设阀值,单位是微秒,默认是10000,即10ms
slowlog-log-slower-than=0 # 会记录所有的命令
slowlog-log-slower-than<0 # 对于任何命令都不会进行记录

Redis使用了一个列表来存储慢查询日志,slowlog-max-len就是列表的最大长度,当列表长度超过这个值时,最老的记录会被删除

config set slowlog-log-slower-than 20000
config set slowlog-max-len 1000
config rewrite  # 持久化配置文件
slowlog get 10  # 查看最近的10条慢查询日志
标识id、发生时间戳、命令耗时、执行命令和参数
1) 1) (integer) 1
   2) (integer) 1749802836
   3) (integer) 97415
   4) 1) "config"
      2) "rewrite"
2) 1) (integer) 0
   2) (integer) 1749795393
   3) (integer) 12119
   4) 1) "zadd"
      2) "xulist"
      3) "251"
      4) "tom"

slowlog len  # 查看慢查询日志的长度
slowlog reset  # 清空慢查询日志

最佳实践

·slowlog-max-len配置建议:线上建议调大慢查询列表,记录慢查询时Redis会对长命令做截断操作,并不会占用大量内存。增大慢查询列表可以减缓慢查询被剔除的可能

·slowlog-log-slower-than配置建议:默认值超过10毫秒判定为慢查询,需要根据Redis并发量调整该值

·由于慢查询日志是一个先进先出的队列,如果慢查询比较多的情况下,会丢失慢查询命令,
为了防止这种情况发生,可以定期执行slow get命令将慢查询日志持久化到其他存储中(例如MySQL)

Redis Shell

redis-cli

redis-cli -r 10 -i 1 info | grep used_memory_human # 每隔1秒执行一次info命令,重复执行10次
echo 'wrold' | redis-cli -x set hello # 读取标准输入,并将其作为参数传递给redis-cli命令
-c(cluster)选项是连接Redis Cluster节点时需要使用的,-c选项可以防止moved和ask异常
-a(auth)选项,不需要手动输入auth命令
--scan选项和--pattern选项用于扫描指定模式的键,相当于使用scan命令。
--slave选项是把当前客户端模拟成当前Redis节点的从节点,可以用来获取当前Redis节点的更新操作

开启两个客户端
一个执行redis-cli --slave,然后持续监听
另一个执行set命令,会发现第一个客户端会收到对应的更新操作
--rdb选项会请求Redis实例生成并发送RDB持久化文件,保存在本地
--pipe选项用于将命令封装成Redis通信协议定义的数据格式,批量发送给Redis执行
--bigkeys选项使用scan命令对Redis的键进行采样,从中找到内存占用比较大的键值,这些键可能是系统的瓶颈
--eval选项用于执行指定Lua脚本
--latency选项可以测试客户端到目标Redis的网络延迟

redis-cli -h 1.1.1.10 --latency  # 测试客户端到目标Redis的网络延迟
min: 0, max: 1, avg: 0.12 (679 samples)

redis-cli -h 1.1.1.10 -i 2 --latency-history  # 每隔2秒打印一次网络延迟情况
min: 0, max: 1, avg: 0.20 (169 samples) -- 2.01 seconds range
min: 0, max: 1, avg: 0.24 (168 samples) -- 2.00 seconds range
min: 0, max: 1, avg: 0.17 (170 samples) -- 2.01 seconds range

redis-cli -h 1.1.1.10 --latency-dist  # 打印网络延迟的分布情况

redis-cli --stat # 实时打印Redis的各种统计信息

redis-cli get hello
"\xe4\xbd\xa0\xe5\xa5\xbd"
redis-cli --raw get hello  # 打印原始字符串,而不是转义后的字符串
你好

redis-server

redis-server --test-memory 1024 # 测试Redis分配内存是否正常

redis-benchmark

redis-benchmark可以为Redis做基准性能测试

redis-benchmark -c 100 -n 20000 # 100个客户端均执行20000次命令,对各类数据结构的命令进行测试,并给出性能指标
-q选项仅仅显示redis-benchmark的requests per second信息
-P选项代表每个请求pipeline的数据量
-k选项代表客户端是否使用keepalive,1为使用,0为不使用,默认值为1
-t选项可以对指定命令进行基准测试
--csv选项会将结果按照csv格式输出

Pipeline

Redis客户端执行一条命令分为如下四个过程:发送命令-->命令排队-->命令执行-->返回结果
Pipeline能将一组Redis命令进行组装,通过一次RTT传输给Redis,再将这组Redis命令的执行结果按顺序返回给客户端

原生批量命令与Pipeline对比

“原子性(Atomic)” 是指操作作为一个不可分割的整体执行,要么完全成功,要么完全失败
·原生批量命令是原子的,Pipeline是非原子的。
·原生批量命令是一个命令对应多个key,Pipeline支持多个命令。
·原生批量命令是Redis服务端支持实现的,而Pipeline需要服务端和客户端的共同实现。

事务与Lua

事务

事务表示一组动作,要么全部执行,要么全部不执行
Redis提供了简单的事务功能,将一组需要一起执行的命令放到multi和exec两个命令之间。
multi命令代表事务开始,exec命令代表事务结束,它们之间的命令是原子顺序执行的
Redis不支持事务中的回滚特性

Lua

Lua语言提供了如下几种数据类型:booleans(布尔)​、numbers(数值)​、strings(字符串)​、tables(表格)

Bitmaps

发布订阅

img
消息发布者和订阅者不进行直接通信,发布者客户端向指定的频道(channel)发布消息,订阅该频道的每个客户端都可以收到该消息

命令

publish channel:sports "Tim won the championship"  # 发布消息
subscribe channel:sports  # 订阅消息
unsubscribe channel:sports  # 取消订阅
psubscribe it*  # 订阅以it开头的频道
pubsub channels  # 查看订阅的频道
pubsub numsub channel:sports  # 查看订阅频道的信息
pubsub numpat  # 查看订阅模式的数量

·客户端在执行订阅命令之后进入了订阅状态,只能接收subscribe、psubscribe、unsubscribe、punsubscribe的四个命令。
·新开启的订阅客户端,无法收到该频道之前的消息,因为Redis不会对发布的消息进行持久化

使用场景

img

GEO

客户端

客户端通信协议

客户端发送一条set hello world命令给服务端,按照RESP的标准,客户端需要将其封装为如下格式(每行用\r\n分隔)​:

*3  # 参数数量为3个,即 set hello world这3个参数
$3  # 表示接下来的字符串长度为3
SET
$5
hello
$5
world

*3\r\n$3\r\nSET\r\n$5\r\nhello\r\n$5\r\nworld\r\n  # 实际传输格式

img
[客户端和服务端使用RESP标准进行数据交互]
img

python客户端reids-py

获取redis-py

pip install redis

easy_install redis

wget https:// github.com/andymccurdy/redis-py/archive/2.10.5.zip
unzip redis-2.10.5.zip
cd redis-2.10.5
#安装redis-py
python setup.py install

redis-py使用方法

import redis
client = redis.StrictRedis(host='127.0.0.1', port=6379)
key = "hello"
setResult = client.set(key, "python-redis")
print setResult
value = client.get(key)  
print "key:" + key + ", value:" + value

#1.string
#输出结果:True
client.set("hello","world")
#输出结果:world
client.get("hello")
#输出结果:1
client.incr("counter")
#2.hash
client.hset("myhash","f1","v1")
client.hset("myhash","f2","v2")
#输出结果:{'f1': 'v1', 'f2': 'v2'}
client.hgetall("myhash")
#3.list
client.rpush("mylist","1")
client.rpush("mylist","2")
client.rpush("mylist","3")
#输出结果:['1', '2', '3']
client.lrange("mylist", 0, -1)
#4.set
client.sadd("myset","a")
client.sadd("myset","b")
client.sadd("myset","a")
#输出结果:set(['a', 'b'])
client.smembers("myset")
#5.zset
client.zadd("myzset","99","tom")
client.zadd("myzset","66","peter")
client.zadd("myzset","33","james")
#输出结果:[('james', 33.0), ('peter', 66.0), ('tom', 99.0)]
client.zrange("myzset", 0, -1, withscores=True)

redis-py中Pipeline的使用方法

import redis
client = redis.StrictRedis(host='127.0.0.1', port=6379)
pipeline = client.pipeline(transaction=False)  # 开启pipeline,transaction=False代表不使用事务
pipeline.set("hello","world")
pipeline.incr("counter")
# 将命令封装到Pipeline中,此时命令并没有真正执行

result = pipeline.execute()  # 执行Pipeline中的命令

redis-py中的Lua脚本使用方法

eval
script_load
evalsha
script_load和evalsha函数要一起使用

import redis
client = redis.StrictRedis(host='127.0.0.1', port=6379)
script = "return redis.call('get',KEYS[1])"
scriptSha = client.script_load(script)
print client.evalsha(scriptSha, 1, "hello");

客户端管理

客户端API

client list  # 查看当前Redis服务端连接的客户端信息
(1)标识:id、addr、fd、name
·id:客户端连接的唯一标识,这个id是随着Redis的连接自增的,重启Redis后会重置为0
·fd:socket的文件描述符,与lsof命令结果中的fd是同一个,如果fd=-1代表当前客户端不是外部客户端,而是Redis内部的伪装客户端
·name:客户端的名字,后面的client setName和client getName两个命令会对其进行说明

(2)输入缓冲区:qbuf、qbuf-free
Redis为每个客户端分配了输入缓冲区,它的作用是将客户端发送的命令临时保存,同时Redis从会输入缓冲区拉取命令并执行,输入缓冲区为客户端发送命令到Redis执行命令提供了缓冲功能

qbuf:缓冲区的总容量
qbuf-free:缓冲区的剩余容量


每个客户端缓冲区的大小不能超过1G,超过后客户端将被关闭
/* Protocol and I/O related defines */
#define REDIS_MAX_QUERYBUF_LEN  (1024*1024*1024) /* 1GB max query buffer. */

输入缓冲区不受maxmemory控制
假设一个Redis实例设置了maxmemory为4G,已经存储了2G数据,但是如果此时输入缓冲区使用了3G,已经超过maxmemory限制,
可能会产生数据丢失、键值淘汰、OOM等情况
posted @ 2026-09-09 15:56  WiseHYH  阅读(14)  评论(0)    收藏  举报