Redis第1讲——入门简介

Java并发编程的总结和学习算是告一段落了,这段时间思来想去,还是决定把Redis再巩固和学习一下。毕竟Redis不论是在面试还是实际应用中都是极其重要的,在面试中诸如Redis的缓存问题、热key、大key、过期策略、持久化机制等;还有在实际应用中的Redis缓存、分布式锁、Reids实现排行榜、分布式限流功能、Redis做延迟队列、消息队列、发布订阅等。相信大家对这并不陌生,而作者想要做的就是在其基础上,把它们进行总结、整理、扩展并深入

一、为什么要学Redis?

目前大多数系统都是集群部署,那么在用传统的锁和缓存时就会出现以下问题:

  • 缓存失效:在分布式集群中,每个节点之间的数据不是共享的,而本地缓存是本地的,因此,在一个节点上的本地缓存可能会缓存旧数据,而在另一个节点上的数据已经更新。这就会导致数据不一致性问题,从而影响系统的正确性。
  • 互斥锁问题:传统的锁(Synchronized、Lock)是基于但服务实现的,多个服务之间无法共享锁的状态,简单来说就是锁失效,那么也会出现数据不一致等问题。

可以通过Redis的分布式缓存和分布式锁来解决上述问题。

还有就是有的功能使用关系型数据库来解决可能很复杂,而用Redis这种非关系型数据库实现就比较简单,比如聊天室功能:

  • 如果用关系型数据库,一般都需要使用JOIN来进行多表查询,而在线的聊天室通常是非常频繁的读写操作,JOIN多表查询再加上频繁读写,不仅实现起来比较复杂,性能也很差。
  • 如果用Redis,那就可以非常容易实现而且性能也远超关系型数据库。比如用Redis的List或Hash数据结构,将聊天室中的所有消息按照时间戳存储在一个列表中,用户发送的消息可以通过Redis的集合或队列存储,再使用Redis的发布订阅功能就可以实现消息的广播和接收。

二、什么是Redis?

Redis(Remote Dictionary Server),即远程字段服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

Redis的作者——Antirez最初创建Redis是为了扩展实时日志分析工具LLOOGG,早先LLOOGG是基于MySQL的,但很快就遇到了性能瓶颈,Antirez相信使用内存可以解决这个问题,于是便开始了Redis的开发工作(原名为LLOOGG Memory Database),之后便有了这个功能强大、高性能、可扩展、易于使用的存储系统。

ps:这就是大佬思维,我们再遇到问题时第一想法是网上搜,而大佬的思维是自己开发一个,膜拜🤗。

  • Redis最重要的功能是做缓存,查询效率远高于Mysql数据库。
  • Redis是基于内存存储数据的,读写性能贼高。
  • Redis 4.0之前,读的速度是110000次/S,写的速度是81000次/S;Redis6.0引入多线程后性能几乎翻倍,读的速度可达200000次/s,写的速度可达170000次/S。
  • Redis不仅仅是Key-Value存储结构,针对Value还有多种数据结构。
  • Redis也提供了相应的持久化方案(RDB、AOF)。
  • Redis提供了主从复制、哨兵模式和Cluster等方案实现高可用。
  • Redis提供了强大的功能,比如事务、发布订阅、Lua脚本等。

优点还有很多,不一一列举了....

Reids是一种非关系型数据库(NoSql),此外,常见的还有以下几种:

  • key-value存储:将数据以键值对的形式存储,常用于缓存,比如Reids、MemCache等。
  • 文档型存储:以类似于JSON或XML格式的文档形式存储,适用于存储和查询复杂的、半结构化的数据,比如Elasticsearch、MongDB等。
  • 面向列存储:将数据按列存储,而不是按行,适用于大规模数据处理和分析,比如HBase、Apache Cassandra等。
  • 图形化存储:以图的形式存储数据,适用于需要处理复杂关系和图算法的常见,比如Neo4j、OrientDB等。

三、Redis为什么要自己定义SDS?

从这开始就正式介绍Redis了。我们知道Redis是C语言实现的,但他并没有直接使用C语言中的字符数组的方式来实现字符串,而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS),并将SDS用作Redis的默认字符串表示,这是为什么呢?

