本章将介绍以下内容:

        慢查询分析:通过慢查询分析,找到有问题的命令进行优化

        Redis Shell:功能强大的Redis Shell会有意想不到的使用功能

        Pipeline:通过Pipeline机制有效提供客户端性能

        事务与Lua:制作自己的专属原子命令

        Bitmaps:通过在字符串数据结构上使用位操作,有效节省内存,为开发提供新的思路

        HyperLogLog:一种基于概率的新算法,难以想象地节省内存空间

        GEO:Redis3.2 提供了基于地理位置信息的功能

    3.1 慢查询分析

        慢查询日志:系统在命令执行前后计算每条命令的执行时间,当超过预设阀值,就将这条命令的相关信息记录下来

        Redis客户端执行一条命令:

       第3章 小功能大用处

        3.1.1 慢查询的两个配置参数

            预设阀值设置:slowlog-log-slower-than和slowlog-max-len配置来解决这两个问题。

            Redis两种修改配置的方法:一种是修改配置文件,另一种是使config set命令动态修改

            config set slowlog-log-slower-than 20000

            config set slowlog-max-len 1000

            config rewrite

            1 获取慢查询日志 slowlog get

            2 获取慢查询日志的长度 slowlog len

            3 慢查询日志重置 slowlog reset

        3.1.2 最佳实践

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

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

            慢查询只记录命令的执行时间,并不包含命令排队和网络传输时间。

            由于慢查询日志是一个先进先出的队列,慢查询比较多的时候,会丢失部分慢查询命令,可以定期执行slow get命令将慢查询日志持久化到其他存储中,然后制作可视化的界面进行查询

    3.2 Redis Shell

            3.2.1 redis-cli详解

            3.2.2 redic-server详解

            3.2.3 redis-benchmark详解

    3.3 Pipeline

            3.3.1 Pipeline概念

                   Redis客户端执行一条命令分为如下四个过程:1 发送命令 2 命令排队 3 命令执行 4 返回结果 RTT往返时间

                   Pipeline 将一组Redis命令进行组装,通过一次RTT传输给Redis,再将这组Redis命令执行的结果按顺序返回给客户端

                   redis-cli的--pipe选项实际上就是使用了Pipeline机制,

            3.3.2 性能测试

                    Pipeline执行速度一般比逐条执行要快

                    客户端和服务端的网络延时越大,Pipe的效果越明显

                    

第3章 小功能大用处

            3.3.3 原生批量命令与Pipeline对比

                    原生批命令是原子的,Pipeline是非原子的

                    原生批命令是一个命令对应多个key,Pipeline支持多个命令

                    原生批命令是Redis服务端支持实现的,而Pipeline需要服务端和客户端的共同实现

            3.3.4 最佳实践

                     Pipe虽然好用,但是每次Pipeline组装的命令个数不能没有节制,否则一次组装的Pipeline数据量过大,一方面会增加客户端的等待时间,另一方面会造成一定的网络阻塞,可以将一次包含大量命令的Pipeline拆分成多次小的Pipeline来完成

    3.4 事务与Lua

    为了保证多条命令组合的原子性,Redis提供了简单的事务功能以及集成Lua脚本来解决这个问题

             3.4.1 事务

                Redis提供了简单的事务功能,将一组需要一起执行的命令放到multi和exec两个命令之间。停止事务的执行,可以使用discard命令代替exec命令即可。Redis不支持事务中的回滚特性

             3.4.2 Lua用法简述

                1 数据类型及其逻辑处理

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

                    一 字符串 

                        local strings val="world"

                        local代表val是一个局部变量,没有代表全局变量

                        --是Lua的注释

                    二 数组

                        lua的数组下标从1开始计算

                        local table myArray={"redis","jedis",true,88.0}

                        print(myArray[3])

                           for 

                                关键字for以end作为结束符

                                 local int sum=0

                                 for i=1,100

                                 do 

                                      sum=sum+i;

                                 end

                                 print(sum)

                                要遍历myArray,首先需要知道tables长度,只需要在变量前加一个#

                                Lua还提供了内置函数ipairs,使用for index,value ipairs(tables)可以遍历出所有索引下标和值

                               for index.value in ipairs(myArray)

                                    do 

                                        print(index)

                                        print(value)

                                    end

                            while循环

                                local int sum=0

                                local int i=0

                                while i<=100

                                do 

                                    sum=sum+i

                                       i=i+1

                                end

                                print(sum)

                            if else

                               要确定数组中是否包含了jedis,有则打印true

                                local table myArray={"redis","jedis",true}

                                for i=1,#myArray

                                do 

                                    if myArray[i]=="jedis"

                                    then 

                                        print(true)

                                        break

                                     else 

                                            do nothing

                                      end

                                  end

                            三 哈希

                                  local tables user_1={age=28,name="tom"}

                                  print("user_1 age is"..user_1["age"])

                2 函数定义

                      函数以function开头,以end结尾,funcName是函数名

                         function funcName()

                          end

                          function contact(str1,str2)

                               return str1..str2

                          end

             3.4.3 Redis与Lua

                1 在Redis中使用Lua

                    在Redis中执行Lua脚本两种方法:eval和evalsha

                    1 eval 脚本内容 key个数 key列表 参数列表 如果Lua脚本较长,还可以使用redis-cli-eval直接执行文件

                    2 evalsha 

