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:希望对大家有所帮助,如果有纰漏或者更好的想法,请您一定不要吝啬你的赐教🙋。  

  • 34
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
第一部分  NoSQL入门 第1章  NoSQL的概念及适用范围 2 1.1  定义和介绍 3 1.1.1  背景与历史 3 1.1.2  大数据 5 1.1.3  可扩展性 7 1.1.4  MapReduce 8 1.2  面向列的有序存储 9 1.3  键/值存储 11 1.4  文档数据库 14 1.5  图形数据库 15 1.6  小结 16 第2章  NoSQL上手初体验 17 2.1  第一印象——两个简单的例子 17 2.1.1  简单的位置偏好数据集 17 2.1.2  存储汽车品牌和号数据 22 2.2  使用多种语言 30 2.2.1  MongoDB驱动 30 2.2.2  初识Thrift 33 2.3  小结 34 第3章  NoSQL接口与交互 36 3.1  没了SQL还剩什么 36 3.1.1  存储和访问数据 37 3.1.2  MongoDB数据存储与访问 37 3.1.3  MongoDB数据查询 41 3.1.4  Redis数据存储与访问 43 3.1.5  Redis数据查询 47 3.1.6  HBase数据存储与访问 50 3.1.7  HBase数据查询 52 3.1.8  Apache Cassandra数据存储与访问 54 3.1.9  Apache Cassandra数据查询 55 3.2  NoSQL数据存储的语言绑定 56 3.2.1  Thrift 56 3.2.2  Java 56 3.2.3  Python 58 3.2.4  Ruby 59 3.2.5  PHP 59 3.3  小结 60 第二部分  NoSQL基础 第4章  理解存储架构 62 4.1  使用面向列的数据库 63 4.1.1  使用关系数据库中的表格和列 63 4.1.2  列数据库对比RDBMS 65 4.1.3  列数据库当做键/值对的嵌套映射表 67 4.1.4  Webtable布局 70 4.2  HBase分布式存储架构 71 4.3  文档存储内部机制 73 4.3.1  用内存映射文件存储数据 74 4.3.2  MongoDB集合和索引使用指南 75 4.3.3  MongoDB的可靠性和耐久性 75 4.3.4  水平扩展 76 4.4  键/值存储Memcached和Redis 78 4.4.1  Memcached的内部结构 78 4.4.2  Redis的内部结构 79 4.5  最终一致性非关系数据库 80 4.5.1  一致性哈希 81 4.5.2  对象版本 82 4.5.3  闲话协议和提示移交 83 4.6  小结 83 第5章  执行CRUD操作 84 5.1  创建记录 84 5.1.1  在以文档为中心的数据库中创建记录 85 5.1.2  面向列数据库的创建操作 91 5.1.3  键/值映射表的创建操作 93 5.2  访问数据 96 5.2.1  用MongoDB访问文档 96 5.2.2  用HBase访问数据 97 5.2.3  查询Redis 98 5.3  更新和删除数据 98 5.3.1  使用MongoDB、HBase和Redis更新及修改数据 98 5.3.2  有限原子性和事务完整性 99 5.4  小结 100 第6章  查询NoSQL存储 101 6.1  SQL与MongoDB查询功能的相似点 101 6.1.1  加载MovieLens数据 103 6.1.2  MongoDB中的MapReduce 108 6.2  访问HBase等面向列数据库中的数据 111 6.3  查询Redis数据存储 113 6.4  小结 116 第7章  修改数据存储及管理演进 117 7.1  修改文档数据库 117 7.1.1  弱schema的灵活性 120 7.1.2  MongoDB的数据导入与导出 121 7.2  面向列数据库中数据schema的演进 124 7.3  HBase数据导入与导出 125 7.4  键/值存储中的数据演变 126 7.5  小结 126 第8章  数据索引与排序 127 8.1  数据库索引的基本概念 127 8.2  MongoDB的索引与排序 128 8.3  MongoDB里创建和使用索引 131 8.3.1  组合与嵌套键 136 8.3.2  创建唯一索引和稀疏索引 138 8.3.3  基于关键字的搜索和多重键 139 8.4  CouchDB的索引与排序 140 8.5  Apache Cassandra的索引与排序 141 8.6  小结 143 第9章  事务和数据完整性的管理 144 9.1  RDBMS和ACID 144 9.2  分布式ACID系统 147 9.
12篇学通csharp网络编程——第四篇 TCP应用编程 12篇学通csharp网络编程——第三篇 HTTP应用编程(下) 12篇学通csharp网络编程——第二篇 HTTP应用编程(上) 12篇学通csharp网络编程——第一篇 基础之进程线程 Lucene(1)lucene,你也会(7篇)——第一篇 快速入门 MongoDB(8)8天学通MongoDB——第八天 驱动实践 8天学通MongoDB——第七天 运维技术 8天学通MongoDB——第六天 分片技术 8天学通MongoDB——第五天 主从复制 8天学通MongoDB——第四天 索引操作 8天学通MongoDB——第三天 细说高级操作 8天学通MongoDB——第二天 细说增删查改 8天学通MongoDB——第一天 基础入门 UML系列(4)团队沟通利器之UML——类图 团队沟通利器之UML—— 序列图 团队沟通利器之UML——用例图 团队沟通利器之UML——活动图 wcf系列(5)wcf系列学习5天速成——第五天 服务托管 wcf系列学习5天速成——第四天 wcf之分布式架构 wcf系列学习5天速成——第三天 事务的使用 wcf系列5天速成——第二天 binding的使用(2) wcf系列5天速成——第一天 binding的使用(1) wpf系列(8)8天入门wpf—— 第八天 最后的补充 8天入门wpf—— 第七天 画刷 8天入门wpf—— 第六天 细说控件 8天入门wpf—— 第五天 数据绑定 8天入门wpf—— 第四天 模板 8天入门wpf—— 第三天 样式 8天入门wpf—— 第二天 xaml详解 8天入门wpf—— 第一天 基础概念介绍 并行开发(8)8天玩转并行开发——第八天 用VS性能向导解剖你的程序 8天玩转并行开发——第七天 简要分析任务与线程池 8天玩转并行开发——第六天 异步编程模 8天玩转并行开发——第五天 同步机制(下) 8天玩转并行开发——第四天 同步机制(上) 8天玩转并行开发——第三天 plinq的使用 8天玩转并行开发——第二天 Task的使用 8天玩转并行开发——第一天 Parallel的使用 多线程系列(5)5天不再惧怕多线程——第五天 线程池 5天不再惧怕多线程——第四天 信号量 5天不再惧怕多线程——第三天 互斥体 5天不再惧怕多线程——第二天 锁机制 5天不再惧怕多线程——第一天 尝试Thread 经典算法专题(21)经典算法题每日演练——第二十一题 十字链表 经典算法题每日演练——第二十题 三元组 经典算法题每日演练——第十九题 双端队列 经典算法题每日演练——第十八题 外排序 经典算法题每日演练——第十七题 Dijkstra算法 经典算法题每日演练——第十六题 Kruskal算法 经典算法题每日演练——第十五题 并查集 经典算法题每日演练——第十四题 Prim算法 经典算法题每日演练——第十三题 赫夫曼树 经典算法题每日演练——第十二题 线段树 经典算法题每日演练——第十一题 Bitmap算法 经典算法题每日演练——第十题 树状数组 经典算法题每日演练——第九题 优先队列 经典算法题每日演练——第八题 AC自动机 经典算法题每日演练——第七题 KMP算法 经典算法题每日演练——第六题 协同推荐SlopeOne 算法 经典算法题每日演练——第五题 字符串相似度 经典算法题每日演练——第四题 最长公共子序列 经典算法题每日演练——第三题 猴子吃桃 经典算法题每日演练——第二题 五家共井 经典算法题每日演练——第一题 百钱买百鸡 开发利器系列(1)介绍一个小工具 Linqer 那点所谓的分布式(2)那点所谓的分布式——memcache 那点所谓的分布式——redis结构专题(5)6天通吃树结构—— 第五天 Trie树 6天通吃树结构—— 第四天 伸展树 6天通吃树结构—— 第三天 Treap树 6天通吃树结构—— 第二天 平衡二叉树 6天通吃树结构—— 第一天 二叉查找树 算法速成系列(15)算法系列15天速成——第十五天 图【下】(大结局) 算法系列15天速成——第十四天 图【上】 算法系列15天速成——第十三天 树操作【下】 算法系列15天速成——第十二天 树操作【中】 算法系列15天速成——第十一天 树操作(上) 算法系列15天速成——第十天 栈 算法系列15天速成——第九天 队列 算法系列15天速成——第八天 线性表【下】 算法系列15天速成——第七天 线性表【上】 算法系列15天速成——第六天 五大经典查找【下】 算法系列15天速成——第五天 五大经典查找【中】 算法系列15天速成——第四天 五大经典查找【上】 算法系列15天速成——第三天 七大经典排序【下】 算法系列15天速成——第二天 七大经典排序【中】 算法系列15天速成——第一天 七大经典排序【上】 算法洗脑系列(8)算法洗脑系列(8篇)——第八篇 概率思想 算法洗脑系列(8篇)——第七篇 动态规划 算法洗脑系列(8篇)——第六篇 回溯思想 算法洗脑系列(8篇)——第五篇 分治思想 算法洗脑系列(8篇)——第四篇 枚举思想 算法洗脑系列(8篇)——第三篇 贪心思想 算法洗脑系列(8篇)——第二篇 递归思想 算法洗脑系列(8篇)——第一篇 递推思想 天籁数学(3)天籁数学——数列篇(3) 天籁数学——数列篇(2) 天籁数学——数列篇(1) 图形图像(1)玩玩图形图像——第一篇:图片灰度化 小爬虫系列(4)玩玩小爬虫——抓取时的几个小细节 玩玩小爬虫——抓取动态页面 玩玩小爬虫——试搭小架构 玩玩小爬虫——入门

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橡 皮 人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值