我们先回顾下C语言中字符串的实现。C语言使用长度N+1的字符串数组来表示长度未N的字符串,并且字符串数组的最后一个元素总是为空字符'\0'

那么这就会产生两个问题:

  • 首先它就不能保存任意内容了,至少'\0'就不能保存了,因为遇到它时就直接截断了。
  • 其次就是C语言中用'\0'来表示字符串结束的方式,所以计算长度、字符串追加等操作,都需要从头遍历,直到遇到'\0'才会返回长度或追加,那么它的性能就不是很高了。

因此,Redis自己定义了一个SDS来解决以上两个问题:

  • 在用字符串数据表示字符串的同时,在这个字符串中增加一个表示分配给该字符串数组的总长度alloc字段和一个表示字符串现有长度len字段,这样在获取长度的时候就不依赖于'\0'了,直接返回len就行了。
  • 在字符串做追加操作时,只需要判断新追加的部分的len加上已有的len是否大于alloc,如果超过就重新申请新空间,反之直接追加就行了。

ps:此外,SDS还被用作缓冲区(buffer):AOF模块中的AOF缓冲区,客户端状态中的输入缓冲区。

四、Redis的数据类型与数据结构

我们常见的数据类型比如string、hash、list、set、zset等类型其实在Redis中是一个个对象,是由简单动态字符串(SDS)、哈希表、整数集合、压缩列表、跳跃表等数据结构实现的。

Reids中的每个对象都由一个redisObject结构表示,该结构中和保存数据有关的有三个属性:

  • type:记录对象的类型,比如字符串对象(string)、列表对象(list)等,可用type key命令查看value的存储类型。
  • encoding:记录对象使用的编码,比如int、embstr等(下面会提到)。
  • ptr:ptr指针指向对象底层实现数据结构,这些结构则是由encoding决定的。

对应关系如下(不是很全但够用):

上图为Redis常用的5种基本类型及Reids 5.0版本的stream类型和Redis的9种编码方式和7种底层数据结构对应的关系。下面我们详细的介绍下。

五、九种数据类型

5.1 String类型

5.1.1 简介

String类型是Redis最基本的数据类型,它可以存储任意类型的数据,比如数字、文本或者是序列化后的对象,最大可存储512MB的数据。

底层实现是SDS,由长度、空闲空间和字节数组三部分组成,并且有3种编码方式:

  • int编码:用于存储整型数据,是以Long类型存储,未使用SDS类型。

  • embstr编码:当存储的字符串长度小于等于32字节,用embstr编码。

  •  raw编码:当存储的字符串长度大于32字节,用raw编码。

5.1.2 应用场景

应用场景还是非常广泛的,比如:

  • 缓存:提高性能,降低数据库压力。
  • 计数器:利用incr和decr命令实现原子性加减操作。
  • 分布式锁:利用setnx命令。
  • 限流:利用计数器的功能来实现限流。

5.1.3 常用命令

  • SET key value:设置指定 key 的值为指定的 value。
  • GET key:获取指定 key 的值。
  • INCR key:将指定 key 的值加 1,并返回加 1 后的值。
  • DECR key:将指定 key 的值减 1,并返回减 1 后的值。
  • APPEND key value:将指定 key 的值追加指定的 value。
  • STRLEN key:返回指定 key 的值长度。
  • SETEX key seconds value:设置指定 key 的值,并指定过期时间,单位为秒。

5.2 hash类型

5.2.1 简介

hash是一个键值对集合,可以存储多个字段和值,简单的说它的value就是一个Map集合,一个hash最多可以存储2^32-1个字段。

底层实现其实有三种:

  • ziplist:压缩列表,当ziplist元素超过512个单个元素超过64字节(可在redis的配置文件中设置),会转为hashtable。

  • listpack:紧凑列表,在Redis7.0之后,listpack取代ziplist,同样,到达上述阈值会转化为hashtable。

  • hashtable:哈希表,类似map。

下面我们来看下它们编码转换的情况:

5.2.2 应用场景

  • 存储对象或实体属性:比如用户信息、商品信息。

  • 存储配置信息:比如连接字符串、端口号、默认配置等。