`                        

第3章 小功能大用处

                 加载脚本:script load命令可以将脚本内容加载到Redis内存中

                 执行脚本:evalsha的使用方法,参数使用SHA1值,执行逻辑和eval一致

                2 Lua的Redis API

                    Lua可以使用redis.call函数实现对Redis的访问。

                    redis.pcall会忽略错误继续执行

                 开发提示:Lua可以使用redis.log函数将Lua脚本的日志输出到Redis的日志文件中,但是一定要控制日志级别

             3.4.4 案例

                    三个好处:Lua脚本在Redis是原子执行的,执行过程中间不会插入其他命令,Lua脚本可以帮助开发和运维人员创造出自己定制的命令,并可以将这些命令常驻在Redis内存中,实现复用的效果,可以将多条命令一次性打包,有效的减少网络开销

                     local mylist=redis.call{"lrange",KEYS[1],0,-1}

                     local count=0

                     for index,key in ipairs(mylist)

                      do 

                        redis.call("incr",key)

                        count=count+1

                      end

                    return count

             3.4.5 Redis如何管理Lua脚本

                 Redis提供了4个命令实现对Lua脚本的管理

                    1 script load script  将Lua脚本加载到Redis内存中

                    2 script exists 用于判断sha1是否已经加载到Redis内存中

                    3 script flush 清除Redis内存已经加载的所有Lua脚本

                    4 script kill 用于杀掉正在执行的Lua脚本

    3.5 Bitmaps

             3.5.1 数据结构模型

                Redis提供了Bitmaps这个“数据结构”可以实现对位的操作

                   Bitmaps本身不是一种数据结构,实际上它就是字符串,但是它可以对字符串进行位操作

                   Bitmaps单独提供了一套命令,所以在Redis中使用字符串的方法不太相同

             3.5.2 命令

                    将每个独立用户是否访问过网站存放在Bitmaps中,将访问过的用户记做1,没有访问的用户记做0,用偏移量作为用户的id

                    1 设置值 setbit key offset value setbit unique:user:2016-04-05 0 1

                    2 获取值 gitbit key offset     

                    3 获取Bitmaps制定范围值的个数 bitcount unique:users:2016-04-05

                    4 Bitmaps间的运算 bitop op destkey key

                    5 计算Bitmaps中第一个值为targetBit的偏移量 bitpos key targetBit的偏移量

             3.5.3 Bitmaps分析

                      数据量大的情况下,使用Bitmaps比集合要好

    3.6 HyperLogLog

            是一种基数算法,可以利用极小的内存空间完成独立总数的统计,数据集可以是IP、Email、ID等

            1 添加 pfadd key element 

                    pfadd 2016_03_06:unque:ids "uuid-1" "uuid-2" "uuid-3" "uuid-3" "uuid-4"

            2 计算独立用户数 pfcount key

                    pfcount 2016_03_06:unque:ids

            3 合并 pfmerge destkey sourcekey 

                    pfadd 2016_03_06:unque:ids "uuid-1" "uuid-2" "uuid-3" "uuid-4" "uuid-5"

                    pfadd 2016_03_06:unque:ids "uuid-6" "uuid-7"

                    pfmerge 2016_03_06:unque:ids 2016_03_06:unque:ids 2016_03_05:unque:ids

            只为了计算独立总数,不需要获取单条数据,可以容忍一定误差率,毕竟在内存占有量上有很大的优势

    3.7 发布订阅

            Redis提供了基于发布订阅模式的消息机制,消息发布和订阅者不进行直接通信,发布者客户端向指定的频道(channel)发布消息,订阅该频道的每个客户度都可以收到该消息

第3章 小功能大用处               

               3.7.1 命令

                    1 发布消息 publish channel message

                    2 订阅消息 subscribe channel 订阅者可以订阅一个或多个频道

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

                    3 取消订阅 unsubscribe channel 

                    4 暗示模式订阅和取消订阅 psubscribe pattern 

                    5 查询订阅  

                        查看活跃的频道 pubsub channels

                        查看频道订阅数 pubsub numsub channel

                        查看模式订阅数 pubsbu numpat 

               3.7.2 使用场景 

第3章 小功能大用处

                    视频服务订阅到video:changes频道下 subscribe video:changes

                    视频管理系统发布消息到video:changes频道如下 publish video:changes "video1,video2,video3"

                    视频服务收到消息,对视频信息进行更新 for video in video1,video2,video3

                                                                                    update{video}                       

    3.8 GEO

                1 增加地理位置信息 geoadd key longitude latitude member 分别是经度,纬度,成员

                2 获取地理位置信息 geopos key member

                3 获取两个地理位置的距离 geodist key member1 member2 unit

                4 获取指定位置范围内的地理信息位置集合

                5 获取geohash geohash key member

                        Redis使用geohash将二维经纬度转换为一维字符串,下面操作会返回beijing的geohash值

                        geohash有如下特点:

                            GEO的数据类型为zset,Redis将所有地理位置信息的geohash存放在zset中、

                            字符串越长,表示的位置更精确

                            两个字符串越相似,它们之间的距离越近,Redis利用字符串前缀匹配算法实现相关的命令

                            geohash编码和经纬度是可以互相转换的

                6 删除地理位置信息 zrem key member 

                      因为GEO的底层实现是zset,所以借用zrem命令实现对地理位置信息的删除

    3.9 本章重点回顾

相关文章:

  • 2021-05-16
  • 2022-12-23
  • 2022-12-23
  • 2022-01-20
  • 2022-12-23
  • 2021-11-20
  • 2021-11-14
  • 2022-12-23
猜你喜欢
  • 2021-07-04
  • 2021-10-07
  • 2021-05-03
  • 2021-12-12
  • 2021-06-02
  • 2022-03-07
  • 2021-05-02
相关资源
相似解决方案