redis 练习笔记(五)--- redis 功能

一,redis 慢查询

1.概述

慢查询日志就是系统在命令执行前后计算每条命令的执行时间,当超过预设阀值,就将这条命令的相关信息(慢查询ID,发生时间戳,耗时,命令的详细信息)记录下来,帮助开发和运维人员定位系统存在的慢操作。

redis命令生命周期:发送 排队 执行 返回。慢查询只统计第3个步骤 执行的时间

注意:

i,慢查询只记录命令在redis的执行时间,不包括排队、网络传输时间
ii,慢查询是先进先出的队列,访问日志记录出列丢失,需定期执行slow get,将结果存储到其它设备中(如mysql)
 

2.预设阀值

编辑配置文件 redis.conf

 

slowlog-log-slower-than   设置阀值,单位微秒

(默认为10毫秒,根据redis并发量来调整,对于高并发比建议为1毫秒)

slow-max-len  慢查询记录存放的最大条数 0记录所有命令 -1命令都不记录 

(线上可加大slow-max-len的值,记录慢查询存长命令时redis会做截断,不会占用大量内存,线上可设置1000以上)

(慢查询记录也是存在队列里的,slow-max-len 存放的记录最大条数,比如设置的slow-max-len=10,当有第11条慢查询命令插入时,队列的第一条命令就会出列,第11条入列到慢查询队列中, 可以config set动态设置,也可以修改redis.conf完成配置。)

 

3. 命令

slowlog get 获取队列里慢查询的命令

slowlog len 获取慢查询列表当前的长度

slowlog reset  对慢查询列表清理(重置)

 

 

二,redis组件常用功能

1.redis-cli

./redis-cli -r 3 -h 127.0.0.1 -p 6380 -a 654670150 ping  连接测试,-r 表示测试次数

./redis-cli -r 100 -i 1 info |grep used_memory_human 每秒输出内存使用量,输100次, -i 代表执行时间,单位为秒

redis-cli --help redis-cli 的所有参数

2.redis-server

./redis-server ./redis.conf  & 指定配置文件在后台运行redis服务

./redis-server --test-memory 1024 检测操作系统能否提供1G内存给redis, 常用于测试,想快速占满机器内存做极端条件的测试,可使用这个指令.或 redis上线前,做一次测试

 

3. redis-benchmark 

redis-benchmark -h 127.0.0.1 -c 100 -n 10000    100个客户端同时请求redis,共执行10000次,检测host为localhost 端口为6379的redis服务器性能 .该指令会对各类数据结构的命令进行测试

redis-benchmark -h 192.168.1.111 -p 6379 -q -d 100   测试存取大小为100字节的数据包的性能

redis-benchmark -h 192.168.1.111 -t set,lpush -n 100000 -q   只测试 set,lpush操作的性能,-q只显示每秒钟能处理多少请求数结果

redis-benchmark -h 192.168.1.111 -n 100000 -q script load "redis.call('set','foo','bar')"  只测试某些数值存取的性能, 比如说我在慢查询中发现,大部分为set语句比较慢,我们自己可以测一下Set是不是真的慢,

 

三,Pipeline

1.概述

RTT: Round Trip Time 往返时间,比如redis客户端执行一条命令(发送命令-〉命令排队-〉命令执行-〉返回结果)的整个过程。

mget ,mset 有效的节约了RTT,但是大部分命令,如hgetall 并不支持批量操作,需要消耗N次RTT,这个时候需要pipeline来解决这个问题。

未使用pipeline执行N条命令图解:

使用pipeline 执行N条命令图解:

使用pipeline VS 不使用pipeline  性能对比:

(使用pipeline执行速度比逐条执行要快,客户端与服务端的网络延迟越大,性能体现越明显)

原生批命令 VS pipeline 

i.  原生批命令是原子性,pipeline是非原子性。

ii. 原生批命令一命令多个key, 但pipeline支持多命令(存在事务),非原子性

iii.原生批命令是服务端实现,而pipeline需要服务端与客户端共同完成

 

(使用pipeline组装的命令个数不能太多,不然数据量过大,增加客户端的等待时间,还可能造成网络阻塞,可以将大量命令的拆分多个小的pipeline命令完成)

 

2. 事务

pipeline是多条命令的组合,为了保证它的原子性,redis提供了简单的事务,,不支持事务回滚

i.redis的简单事务,将一组需要一起执行的命令放到multi和exec两个命令之间,其中multi代表事务开始,exec代表事务结束