5.2.3 常用命令

  • HSET:设置 hash 中的字段和值。用法:HSET key field value
  • HGET:获取指定 hash 字段的值。用法:HGET key field
  • HMSET:同时设置 hash 中多个字段和值。用法:HMSET key field1 value1 [field2 value2 …]
  • HMGET:获取指定 hash 中多个字段的值。用法:HMGET key field1 [field2 …]
  • HGETALL:获取 hash 中所有字段和值。用法:HGETALL key
  • HDEL:删除 hash 中的一个或多个字段。用法:HDEL key field1 [field2 …]
  • HEXISTS:检查指定的字段在 hash 中是否存在。用法:HEXISTS key field
  • HINCRBY:将 hash 中指定字段的值增加指定增量。用法:HINCRBY key field increment
  • HINCRBYFLOAT:将 hash 中指定字段的浮点数值增加指定增量。用法:HINCRBYFLOAT key field increment
  • HKEYS:获取 hash 中所有的字段。用法:HKEYS key
  • HVALS:获取 hash 中所有的值。用法:HVALS key
  • HLEN:获取 hash 中的字段数量。用法:HLEN key
  • HSCAN:迭代遍历 hash 中的字段和值。用法:HSCAN key cursor [MATCH pattern] [COUNT count]

5.3 List类型

5.3.1 简介

List是一个存取有序的字符串列表,按照插入顺序排序,有下标,并且支持两端插入或删除元素。一个list的键最多可以存储2^32-1个元素。

底层实现是linkedlist和zipList:

  • ziplist:当ziplist的结点超过512个或节点内存大于64字节时会转为linkedlist,当然,这个在Redis配置文件中也可以修改。
  • linkedlist:双端链表。

下面介绍一下,不同版本的Redis其list的实现:

  • Reids3.2之前:list使用linkedlist和ziplist。
  • Reids3.2至Redis7.0:list使用的是quicklist,linkedlist和ziplist的结合。
  • Reids7.0之后:list使用的也是quicklist,不过将ziplist转为listpack,其实就是listpack和linkedlist结合。

5.3.2 应用场景

  • 消息队列:将消息以先后顺序添加到list中,然后可以用lpop命令从列表的左侧弹出消息并处理。
  • 实时排行榜:将用户的得分或其它评价指标作为list的值,在该指标上进行排序。通过lpush、rpush和ltrim命令可以动态地更新排行榜。
  • 发布/订阅:发布者使用rpush命令将消息推送到列表中,订阅者用blpop或brpop命令在列表上进行阻塞弹出接收消息。
  • 历史记录:将聊天记录、日志信息等存储为list的值,使用lpush和lrange命令可以存储和查询最近的几条消息。

5.3.3 常用命令

  • LPUSH:从列表的左侧添加一个或多个元素。用法:LPUSH key value1 [value2 …]
  • RPUSH:从列表的右侧添加一个或多个元素。用法:RPUSH key value1 [value2 …]
  • LPOP:从列表的左侧弹出第一个元素。用法:LPOP key
  • RPOP:从列表的右侧弹出最后一个元素。用法:RPOP key
  • LRANGE:获取列表中指定范围的元素。用法:LRANGE key start stop
  • LINDEX:获取列表中指定索引位置的元素。用法:LINDEX key index
  • LLEN:获取列表的长度(即元素数量)。用法:LLEN key
  • LTRIM:修剪列表,只保留指定范围内的元素,其余元素删除。用法:LTRIM key start stop
  • LINSERT:在列表中指定元素的前面或后面插入一个新元素。用法:LINSERT key BEFORE|AFTER pivot value
  • LREM:从列表中删除指定数量的匹配元素。用法:LREM key count value

5.4 set类型

5.4.1 简介

set是一个无序的字符串集合,不允许重复,没有下标,一个set类型的键最多可以存储2^32-1个元素。

底层实现为intset和hashtable:

  • intset:当使用intset进行存储时,redis会自动的进行递增排序,因此,只存整型的话,其是一个有顺序的结构,但是并非只存整型数据就一直用intset,当整型的元素个数超过512个元素时,会转为hashtable。当存的是非整形时,也会转为hashtable进行存储。

  • hashtable:与hash类型的哈希表相同,将元素存储在一个数组中,并通过哈希函数计算元素在数组中的索引。

