zoukankan      html  css  js  c++  java
  • Redis学习笔记三:删除策略和高级数据结构

    这是Redis学习笔记的第三篇,这篇主要讲Redis的删除策略和高级数据结构。

    数据删除

    讲数据删除策略之前我们得先了解什么是过期数据?

    其实之前我们就已经接触过数据得时限,Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态:

       XX :具有时效性的数据
       -1 :永久有效的数据
       -2 :已经过期的数据 或 被删除的数据 或 未定义的数据

    那么也就是说过期的数据指的是我们给他指定了期限,然后时间到期的数据。

    那么这些数据是真的一到期Redis就把它们删除了吗,显然这个任务是很困难的,要达到这个目的Redis要时刻监视所有的数据的时间。

    所有我们延时删除数据,于是我们就需要对过期数据做数据删除策略。

    我们有三个数据删除策略:1,定时删除  2,惰性删除  3,定期删除

     

     在讲到三种删除策略之前,我们先看这张图,可以发现:我们可以通过“EXPIRE”/“PEXPIRE”来指定key过期的时间(秒/毫秒),然后具有“过期”时间的key将会被添加到expires集合中,那么我们的删除策略就是在这个expires上做文章。

    定时删除

    人如其名,这个策略就是定时删除过期数据。具体为:创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作。

    很好理解,就是定时去看看所有的有期限的key,发现过期的就删掉。

     优点:节约内存,到时就删除,快速释放掉不必要的内存占用
     缺点:CPU压力很大,无论CPU此时负载量多高,均占用CPU,会影响redis服务器响应时间和指令吞吐量
    其实际就是用处理器性能换取存储空间 (拿时间换空间)。

    惰性删除

    数据到达过期时间,不做处理。等下次访问该数据时  ①如果未过期,返回数据。  ②发现已过期,删除,返回不存在。

    这个也比较好理解,就是我们不刻意去做删除。等到有机会访问该数据时,再对这个数据做删除判断,如果发现过期则删除(Redis:看到这个数据了吗,丢掉也不给你

     优点:节约CPU性能,发现必须删除的时候才删除
     缺点:内存压力很大,出现长期占用内存的数据
    其实际是用存储空间换取处理器性能(拿时间换空间)

    定期删除

    定时删除是上诉两种极端方法的折中。它周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度。

     这个策略会复杂一些,我直接配合黑马程序员的图来讲了,首先在以前我们说过数据库其实不止一个(默认是16个,我们可以通过select去选择数据库),那么expires集合也不止一个(和数据库个数一样多)。那么这个定期删除策略就是CPU拿出250ms事件去做删除这件事,扫一个数据库期限集合expires的时间是250ms/server.hz(可以理解为一个时间片),那么每一个时间片我们对某个expires[]进行检测:

    对某个expires[*]检测时,随机挑选W个key检测(这是一个时间片做的事情)
       如果key超时,删除key
       如果一轮中删除的key的数量>W*25%,循环该过程(即对这个比较多垃圾的库再用一个时间片)
       如果一轮中删除的key的数量≤W*25%,检查下一个expires[*],0-15循环(这个库垃圾不多,下一个)

    那么大志就是这么一个流程了。另外要提的是redis用current_db来保证当前在扫哪个库,然后其实上诉的W可以通过ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP调整。


       特点1:CPU性能占用设置有峰值,检测频度可自定义设置
       特点2:内存压力不是很大,长期占用内存的冷数据会被持续清理
    其实际是周期性抽查存储空间(随机抽查,重点抽查)

    逐出算法

    上面讲的删除策略都是对有期限的数据的策略。我们考虑这种情况:可能是永久数据太多,可能是redis删除不够快导致有新数据想进入redis时候,内存不足了。于是就有了我们的逐出算法:

    Redis使用内存存储数据,在执行每一个命令前,会调用freeMemorylfNeeded()检测内存是否充足。如果内存不满足新加入数据的最低存储要求,redis要临时删除一些数据为当前指令清理存储空间。清理数据的策略称为逐出算法

    逐出算法的配置

    maxmemory

    最大可使用内存。作用是:占用物理内存的比例,默认为0,表示不限制。生产环境中根据需求设定,通常设置在50%以上

    maxmemory-samples
    

    每次选取待删除数据的个数。作用是:类似上面的定期删除策略,逐出算法选取数据时并不会全库扫描,导致严重的性能消耗,降低读写性能。因此采用随机获取数据的方式作为待检测删除数据

    maxmemory-policy
    

    删除策略。作用是:达到最大内存后的,对被挑选出来的数据进行删除的策略

    逐出算法删除策略

    有以下八种策略,大家都学过操作系统应该很好懂就不细讲了。

     检测易失数据(可能会过期的数据集server.db[i].expires )
      ① volatile-lru:挑选最近最少使用的数据淘汰
      ② volatile-lfu:挑选最近使用次数最少的数据淘汰
      ③ volatile-ttl:挑选将要过期的数据淘汰
      ④ volatile-random:任意选择数据淘汰
     检测全库数据(所有数据集server.db[i].dict )
      ⑤ allkeys-lru:挑选最近最少使用的数据淘汰
      ⑥ allkeys-lfu:挑选最近使用次数最少的数据淘汰
      ⑦ allkeys-random:任意选择数据淘汰
     放弃数据驱逐
      ⑧ no-enviction(驱逐):禁止驱逐数据(redis4.0中默认策略),会引发错误OOM(Out Of Memory)

    Redis服务器配置

    我们之前提到过redis的conf文件,我们通常建议以conf文件启动redis服务器端,那么这里再补充一些常用到的配置。

    设置服务器以守护进程的方式运行

    deamonize yes|no

    绑定主机地址,绑定之后就只有这个ip能访问

    bind 127.0.0.1

    设置服务器端口号,用哪个端口

    port 6379

    设置数据库数量,之前多次说到的数据库数量其实可以调的

    databases 16
    

    日志配置:

    设置服务器以指定日志记录级别

    loglevel debug|verbose|notice|warning

    日志记录文件名

    logfile 端口号.log
    

    客户端配置

    设置同一时间最大客户端连接数,默认无限制。当客户端连接到达上限,Redis会关闭新的连接

    maxclients 0

    客户端闲置等待最大时长,达到最大值后关闭连接。如需关闭该功能,设置为 0

    timeout 300
    

    多服务器快捷配置

    导入并加载指定配置文件信息,用于快速创建redis公共配置较多的redis实例配置文件,便于维护(就是想C的include功能来导入配置文件

    include /path/server-端口号.conf
    

    高级数据结构

    在第一篇学习笔记主要讲的就是redis的5中数据结构,那5中式redis最最最常用的。这里再补充三种高级点的数据结构,它并不那么常用,但是能提供的功能也高级一点。

    Bitmaps

    bitmap是什么,这个也是比较常见的数据结构了。那么再redis这里也一样,bitmap就是二进制位来保存0/1信息的数据结构。

    bitmap最基础的两个操作

    获取指定key对应偏移量上的bit值:

    getbit key offset

    设置指定key对应偏移量上的bit值,value只能是1或0:

    setbit key offset value
    

      

    bitmap进阶的两个操作

    对指定key按位进行交、并、非、异或操作,并将结果保存到destKey中:

    bitop op destKey key1 [key2...]

    这里的op可以取:and:交  or:并   not:非  xor:异或

    统计指定key中1的数量:

    bitcount key [start end]
    

      

    可以看出,bitmap对于统计 只有是/否 两个答案的场景非常有用。

    HyperLogLog
    基数:基数是数据集去重后元素个数
    HyperLogLog 是用来做基数统计的,运用了LogLog的算法

    添加数据:

    pfadd key element [element ...]

    统计数据:

    pfcount key [key ...]

    合并数据:

    pfmerge destkey sourcekey [sourcekey...]
    

    GEO
    GEO是用于统计地图上(经纬度表示)两点之间距离的。

    GEO类型的基本操作
    添加坐标点:

    geoadd key longitude latitude member [longitude latitude member]

    获取坐标点:

    geopos key member[member …]

    计算坐标点距离:

    geodist key member1 member2 [unit]
    

      



    参考资料:

    Bilibili黑马程序员的Redis视频:https://www.bilibili.com/video/BV1CJ411m7Gc

  • 相关阅读:
    贪心算法与动态规划
    Linux重要目录结构
    博客园添加目录索引
    冒泡排序&插入排序&其他排序
    Linux下部署自己写的Web项目
    Java算法入门-数组&链表&队列
    Java集合-数据结构之栈、队列、数组、链表和红黑树
    Java集合-单例模式斗地主&Collections类的shuffle方法了解
    什么是反向代理服务器
    Linux信号处理
  • 原文地址:https://www.cnblogs.com/clno1/p/12994361.html
Copyright © 2011-2022 走看看