热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Redis6新手入门提升篇

Redis6新手入门提升篇文章目录Redis6新手入门提升篇键的过期策略内存淘汰机制慢查询简介慢查询配置查看慢查询日志查询日志获取当前慢查询日志记录数慢查询日志重置Pipeline
Redis 6 新手入门提升篇

文章目录

  • Redis 6 新手入门提升篇
    • 键的过期策略
        • `内存淘汰机制`
    • 慢查询
      • 简介
      • 慢查询配置
      • 查看慢查询日志
        • 查询日志
        • 获取当前慢查询日志记录数
        • 慢查询日志重置
    • Pipeline
    • BitMap
      • API
        • `SETBIT`
        • `BITCOUNT`
        • `GETBIT`
        • `BITOP`
      • 实战
    • GEO
        • `geoadd`
        • `geopos`
        • `geodist`
        • `georadius`
        • `georadiusbymember`
        • `zrem`
    • 布隆过滤器
      • `原理`
      • `应用场景`
  • 总结


键的过期策略

在redis中当键到了过期的时间,就会立马被删除掉吗?

我们了解一下删除策略的知识,删除策略可分为三种

  • 定时删除(对内存友好,对CPU不友好)
  • 惰性删除(对CPU极度友好,对内存极度不友好)
  • 定期删除(折中)

惰性删除是指每次从键空间取键的时候,判断一下该键是否过期了,如果过期了就删除。

Redis采用的是惰性删除+定期删除两种策略,所以说,在Redis里边如果键到了过期的时间了,未必被立马删除的!

所谓定期删除,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。

假设 redis 里放了 10w 个 key,都设置了过期时间,你每隔几百毫秒,就检查 10w 个 key,那 redis 基本上就死了,cpu 负载会很高的,消耗在你的检查过期 key 上了。

注意,这里可不是每隔 100ms 就遍历所有的设置过期时间的 key,那样就是一场性能上的灾难

实际上 redis 是每隔 100ms 随机抽取一些 key 来检查和删除的。

但是问题是,定期删除可能会导致很多过期 key 到了时间并没有被删除掉,那咋整呢?

所以就是惰性删除了。这就是说,在你获取某个 key 的时候,redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。

获取 key 的时候,如果此时 key 已经过期,就删除,不会返回任何东西。

但是实际上这还是有问题的,如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?

答案是:走内存淘汰机制

内存淘汰机制

如果定期删除漏掉了很多过期key,也没及时去查(没走惰性删除),大量过期key堆积在内存里,导致redis内存块耗尽了,咋整?

我们可以设置内存最大使用量,当内存使用量超出时,会施行数据淘汰策略

Redis的内存淘汰机制有以下几种:

volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
volatile-random:从已设置过期时间的数据集中任意选择数据淘汰
allkeys-lru:从数据集中挑选最近最少使用的数据淘汰
allkeys-random:从数据集中任意选择数据淘汰
no-enviction:当内存达到限制的时候,不淘汰任何数据


慢查询


简介

和很多关系型数据库一样, Redis 也提供了慢查询日志记录,Redis会把执行比较慢的命令放到内部的一个list列表中。

注意:慢查询记录的只是命令的执行时间,不包括网络传输和排队时间。


慢查询配置

关于 Redis 慢查询的配置有两个,分别是 slowlog-log-slower-thanslowlog-max-len
slowlog-log-slower-than 用来控制慢查询的阈值,所有执行时间超过该值的命令都会被记录下来。该值的单位为微秒,默认值为 10000,如果设置为 0,那么所有的记录都会被记录下来,如果设置为小于 0 的值,那么对于任何命令都不会记录,即关闭了慢查询。可以通过在配置文件中设置,或者用 config set 命令来设置:

config set slowlog-log-slower-than 10000

slowlog-max-len 用来设置存储慢查询记录列表的大小,默认值为 128,当该列表满了时,如果有新的记录进来,那么 Redis 会把队最旧的记录清理掉,然后存储新的记录。在生产环境我们可以适当调大,比如调成 1000,这样就可以缓冲更多的记录,方便故障的排查。配置方法和 slowlog-log-slower-than 类似,可以在配置文件中指定,也可以在命令行执行 config set 来设置:

config set slowlog-max-len 1000


查看慢查询日志


查询日志

Redis 专门提供了一组命令来查询慢查询日志:

SLOWLOG GET

慢查询redis.PNG

可以看到这里查到了两条慢查询记录,分别是ZINCRRBY和ZREVRANGE命令
那么记录的中的1)2)3)4)分别表示什么呢?
1)表示日志唯一标识符uid
2)命令执行时系统的时间戳
3)命令执行的时长,以微妙来计算
4)命令和命令的参数