5.4.2 应用场景

  • 去重:利用sadd和scard命令实现元素的去重并计数。
  • 粉丝和关注系统:使用两个set分别存储用户的关注者和粉丝,使用sadd命令和srem命令来添加和移除关注,使用sinter和sunion命令可以计算共同关注和推荐关注。
  • 抽奖:将用户存储在set中,使用sadd和srem命令增加和删除参与资格,通过srandmember命令从set中随机选择一个或多个参与者。

5.4.3 常用命令

  • SADD:向 set 中添加一个或多个元素。用法:SADD key member1 [member2 …]
  • SREM:从 set 中删除一个或多个元素。用法:SREM key member1 [member2 …]
  • SMEMBERS:获取 set 中的所有元素。用法:SMEMBERS key
  • SISMEMBER:检查元素是否在 set 中。用法:SISMEMBER key member
  • SUNION:获取多个 set 的并集。用法:SUNION key1 [key2 …]
  • SINTER:获取多个 set 的交集。用法:SINTER key1 [key2 …]
  • SDIFF:获取两个 set 的差集(第一个 set 中有,第二个 set 中没有的元素)。用法:SDIFF key1 key2
  • SCARD:获取 set 的元素数量(即集合的基数)。用法:SCARD key
  • SPOP:从 set 中随机弹出一个元素。用法:SPOP key
  • SRANDMEMBER:从 set 中随机获取一个或多个元素。用法:SRANDMEMBER key [count]

5.5 zset类型

5.5.1 简介

zset数据类型存取有序、不允许重复、有下标,并且给每个元素赋予了一个排序权重值(score)。Redis通过权重值来给集合中的元素进行从小到大排序,权重值可以重复。一个zset类型的键最多可以存储2^32-1个元素。

其底层存储结构也用了两种,ziplist和skiplist,也有切换关系:

  • ziplist:ziplist存储元素超过128个内存超过64字节,会转为skiplist。redis7.0之前是ziplist,之后为listpack。
  • skiplist:跳跃表(之后详解)。

ps:这让我想起了之前面试官问zset类型底层是什么,当时大言不惭的说跳跃表的场景😅(当时对此深信不疑)。

5.5.2 应用场景

  • 排行榜:将用户的得分、浏览量、商品销量等排序信息存储在有序集合中,使用zadd命令添加元素,使用zrange或zrevrange命令获取排行榜的前几名或全部成员,使用zrank或zrevrank命令获取指定成员在排行榜中的排名。
  • 延迟队列:将任务及其执行时间存储在 zset 中,使用任务执行时间作为元素的分值,可以使用 zadd 命令添加任务和执行时间,使用 zrange 和 zrem 命令按执行时间获取任务。
  • 区间查询:通过 zrangebyscore 或者 zrevrangebyscore 命令根据分值范围获取元素。

5.5.3 常用命令

  • ZADD:向 zset 中添加一个或多个元素,以及它们的分值。用法:ZADD key score1 member1 [score2 member2 …]
  • ZREM:从 zset 中删除一个或多个元素。用法:ZREM key member1 [member2 …]
  • ZSCORE:获取指定元素的分值。用法:ZSCORE key member
  • ZRANK:获取指定元素在 zset 中的排名(按升序)。用法:ZRANK key member
  • ZREVRANK:获取指定元素在 zset 中的倒序排名(按降序)。用法:ZREVRANK key member
  • ZRANGE:按升序获取 zset 中的一定范围元素。用法:ZRANGE key start stop [WITHSCORES]
  • ZREVRANGE:按降序获取 zset 中的一定范围元素。用法:ZREVRANGE key start stop [WITHSCORES]
  • ZCOUNT:统计 zset 中指定分值范围内的元素数量。用法:ZCOUNT key min max
  • ZINCRBY:增减指定元素的分值。用法:ZINCRBY key increment member
  • ZCARD:获取 zset 中元素的数量(即集合的基数)。用法:ZCARD key

5.6 stream类型

