一站式学习Redis, 从入门到高可用分布式实践-04redis其它功能
04-瑞士军刀redis其它功能
- 慢查询
- 
生命周期、两个配置、三个命令、运维经验 
 ![]() 
- 
生命周期两点说明: 
 慢查询发生在第三阶段(执行命令);
 客户端超时不一定是慢查询,但是慢查询是客户端超时的一个可能因素
- 
两个配置: 
- 
slowlog-max-len: 
 先进先出队列、固定长度、保存在内存内
- 
slowlog-log-slower-than: 
 慢查询阈值(单位:微秒)、
 slowlog-log-slower-than=0,记录所有命令
 slowlog-log-slower-than<0,不记录任何命令
- 
默认值 
 config get slowlog-max-len
 config get slowlog-log-slower-than
- 
修改配置文件重启,不建议 
- 
动态配置 
 config set slowlog-max-len 1000
 config set slowlog-log-slower-than 1000
- 
慢查询命令 
 slowlog get [n] 获取慢查询队列
 slowlog len 获取慢查询队列长度
 slowlog reset 清空慢查询队列
- 
运维经验 
 slowlog-log-slower-than不要设置过大,默认值是10ms,通常设置1ms
 slowlog-max-len慢查询队列大小,默认值是128
 理解命令的生命周期
 定期持久化慢查询
- pipeline
 (1)什么是流水线、客户端时间、与原生操作对比、使用建议
 (2)什么是流水线
 ![]() 
 一次pipeline(n条命令) = 一次网络时间+n次命令时间
 (3)流水线的作用
 ![]() 
- reids的命令时间是微秒级别的
- pipeline每次条数要控制网略
 (4)流水线的作用-续
 ![]() 
 (5)流水线pipeline效率比对
import time
import redis
pool = redis.ConnectionPool(host="xxxxx", port=6382, db=1, password="xxxx")
r = redis.Redis(connection_pool=pool)
# 不使用pipeline时
"""
# 计时开始
start = time.time()
for i in range(10000):
    r.hset(f"hashkey:{i}", f"field{i}", f"value{i}")
print(time.time() - start)  # 执行时间312秒
"""
# 使用pipeline时
start = time.time()
for i in range(100):
    pipe = r.pipeline()  # 管道/流水线默认是原子的,也可以关闭transaction=False
    for j in range(100*i, 100*(i+1)):
        pipe.hset(f"hashkey:{j}", f"field{j}", f"value{j}")
    pipe.execute()
print(time.time() - start)  # 执行耗时7s, 比上面不使用pipeline快了40多倍
# 使用pipeline时-2调整每次传输100个命令为1000个命令,效率又显著提高了
start = time.time()
for i in range(10):
    pipe = r.pipeline()  # 管道/流水线默认是原子的,也可以关闭transaction=False
    for j in range(1000*i, 1000*(i+1)):
        pipe.hset(f"hashkey:{j}", f"field{j}", f"value{j}")
    pipe.execute()
print(time.time() - start)  # 执行耗时1s, 比上面不使用pipeline快了300多倍
(6)使用建议
- 注意每次pipeline携带的数据量
- pipeline每次只能作用在一个redis节点上
- M操作与pipeline的区别
- 发布订阅
 (1)角色、模型、API、发布订阅与消息队列
 (2)角色:发布者publisher、订阅者subscriber、频道channel
 (3)模型:
 ![]() 
 (4)发布订阅角色和模型
 ![]() 
 (5)发布订阅API
 publish subscribe unsubscribe 其它
 (6)发布订阅案例
 一个发布者,两个订阅者
- 两个订阅者
import redis
from threading import Thread, current_thread
pool = redis.ConnectionPool(host="xxxxxx", port=6382, db=0, password="xxxxxx")
r = redis.Redis(connection_pool=pool)
class PubSub(object):
    def __init__(self):
        self.pub = r.pubsub()
    def subscribe(self, *args):
        self.pub.subscribe(*args)
        self.pub.parse_response()
        self.pub.parse_response()
        return self.pub
def subscribe(p):
    while True:
        msg = p.parse_response()
        for i in msg:
            print(current_thread().name, i.decode(encoding="utf8"))
if __name__ == '__main__':
    # 开启一个订阅者
    t1 = Thread(target=subscribe, args=(PubSub().subscribe("my-first-channel", "my-second-channel"),))
    t1.start()
    # 开启第二个订阅者
    t2 = Thread(target=subscribe, args=(PubSub().subscribe("my-first-channel", "my-third-channel"),))
    t2.start()
    # 等待所有子线程结束,主线程在结束
    t1.join()
    t2.join()
- 一个发布者
import redis
pool = redis.ConnectionPool(host="xxxxxx", port=6382, db=0, password="xxxxx")
r = redis.Redis(connection_pool=pool)
r.publish("my-first-channel", "first:哈哈哈")
r.publish("my-second-channel", "second:嘿嘿嘿")
r.publish("my-third-channel", "third:呵呵呵")
- 
bitmap 
- 
HyperLogLog 
 (1)新的数据结构
 基于hyperloglog算法:极小空间完成独立数量统计
 本质还是字符串
 (2)三个命令
 pfadd key element [element] 向hyperloglog中添加元素
 pfcount key 计算Hyperloglog独立总数
 pfmerge destkey sourcekey [sourcekey ...] 合并多个hyperloglog
 (3)内存消耗
 (4)使用经验
 
                    
                     
                    
                 
                    
                






 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号