获取当前慢查询日志记录数


SLOWLOG LEN


慢查询日志重置


SLOWLOG RESET


Pipeline

pipeline命令用来批量操作redis命令

由于redis是单线程的,下一次请求必须等待上一次请求执行完成后才能继续执行。执行N次命令需要N次网络时间+执行时间,然而使用Pipeline模式,客户端可以一次性的发送多个命令,也就是1次网络时间+N次执行时间,这样就大大的减少了网络往返时间,提高了系统性能。

下面看下伪代码:

Jedis redis = new Jedis("127.0.0.1", 6379);
Pipeline pipe &#61; redis.pipelined();for (int i &#61; 0; i < 10000; i&#43;&#43;) {pipe.hmset("key_" &#43; i, data); //将值封装到PIPE对象&#xff0c;此时并未执行&#xff0c;还停留在客户端}pipe.sync(); //将封装后的PIPE一次性发给redisjedis.close;

那么问题来了&#xff0c;在什么样的情景下适合使用pipeline呢&#xff1f;

有些系统可能对可靠性要求很高&#xff0c;每次操作都需要立马知道这次操作是否成功&#xff0c;是否数据已经写进redis了&#xff0c;那这种场景就不适合。
还有的系统&#xff0c;可能是批量的将数据写入redis&#xff0c;允许一定比例的写入失败&#xff0c;那么这种场景就可以使用了&#xff0c;比如10000条一下进入redis&#xff0c;可能失败了2条无所谓&#xff0c;后期有补偿机制就行了&#xff0c;比如短信群发这种场景&#xff0c;如果一下群发10000条&#xff0c;按照第一种模式去实现&#xff0c;那这个请求过来&#xff0c;要很久才能给客户端响应&#xff0c;这个延迟就太长了&#xff0c;如果客户端请求设置了超时时间5秒&#xff0c;那肯定就抛出异常了&#xff0c;而且本身群发短信要求实时性也没那么高&#xff0c;这时候用pipeline最好了。

BitMap

Bitmap是一串连续的2进制数字&#xff08;0或1&#xff09;&#xff0c;每一位所在的位置为偏移(offset)&#xff0c;在bitmap上可执行AND,OR,XOR以及其它位操作。

API


SETBIT


SETBIT KEY OFFSET VALUE

该命令用于对 key 所储存的字符串值&#xff0c;设置或清除指定偏移量上的位(bit)。时间复杂度O(1)

在redis中&#xff0c;存储的字符串都是以二进制的形式存在的。
如何通过SETBIT命令将’a’变成’b’呢&#xff1f;即将 01100001 变成 01100010&#xff08;b的ASCII码是98&#xff09;&#xff0c;其实就是将’a’中的offset 6从0变成1&#xff0c;将offset 7从1变成0。
每次SETBIT完毕之后&#xff0c;会返回该位置原先的bit值。

BITCOUNT


BITCOUNT KEY [START END]

该命令统计字符串中指定范围里bit被设置为1的数量

GETBIT


GETBIT KEY OFFSET

返回key对应的string在offset处的bit值

BITOP


BITOP operation destkey key [key…]

可以对多个二进制进行交集、并集等操作&#xff0c;并将结果保存到 destkey 上

实战

一个简单的例子&#xff1a;日活跃用户

为了统计今日登录的用户数&#xff0c;我们建立了一个bitmap,每一位标识一个用户ID。当某个用户访问我们的网页或执行了某个操作&#xff0c;就在bitmap中把标识此用户的位置为1。这样的话我们就可以通过BITCOUNT命令得到当日活跃用户数。

注意&#xff1a;使用BitMap统计流量适用于亿级流量系统&#xff0c;如果系统用户只有10w的话使用set数据结构会更好。

GEO

GEO功能在Redis3.2版本提供&#xff0c;支持存储地理位置信息用来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能。GEO的数据类型为zset

geoadd


  • 添加经纬度信息

geoadd cityGeo 116.405285 39.904989 "北京"
geoadd cityGeo 121.472644 31.231706 "上海"

geopos


  • 查找指定key的经纬度信息&#xff0c;可以指定多个key&#xff0c;批量返回

127.0.0.1:6379> geopos cityGeo 北京
1) "116.40528291463851929"
2) "39.9049884229125027"

geodist


  • 返回两个地方的距离&#xff0c;可以指定单位&#xff0c;比如米m&#xff0c;千米km&#xff0c;英里mi&#xff0c;英尺ft

127.0.0.1:6379> geodist cityGeo 北京 上海
"1067597.9668"
127.0.0.1:6379> geodist cityGeo 北京 上海 km
"1067.5980"