5.6.1 简介

stream是Redis5.0新加的一个数据类型,通常被视为一个日志或消息队列,它是一个由多个键值对组成的可持久化、有序、可重复的数据流。一个stream类型的键最多可以存储2^64-1个键值对。

底层实现是rax tree(基数树)和listpack,rax是一种压缩的前缀树结构,消息ID是作为rax中的key,消息具体数据是使用listpack保存,并作为value和消息ID一起保存到rax tree中。

5.6.2 应用场景

  • 消息队列:生产者可以使用XADD命令将消息添加到stream中,消费者可以使用XREAD或XREADGROUP命令消费消息。
  • 实时日志:每个日志视为一个消息,可以根据时间戳、唯一的消息ID、消息内容等属性进行查询和筛选。通过XADD命令添加日志,XREAD或XREADGROUP命令获取日志。
  • 事件流处理:例如用户活动流、系统监控事件等。事件流中的每个事件被视为一个消息,可以根据事件类型、时间戳、事件属性等条件进行查询和分析。

5.6.3 常用命令

  • XADD:向 Stream 中添加一条消息。用法:XADD key [MAXLEN [~|~count] [LIMIT count]] * field1 value1 [field2 value2 …] 示例:XADD mystream * name Alice age 25
  • XLEN:获取 Stream 中的消息数量。用法:XLEN key 示例:XLEN mystream
  • XRANGE:按照 ID 范围获取 Stream 中的消息列表。用法:XRANGE key start end [COUNT count] 示例:XRANGE mystream 0-0 10
  • XREAD:读取 Stream 中的消息。用法:XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key …] id [id …] 示例:XREAD COUNT 10 STREAMS mystream 0
  • XDEL:删除 Stream 中的消息。用法:XDEL key id [id …] 示例:XDEL mystream 1578854095166-0 1578854095166-1
  • XGROUP CREATE:创建消费者组。用法:XGROUP CREATE key groupname id_or_$ [MKSTREAM] 示例:XGROUP CREATE mystream mygroup $
  • XGROUP SETID:设置消费者组的消费位置。用法:XGROUP SETID key groupname id_or_$ 示例:XGROUP SETID mystream mygroup 0-0
  • XREADGROUP:消费者组读取 Stream 中的消息。用法:XREADGROUP GROUP groupname consumerkey [COUNT count] [BLOCK milliseconds] STREAMS key [key …] id [id …] 示例:XREADGROUP GROUP mygroup consumer1 COUNT 10 STREAMS mystream >
  • XACK:消费者确认已消费的消息。用法:XACK key groupname id [id …] 示例:XACK mystream mygroup 1578854095166-0 1578854095166-1
  • XCLAIM:消费者从待处理列表中获取消息。用法:XCLAIM key groupname consumer min-idle-time ID [ID …] [IDLE ms] [TIME ms-unix-time] [RETRYCOUNT count] [FORCE] 示例:XCLAIM mystream mygroup consumer1 60000 1578854095166-0

5.7 Hyperloglog类型

5.7.1 简介

Hyperloglog是一种概率数据结构,算法的最本源则是伯努利过程。用在恒定的内存大小下估计集合的计数(不同元素的个数),以及对多个集合进行并、交运算等。优点是可以使用极少的内存空间,同时可以保证较高的准确性。每个Hyperloglog键秩序要花费12KB内存,便可计算接近2^64个不同元素的基数。

底层实现是HLL_DENSE(稠密矩阵)和HLL_SPARSE(稀疏矩阵):

  • 稀疏矩阵:计数较少时使用。

  • 稠密矩阵:计数增多,超过阈值后,会转为稠密矩阵。

5.7.2 应用场景

  • 计算网站的UV(unique visitor)数量:通过记录用户请求的 IP 地址(或浏览器 cookie 等标识符),使用 HyperLogLog 可以快速估计出网站的独立访客数。
  • 统计在线用户数量:通过记录用户登录名、客户端ID等信息,使用 HyperLogLog 可以快速估计在一段时间内在线用户的数量。
  • 统计数据库中某字段的不同取值数量:通过记录字段值,使用 HyperLogLog 可以估算不同取值的数量,例如估算某个表中年龄、地区等字段的不同取值数量。