ii. 停止事务discard

iii.redis不支持回滚功能

命令错误,语法不正确,导致事务不能正常结束

运行错误,语法正确,但类型错误,事务可以正常结束

 

iv.watch 

使用watch 后 multi 失效,事务失效

 

3. lua 语音和 redis

lua: Lua是可扩展的轻量级编程语言,它是用C语言编写的,类似于存储过程

a 使用脚本的好处:

i. 减少网络开销(减少了网络往返时延)

ii.原子性(Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入)

iii.复用性

 

b.lua 语法

while 循环 ,字段初始化,输出 

local int sum = 0
local int i = 0
while i <= 100
do 
    sum = sum +i
    i = i+1
end 
print(sum)

数组初始化,for循环   条件判断逻辑

local tables myArray = {"james","java",false,34}
local int sum = 0
print(myArray[3])
for i = 1,100
do
    sum = sum +1 
end 
print(sum)
for j = 1,#myArray
do 
    print(myArray[j])
    if myArray[j] == "james"
    then 
        print("true")
        break;
    else 
        print("false")
    end 
end 

 

4. 实例

实现访问频率限制: 实现访问者 $ip 127.0.0.1在一定的时间 $time 20S内只能访问 $limit 10次

解决方案:

a. java 

private boolean accessLimit(String ip, int limit,
 int time, Jedis jedis) {
    boolean result = true;

    String key = "rate.limit:" + ip;
    if (jedis.exists(key)) {
        long afterValue = jedis.incr(key);
        if (afterValue > limit) {
            result = false;
        }
    } else {
        Transaction transaction = jedis.multi();
        transaction.incr(key);
        transaction.expire(key, time);
        transaction.exec();
    }
    return result;
}

缺点:

i. 可能会出现竞态条件,解决方法是用 WATCH 监控 rate.limit:$IP 的变动, 但较为麻烦;

ii.最多需要向Redis请求5条指令, 传输过多

 

b.lua

ipcount.lua

local key = KEYS[1]
local limit = tonumber(ARGV[1])
local expire_time = tonumber(ARGV[2])

local is_exists = redis.call("exists",key)
if is_exists == 1 then
        if redis.call("incr",key) > limit then
                return 0
        else
                return 1
        end
else
        redis.call("set",key,1)
        redis.call("expire",key,expire_time)
        return 1
end

指令:

./redis-cli -p 6379 -a 654670150 --eval ./ipcount.lua  192.168.31.99 , 10 120 ttl rate.limit:127.0.0.1

原理图:

redis对lua脚本的管理:

script load "$(cat random.lua)"  将LUA脚本内容加载到redis

script exists afe90689cdeec602e374ebad421e3911022f47c0  检查sha1值的LUA脚本是否加载到redis中

script flush

script kill

 

 

四,发布订阅

1. 概述

 redis提供了“发布、订阅”模式的消息机制,其中消息订阅者与发布者不直接通信,发布者向指定的频道(channel)发布消息,订阅该频道的每个客户端都可以接收到消息

 

 

2.功能

redis主要提供发布消息、订阅频道、取消订阅以及按照模式订阅和取消订阅

i. 发布消息

publish channel message

ii.订阅频道

subscribe channel [channel ...]

iii.查看订阅数

pubsub numsub channel 

iv.取消订阅

unsubscribe [channel [channel ...]]

v.按照模式 订阅 和 取消订阅

psubscribe ch*   订阅以ch开头的所有频道

punsubscribe ch*   //取消以ch开头的所有频道

3. 应用

> 今日头条订阅号、微信订阅公众号、新浪微博关注、邮件订阅系统
> 即使通信系统
> 群聊部落系统(微信群)
eg:

微信班级群 class:20170101

    a、学生C订阅一个主题叫 :class:20170101

        >subscribe class:20170101

    b、学生A针对class:20170101主体发送消息,那么所有订阅该主题的用户都能够接收到该数据。

        >publish class:20170101 "hello world! I am A"

    c、学生B针对class:20170101主体发送消息,那么所有订阅该主题的用户都能够接收到该数据。

        >publish class:20170101 "hello world! I am B"

    展示学生C接受到的A\B同学发送过来的消息信息

        1) "subscribe"

        2) "class:20170101"

        3) (integer) 1

        1) "message"

        2) "class:20170101"

        3) "hello world! I am A"

        1) "message"

        2) "class:20170101"

        3) "hello word! I am B"

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值