georadius


  • 以给定的经纬度为中心,返回键包含的位置元素当中,与中心的距离不超过给定最大距离的所有位置元素

georadius cityGeo 116.405285 39.904989 100 km WITHDIST WITHCOORD ASC COUNT 5

可以指定WITHDIST返回距离&#xff0c;WITHCOORD返回经纬度&#xff0c;WITHHASH返回geohash值
可以指定ASC或DESC&#xff0c;根据距离来排序
可以指定COUNT限定返回的记录数

georadiusbymember


  • 和georadius一样&#xff0c;不过中心点是由给定的位置元素决定的&#xff0c;而不是像georadius那样,使用输入的经度和纬度来决定中心点。

georadiusbymember cityGeo 北京 100 km WITHDIST WITHCOORD ASC COUNT 5

zrem


  • GEO没有提供删除成员的命令&#xff0c;但是因为GEO的底层实现是zset&#xff0c;所以可以借用zrem命令实现对地理位置信息的删除.

zrem cityGeo 北京

布隆过滤器

本质上布隆过滤器是一种数据结构&#xff0c;比较巧妙的概率型数据结构&#xff0c;特点是高效地插入和查询&#xff0c;可以用来告诉你 “某样东西一定不存在或者可能存在”。

相比于传统的 List、Set、Map 等数据结构&#xff0c;它更高效、占用空间更少&#xff0c;但是缺点是其返回的结果是概率性的&#xff0c;而不是确切的。

原理

其本质就是一个只包含0和1的bit数组。具体操作当一个元素被加入到集合里面后&#xff0c;该元素通过K个Hash函数运算得到K个hash后的值&#xff0c;然后将K个值映射到这个位数组对应的位置&#xff0c;把对应位置的值设置为1。查询是否存在时&#xff0c;我们就看对应的映射点位置如果全是1&#xff0c;他就很可能存在&#xff08;跟hash函数的个数和hash函数的设计有关&#xff09;&#xff0c;如果有一个位置是0&#xff0c;那这个元素就一定不存在。

如果我们要映射一个值到布隆过滤器中&#xff0c;我们需要使用多个不同的哈希函数生成多个哈希值&#xff0c;并对每个生成的哈希值指向的 bit 位置 1&#xff0c;例如针对值 “baidu” 和三个不同的哈希函数分别生成了哈希值 1、4、7&#xff0c;则上图转变为
image

Ok&#xff0c;我们现在再存一个值 “tencent”&#xff0c;如果哈希函数返回 3、4、8 的话

image

值得注意的是&#xff0c;4 这个 bit 位由于两个值的哈希函数都返回了这个 bit 位&#xff0c;因此它被覆盖了。现在我们如果想查询 “dianping” 这个值是否存在&#xff0c;哈希函数返回了 1、5、8三个值&#xff0c;结果我们发现 5 这个 bit 位上的值为 0&#xff0c;说明没有任何一个值映射到这个 bit 位上&#xff0c;因此我们可以很确定地说 “dianping” 这个值不存在。而当我们需要查询 “baidu” 这个值是否存在的话&#xff0c;那么哈希函数必然会返回 1、4、7&#xff0c;然后我们检查发现这三个 bit 位上的值均为 1&#xff0c;那么我们可以说 “baidu” 存在了么&#xff1f;答案是不可以&#xff0c;只能是 “baidu” 这个值可能存在。

这是为什么呢&#xff1f;答案跟简单&#xff0c;因为随着增加的值越来越多&#xff0c;被置为 1 的 bit 位也会越来越多&#xff0c;这样某个值 “taobao” 即使没有被存储过&#xff0c;但是万一哈希函数返回的三个 bit 位都被其他值置位了 1 &#xff0c;那么程序还是会判断 “taobao” 这个值存在。

应用场景

常见的适用应用场景有&#xff0c;利用布隆过滤器减少磁盘 IO 或者网络请求&#xff0c;因为一旦一个值必定不存在的话&#xff0c;我们可以不用进行后续昂贵的查询请求&#xff0c;比如可以用来解决缓存穿透的问题。

总结

如果这篇文章对您有所帮助&#xff0c;或者有所启发的话&#xff0c;求一键三连&#xff1a;点赞、转发、收藏&#xff0c;您的支持是我坚持写作最大的动力。


推荐阅读
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • Java程序设计第4周学习总结及注释应用的开发笔记
    本文由编程笔记#小编为大家整理,主要介绍了201521123087《Java程序设计》第4周学习总结相关的知识,包括注释的应用和使用类的注释与方法的注释进行注释的方法,并在Eclipse中查看。摘要内容大约为150字,提供了一定的参考价值。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
author-avatar
mobiledu2502925453
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有