5.7.3 常用命令

  • PFADD:向 HyperLogLog 中添加一个或多个元素。用法:PFADD key element [element …] 示例:PFADD myloglog user1 user2 user3
  • PFCOUNT:获取 HyperLogLog 的基数估计值。用法:PFCOUNT key [key …] 示例:PFCOUNT myloglog
  • PFMERGE:将多个 HyperLogLog 合并为一个。用法:PFMERGE destkey sourcekey [sourcekey …] 示例:PFMERGE mergedloglog myloglog1 myloglog2
  • PEXPIRE:设置 HyperLogLog 的过期时间。用法:PEXPIRE key milliseconds 示例:PEXPIRE myloglog 60000
  • PTTL:获取 HyperLogLog 的剩余过期时间。用法:PTTL key 示例:PTTL myloglog
  • PERSIST:移除 HyperLogLog 的过期时间。用法:PERSIST key 示例:PERSIST myloglog

5.8 GEO类型

5.8.1 简介

GEO(地理位置)是一个键值对集合,其中每个元素都包含一个经度和纬度,可以用于存储地理位置信息并支持基于位置的搜索。

它是基于zset数据类型实现的,利用geohash算法将经纬度编码为二进制字符串,并作为zset的score值。在使用GEORADIUS和GEORADIUSBYMEMBER命令搜索元素时,Redis会构建一个跳跃表,以实现高效的搜索。

5.8.2 应用场景

  • 附近的人/商家搜索:通过将用户/商家的地理位置坐标存储在 Redis 的 GEO 数据结构中,可以根据用户当前的地理位置快速查询附近的人或商家,实现定位服务和位置搜索功能。
  • 地点推荐:通过存储地点的坐标和属性,可以根据用户当前的地理位置快速推荐附近的景点、餐厅、酒店等地点,并按距离排序。
  • 打车/配送系统:可以使用 GEO 数据类型来存储司机的位置和乘客的位置,以便快速匹配附近的司机和乘客,并计算两者之间的距离。
  • 热点地理位置统计:通过记录用户地理位置的访问次数,可以统计热门地点,用于展示热门景点、餐厅等信息。

5.8.3 常用命令

  • PFADD:向 HyperLogLog 中添加元素。用法:PFADD key element [element …] 示例:PFADD myloglog a b c
  • PFCOUNT:获取 HyperLogLog 的近似基数(唯一元素数量)。用法:PFCOUNT key [key …] 示例:PFCOUNT myloglog
  • PFMERGE:将多个 HyperLogLog 合并为一个 HyperLogLog。用法:PFMERGE destkey sourcekey [sourcekey …] 示例:PFMERGE merged myloglog1 myloglog2 myloglog3
  • PEXPIRE:设置 HyperLogLog 的过期时间。用法:PEXPIRE key milliseconds 示例:PEXPIRE myloglog 60000
  • PTTL:获取 HyperLogLog 的剩余过期时间。用法:PTTL key 示例:PTTL myloglog
  • PERSIST:移除 HyperLogLog 的过期时间。用法:PERSIST key 示例:PERSIST myloglog

5.9 bitmap类型

5.9.1简介

bitmap是一种紧凑的数据结构,可以用于表示一个只有0和1的数组。位图可以用于高效地存储大规模的布尔值,以及进行位运算、位图图形化等操作。一个bitmap最多可以存储2^32-1个二进制位。

底层使用了一种“压缩位图”的数据结构。通过使用两个数组来存储位图数据:一个存储实际位的值,另一个存储每个字节中1的个数。这种方式可大大压缩位图数据的大小。

5.9.2 应用场景

  • 统计在线用户:与统计用户活跃类似,可以使用 Bitmap 来实现对在线用户的统计。比如将一个 key 对应的字符串的每个比特位表示一个用户,当某个用户在线时,将对应的比特位置为 1。此时使用 BITCOUNT 命令来计算在线的用户数。
  • Bloom Filter:利用 SETBIT 和 GETBIT命令实现快速判断一个元素是否存在于一个集合中。
  • 统计用户访问情况:可以利用 Bitmap 记录用户的访问情况,如记录用户是否已浏览一篇文章。可以使用 SETBIT 命令为特定文章的每个用户设置一个比特位,并在用户浏览过该文章时,将其对应的比特位设置为 1。这些比特位的数据将存储在同一个键值下,以记住哪个用户看过哪些文章。
  • 实现位图索引:利用 bitop 和 bitpos 命令实现对多个条件进行位运算和定位

5.9.3 常用命令

  • SETBIT:设置位图在指定偏移量的值。用法:SETBIT key offset value 示例:SETBIT mybitmap 0 1
  • GETBIT:获取位图在指定偏移量的值。用法:GETBIT key offset 示例:GETBIT mybitmap 0
  • BITCOUNT:计算位图中值为1的位的数量。用法:BITCOUNT key [start end] 示例:BITCOUNT mybitmap 0 10
  • BITOP:对多个位图执行位运算操作,并将结果保存在指定位图中。用法:BITOP operation destkey key [key …] 示例:BITOP AND result mybitmap1 mybitmap2 mybitmap3
  • BITPOS:查找位图中指定bit(0或1)第一次出现的偏移量。用法:BITPOS key bit [start] [end] 示例:BITPOS mybitmap 0 100
  • BITFIELD:使用位域操作位图。用法:BITFIELD key [GET type offset] [SET type offset value] 示例:BITFIELD mybitmap GET u4 0

End:希望对大家有所帮助,如果有纰漏或者更好的想法,请您一定不要吝啬你的赐教🙋。  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/243475.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能优化算法应用:基于鸽群算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于鸽群算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于鸽群算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.鸽群算法4.实验参数设定5.算法结果6.参考文献7.MA…

12.12年末大促,退换货寄件5元起 !

促销新闻报道: 在双十二促销季,闪侠惠递携手圆通、申通、中通、京东、德邦推出了一系列寄件促销活动!在这场活动中,退换货运费贵,你该怎么办?从今天开始,闪侠惠递和五大物流企业为您带来了一场…

架构简洁之道有感,谈谈软件组件聚合的张力

配图由腾讯混元助手生成 这篇文章介绍了软件架构设计中组件设计思想,围绕“组件间聚合的张力”这个有意思的角度,介绍了概念,并且结合架构设计示例对这个概念进行了进一步阐述。 组件聚合?张力?这标题,有种…

7+PPI+机器学习+实验,非肿瘤结合建模筛选生物标志物,可升级

今天给同学们分享一篇生信文章“Identification of diagnostic biomarkers and therapeutic targets in peripheral immune landscape from coronary artery disease”,这篇文章发表在J Transl Med期刊上,影响因子为7.4。 结果解读: 外周血中…

docker-compose 单机容器编排

docker-compose 单机容器编排 Dockerfile:先配置好的文件,然后bulid,镜像容器。 docker-compose 既可以基于dockerfile,也可以基于镜像,一键式拉起镜像和容器。 docker-compose 核心就是yml文件,可以定义…

idea__SpringBoot微服务11——整合Druid数据源(新依赖)(新注解)

整合JDBC 一、导入依赖二、配置Druid————————创作不易,如觉不错,随手点赞,关注,收藏(* ̄︶ ̄),谢谢~~ 接着 第10的 新注解: ConfigurationProperties ConfigurationPropert…

介绍一款上传漏洞fuzz字典生成工具

介绍一款上传漏洞fuzz字典生成工具 1.工具概述2.安装3.参数解析4.使用案例1.工具概述 upload-fuzz-dic-builder是一个上传漏洞fuzz字典生成脚本,生成时给的上传点相关信息越详细,生成的字典越精确 upload-fuzz-dic-builder 2.安装 克隆项目: git clone git@github.com:c…

TCP/IP详解——TCP 协议

文章目录 一、传输层协议1. TCP1.1 TCP 的字节流1.2 TCP 端口号1.3 TCP 头部1.4 TCP 选项部分字段1.5 TCP 三次握手1.6 TCP 三次握手不成功1.6.1 TCP 拒绝(被RST重置)1.6.2 TCP 半连接1.6.3 TCP 连接无响应 1.7 TCP 传输过程及原理1.7.1 TCP 传输过程1.7…

现代雷达车载应用——第2章 汽车雷达系统原理 2.4节 雷达波形和信号处理

经典著作,值得一读,英文原版下载链接【免费】ModernRadarforAutomotiveApplications资源-CSDN文库。 2.4 雷达波形和信号处理 对于连续波雷达来说,波形决定了其基本信号处理流程以及一些关键功能。本节将以FMCW波形为例,讨论信号…

【MySQL命令】show slave status\G 超详细全面解释

这个命令是DBA日常运维中常用来查看主从状态的命令,很多备份,监控工具也会使用到该命令监控主从状态是否正常,主从延迟,获取位点信息等。作为常用日常命令,一定要完全理解该命令的输出。今天主要结合 官方文档 和 实际…

iptables详解

1、介绍 iptables 是一个在 Linux 系统上用于配置和管理防火墙规则的工具。它允许系统管理员定义数据包的过滤规则、网络地址转换(NAT)规则和数据包的网络地址和端口的转发规则。iptables 提供了非常灵活和强大的功能,可以用于保护网络安全、…

Python数据科学视频讲解:Python序列的概念及通用操作

2.10 Python序列的概念及通用操作 视频为《Python数据科学应用从入门到精通》张甜 杨维忠 清华大学出版社一书的随书赠送视频讲解2.10节内容。本书已正式出版上市,当当、京东、淘宝等平台热销中,搜索书名即可。内容涵盖数据科学应用的全流程,…

Python 自动化之收发邮件(一)

imapclient / smtplib 收发邮件 文章目录 imapclient / smtplib 收发邮件前言一、基本内容二、发送邮件1.整体代码 三、获取邮件1.整体代码 总结 前言 简单给大家写个如何用Python进行发邮件和查看邮件教程,希望对各位有所帮助。 一、基本内容 本文主要分为两部分…

为什么FPGA是战略芯片?

FPGA(Field Programmable Gate Array)是在PAL(可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物,它是作为一种半定制电路而出现的,既解决了定制电路的不足&…

c++知识总结

一 细碎知识 1.27 # 1.27.1 # pragma once 参考 C++学习笔记之pragma once的理解_pragma once什么意思-CSDN博客https://blog.csdn.net/lynnlee_36/article/details/105322937作用 保证只被编译一次,和#ifndef,#define,#endif功能相同 1.27.2 #if defined(__cplusplus…

1688按关键字搜索工厂数据,商品详情页数据的采集

公共参数 名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中,点击获取测试key和secret)secretString是调用密钥api_nameString是API接口名称(包括在请求地址中)[item_search,item_get,item_search_shop等]cacheStrin…

十个Vue3实用但是冷门的API

文章目录 一、前言二、readonly三、shallowRef四、shallowReactive五、toRef & toRefs5.1、 toRef5.2、toRefs 六、toRaw & markRaw & unref6.1、toRaw6.2、markRaw6.3、unref 七、effectScope & onScopeDispose7.1、收集副作用7.2、全局状态管理 八、provide …

如何防止订单重复支付的?

如图是一个简化的下单流程,首先是提交订单,然后是支付。 支付的话,一般是走支付网关(支付中心),然后支付中心与第三方支付渠道(微信、支付宝、银联)交互。 支付成功以后&#xff0c…

2023-03-27 在vmware 下安装 TrueNAS

Download TrueNAS SCALE - Data Storage Software 安装 TrueNAS 的,官网推荐系统要求: 处理器 记忆 启动装置 贮存 2 核 Intel 64 位或 AMD x86_64 处理器 8 GB 内存 16 GB SSD 引导设备 用于单个存储池的两个相同大小的设备 等待系统安装完成 esxi搭建true…

OpenHarmony应用开发——实现Toast提示功能-鸿蒙物联网应用开发-HarmonyOs应用开发

一、前言 本文我们将实现Toast样式的功能,以便于和用户进行简单、基本的信息交互。需要注意的是,本专栏(OpenHarmony应用开发)不阐述UI设计内容,而主要介绍大家开发中常遇到、常使用的功能问题,以及在物联网…