• redis 支持的数据类型


    前言

    Redis 数据库支持的数据类型。

    • 最基本的5种

      • 字符串(string)
      • 哈希(hash)
      • 列表(list)
      • 集合(set)
      • 有序集合(sorted set)
        在这里插入图片描述
      结构类型结构存储的值结构的读写能力
      String字符串可以是字符串、整数或浮点数对整个字符串或字符串的一部分进行操作;对整数或浮点数进行自增或自减操作;
      List列表一个链表,链表上的每个节点都包含一个字符串对链表的两端进行push和pop操作,读取单个或多个元素;根据值查找或删除元素;
      Set集合包含字符串的无序集合字符串的集合,包含基础的方法有看是否存在添加、获取、删除;还包含计算交集、并集、差集等
      Hash散列包含键值对的无序散列表包含方法有添加、获取、删除单个元素
      Zset有序集合和散列一样,用于存储键值对字符串成员与浮点数分数之间的有序映射;元素的排列顺序由分数的大小决定;包含方法有添加、获取、删除单个元素以及根据分值范围或成员来获取元素
    • 新版本

      • 位图 BitMap(2.2)
      • 基数统计 ( HyperLogLog) # 2.8.9新增
      • Geo:地理位置信息储存起来, 并对这些信息进行操作 # 3.2新增
      • 流(Stream)# 5.0新增

    一、字符串

    String 是一组字节。在 Redis 数据库中,字符串是二进制安全的。这意味着它们具有已知长度,并且不受任何特殊终止字符的影响。可以在一个字符串中存储最多 512 兆字节的内容。

    1.1、命令使用

    1.1.1、基本操作

    • set (key) (value):设置键值对
    • setnx (key) (value):防止覆盖,设置键值对,
      • 如果key不存在就设置,返回1
      • 如果key已经存在就不设置,返回0
    • get(key):获取key对应的value
    • getset (key) (value) :先get再set,返回旧值,如果没有旧值返回nil
    • append (key) (value):向指定的key的value后追加字符串
    • del (key) :删除key
    • strlen (key):获取key对应值的字符串长度

    1.1.2、数字value的加减

    • incr (key) :value + 1
    • decr (key) :value - 1
    • incrby (key) (number):value + number
    • decrby (key) (number):value - number

    1.1.3、 获取或者设置指定范围内的值

    • getrange (key) (begin) (end) :获取[begin,end]下标范围内的值,如果是(0,1)就是获取所有值
    • setrange (key) (begin) (xxxx) :从begin下标开始设置xxx值,将原有的替换掉

    1.1.4、设置键值过期时间

    • setex (key) (seconds) expire:设置键过期时间
    • ttl (key) :查看key剩余存活时间

    1.1.5、同时设置或获取多个key-value

    • met (key1) (value1) (key2) (value2):用于同时设置一个或多个 key-value 对
    • mget (key1) (key2) :返回所有(一个或多个)给定 key 的值(如果某个key不存在,不存在的key返回null)
    • msetnx(key1) (value1) (key2) (value2):当所有 key 都成功设置,返回 1 。 如果有一个key设置失败,所有的key设置都会失败,返回 0 。原子操作

    1.2、使用场景

    1.2.1、实战场景

    • 缓存: 经典使用场景,把常用信息,字符串,图片或者视频等信息放到redis中,redis作为缓存层,mysql做持久化层,降低mysql的读写压力
    • 计数器:redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源。
    • session:常见方案spring session + redis实现session共享,

    1.3、编码与底层结构

    字符串是Redis最基本的数据类型,不仅所有key都是字符串类型,其它几种数据类型构成的元素也是字符串。注意字符串的长度不能超过512M。

    1.3.1、编码

    字符串对象的编码可以是int,raw或者embstr。

    1. int 编码:保存的是可以用 long 类型表示的整数值
    2. embstr 编码:保存长度小于44字节的短字符串(redis3.2版本之前是39字节,之后是44字节)对其进行修改后变成raw编码,无论是否达到44字节
    3. raw 编码:保存长度大于44字节的长字符串(redis3.2版本之前是39字节,之后是44字节)

    1.4、内存布局

    字符串对象支持三种编码方式: RAW, INT, EMBSTR, 三种方式的内存布局分别如下:

    1.4.1、raw 和 embstr 的区别

    其实 embstr 编码是专门用来保存短字符串的一种优化编码,

    embstr与raw都使用redisObject和sds保存数据,

    • embstr的使用只分配一次内存空间(因此redisObject和sds是连续的)
    • raw需要分配两次内存空间(分别为redisObject和sds分配空间)

    只分配一次内存空间的好处是,创建时少分配一次空间,删除时少释放一次空间,以及对象的所有数据连在一起,寻找方便。

    而embstr的坏处也很明显,如果字符串的长度增加需要重新分配内存时,整个redisObject和sds都需要重新分配空间,因此redis中的embstr实现为只读。

    1.5、编码的转换

    • 当 int 编码保存的值不再是整数,或大小超过了long的范围时,自动转化为raw。
    • 对于 embstr 编码,由于 Redis 没有对其编写任何的修改程序(embstr 是只读的),在对embstr对象进行修改时,都会先转化为raw再进行修改,因此, 只要是修改embstr对象,修改后的对象一定是raw的,无论是否达到了44个字节。

    使用 SET 命令在 name 键中存储字符串 redis.com.cn,然后使用 GET 命令查询 name。

    SET name "abc"  
    OK  
    GET name   
    "abc" 
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    在上面的例子中,SET 和 GET 是 Redis 命令,name 是 Redis 中使用的 key,abc 是存储在 Redis 中的字符串值。

    二、哈希

    哈希是键值对的集合。在 Redis 中,哈希是字符串字段和字符串值之间的映射。因此,它们适合表示对象。
    一个hash可以存多个key-value,类似一个对象的多个字段和属性

    2.1、命令使用

    命令简述使用
    HSET添加键值对HSET hash-key sub-key1 value1
    HGET获取指定散列键的值HGET hash-key key1
    HGETALL获取散列中包含的所有键值对HGETALL hash-key
    HDEL如果给定键存在于散列中,那么就移除这个键HDEL hash-key sub-key1

    2.2、例

    让我们存储一个用户的对象,其中包含用户的基本信息。

    HMSET user:1 username ajeet password javatpoint alexa 2000  
    OK  
    HGETALL  user:1  
    "username"  
    "ajeet"  
    "password"  
    "javatpoint"  
    "alexa"  
    "2000" 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Redis数据类型2

    这里,HMSET 和 HGETALL 是 Redis 的命令,而 user:1 是键。

    每个哈希可以存储多达 2的32– 次方 1 个字段-值对。

    2.3、编码与底层结构

    哈希对象的键是一个字符串类型,值是一个键值对集合。

    2.3.1、编码

    哈希对象的编码可以是 ziplist 或者 hashtable;

    2.3.2、底层结构

    对应的底层实现有两种, 一种是ziplist, 一种是dict。

    2.4、内存布局

    需要注意的是: 当采用HT编码, 即使用dict作为哈希对象的底层数据结构时, 键与值均是以sds的形式存储的.

    举例说明

    • 当使用ziplist,也就是压缩列表作为底层实现时,新增的键值对是保存到压缩列表的表尾。

    比如执行以下命令:

    hset profile name "Tom"
    hset profile age 25
    hset profile career "Programmer"
    
    • 1
    • 2
    • 3

    ⚡️ 在前面介绍压缩列表时,我们介绍过压缩列表是Redis为了节省内存而开发的,是由一系列特殊编码的连续内存块组成的顺序型数据结构,相对于字典数据结构,压缩列表用于元素个数少、元素长度小的场景。其优势在于集中存储,节省空间。

    • 当使用 hashtable 编码时,底层使用字典数据结构,哈希对象中的每个键值对都使用一个字典键值对。上面命令存储如下:

    2.5、编码转换

    和上面列表对象使用 ziplist 编码一样,当同时满足下面两个条件时,使用ziplist(压缩列表)编码,否则使用hashtable 编码

    • 列表保存元素个数小于512个(配置文件中的 set-max-intset-entries 修改)

    • 每个元素长度小于64字节

    三、 列表

    Redis 列表定义为字符串列表,按插入顺序排序。可以将元素添加到 Redis 列表的头部或尾部。
    Redis中的List其实就是双端链表

    • 使用List结构,我们可以轻松地实现最新消息排队功能(比如新浪微博的TimeLine)。List的另一个应用就是消息队列,可以利用List的 PUSH 操作,将任务存放在List中,然后工作线程再用 POP 操作将任务取出进行执行。
    • Redis还提供了操作List中某一段的api,你可以直接查询,删 除List中某一段的元素。
    • 使用列表的技巧
      • lpush+lpop=Stack(栈)
      • lpush+rpop=Queue(队列)
      • lpush+ltrim=Capped Collection(有限集合)
      • lpush+brpop=Message Queue(消息队列)

    3.1、命令使用

    命令简述使用
    RPUSH将给定值推入到列表右端RPUSH key value
    LPUSH将给定值推入到列表左端LPUSH key value
    RPOP从列表的右端弹出一个值,并返回被弹出的值RPOP key
    LPOP从列表的左端弹出一个值,并返回被弹出的值LPOP key
    LRANGE获取列表在给定范围上的所有值LRANGE key 0 -1
    LINDEX通过索引获取列表中的元素。你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。LINEX key index

    3.2、使用场景

    • 微博TimeLine: 有人发布微博,用lpush加入时间轴,展示新的列表信息。
    • 消息队列

    3.3、编码与底层结构

    list 列表,它是简单的字符串列表,按照插入顺序排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边),它的底层实际上是个链表结构。

    3.3.1、编码

    列表对象的编码是quicklist。 (之前版本中有linked和ziplist这两种编码)

    bash
    lpush javatpoint java  
    (integer) 1  
    lpush javatpoint java  
    (integer) 1  
    lpush javatpoint java  
    (integer) 1  
    lpush javatpoint java  
    (integer) 1  
    lrange javatpoint 0 10  
    "cassandra"  
    "mongodb"  
    "sql"  
    "java"  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    列表的最大长度为 232 – 1 个元素(超过 40 亿个元素)。

    四、Set集合

    集合(set)是 Redis 数据库中的无序字符串集合。在 Redis 中,添加,删除和查找的时间复杂度是 O(1)。

    Redis 的 Set 是 String 类型的无序集合。

    • 标签(tag),给用户添加标签,或者用户给消息添加标签,这样有同一标签或者类似标签的可以给推荐关注的事或者关注的人。
    • 点赞,或点踩,收藏等,可以放到set中实现

    4.1、命令使用

    命令简述使用
    SADD向集合添加一个或多个成员SADD key value
    SCARD获取集合的成员数SCARD key
    SMEMBER返回集合中的所有成员SMEMBER key member
    SISMEMBER判断 member 元素是否是集合 key 的成员SISMEMBER key member

    4.2、例

    sadd tutoriallist redis  
    (integer) 1  
    redis 127.0.0.1:6379> sadd tutoriallist sql  
    (integer) 1  
    redis 127.0.0.1:6379> sadd tutoriallist postgresql  
    (integer) 1  
    redis 127.0.0.1:6379> sadd tutoriallist postgresql  
    (integer) 0  
    redis 127.0.0.1:6379> sadd tutoriallist postgresql  
    (integer) 0  
    redis 127.0.0.1:6379> smembers tutoriallist  
    1) "redis"  
    2) "postgresql"  
    3) "sql" 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Redis数据类型4

    在上面的示例中,您可以看到 postgresql 被添加了三次,但由于该集的唯一属性,它只添加一次。

    集合中的最大成员数为 232-1 个元素(超过 40 亿个元素)。

    4.3、编码与底层结构

    集合对象 set 是 string 类型(整数也会转换成string类型进行存储)的无序集合。

    注意集合和列表的区别:

    • 集合中的元素是无序的,因此不能通过索引来操作元素;
    • 集合中的元素不能重复

    4.3.1、编码

    集合对象的编码可以是 intset 或者 hashtable;

    4.3.2、底层结构

    对应的底层实现分别是intset和dict

    • 显然当使用intset作为底层实现的数据结构时, 集合中存储的只能是数值数据, 且必须是整数;
    • 当使用dict作为集合对象的底层实现时, 是将数据全部存储于dict的键中, 值字段闲置不用.

    举例说明

    SADD numbers 1 3 5
    
    • 1
    SADD Dfruits "apple" "banana" "cherry"
    
    • 1

    4.4、编码转换

    当集合同时满足以下两个条件时,使用 intset 编码,否则使用 hashtable 编码

    • 集合对象中所有元素都是整数

    • 集合对象所有元素数量不超过512(可以通过配置文件的 set-max-intset-entries 进行配置)

    五、有序集合

    Redis 有序集合类似于 Redis 集合,也是一组非重复的字符串集合。但是,排序集的每个成员都与一个分数相关联,该分数用于获取从最小到最高分数的有序排序集。虽然成员是独特的,但可以重复分数。

    redis 127.0.0.1:6379> zadd tutoriallist 0 redis  
    (integer) 1  
    redis 127.0.0.1:6379> zadd tutoriallist 0 sql  
    (integer) 1  
    redis 127.0.0.1:6379> zadd tutoriallist 0 postgresql  
    (integer) 1  
    redis 127.0.0.1:6379> zadd tutoriallist 0 postgresql  
    (integer) 0  
    redis 127.0.0.1:6379> zadd tutoriallist 0 postgresql  
    (integer) 0  
    redis 127.0.0.1:6379> ZRANGEBYSCORE tutoriallist 0 10  
    1) "postgresql"  
    2) "redis"  
    3) "sql"   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Redis数据类型5

    六、位图 Redis Bitmap

    Redis Bitmap 通过类似 map 结构存放 0 或 1 ( bit 位 ) 作为值。

    Redis Bitmap 可以用来统计状态,如日活是否浏览过某个东西。

    Redis setbit 命令
    Redis setbit 命令用于设置或者清除一个 bit 位。

    *Redis setbit 命令语法格式

    SETBIT key offset value
    
    • 1

    *范例

    127.0.0.1:6379> setbit aaa:001 10001 1 # 返回操作之前的数值
    (integer) 0
    127.0.0.1:6379> setbit aaa:001 10002 2 # 如果值不是0或1就报错
    (error) ERR bit is not an integer or out of range
    127.0.0.1:6379> setbit aaa:001 10002 0
    (integer) 0
    127.0.0.1:6379> setbit aaa:001 10003 1
    (integer) 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    七、基数统计 HyperLogLog

    Redis HyperLogLog 可以接受多个元素作为输入,并给出输入元素的基数估算值

    • 基数
      集合中不同元素的数量,比如 {‘apple’, ‘banana’, ‘cherry’, ‘banana’, ‘apple’} 的基数就是 3

    • 估算值
      算法给出的基数并不是精确的,可能会比实际稍微多一些或者稍微少一些,但会控制在合 理的范围之内

    HyperLogLog 的优点是:即使输入元素的数量或者体积非常非常大,计算基数所需的空间总是固定的、并且是很小的。

    在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 264 个不同元素的基数。

    这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

    因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

    • Redis PFADD 命令
      Redis PFADD 命令将元素添加至 HyperLogLog

      Redis PFADD 命令语法格式
      PFADD key element [element …]

    • 范例

    127.0.0.1:6379> PFADD unique::ip::counter '192.168.0.1'
    (integer) 1
    127.0.0.1:6379> PFADD unique::ip::counter '127.0.0.1'
    (integer) 1
    127.0.0.1:6379> PFADD unique::ip::counter '255.255.255.255'
    (integer) 1
    127.0.0.1:6379> PFCOUNT unique::ip::counter
    (integer) 3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    八、Geo 地理位置

    Redis 的 GEO 特性在 Redis 3.2 版本中推出, 这个功能可以将用户给定的地理位置信息储存起来, 并对这些信息进行操作。GEO的数据结构总共有六个命令:geoadd、geopos、geodist、georadius、georadiusbymember、gethash,GEO使用的是国际通用坐标系WGS-84。

    1. GEOADD:添加地理位置
    2. GEOPOS:查询地理位置(经纬度),返回数组
    3. GEODIST:计算两位位置间的距离
    4. GEORADIUS:以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
    5. GEORADIUSBYMEMBER:以给定的地理位置为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
    127.0.0.1:6379> geoadd kcityGeo 116.405285 39.904989 "beijing"
    (integer) 1
    127.0.0.1:6379> geoadd kcityGeo 121.472644 31.231706 "shanghai"
    (integer) 1 
    127.0.0.1:6379> geodist kcityGeo beijing shanghai km
    "1067.5980"
    127.0.0.1:6379> geopos kcityGeo beijing
    1) 1) "116.40528291463851929"
       2) "39.9049884229125027"
    127.0.0.1:6379> geohash kcityGeo beijing
    1) "wx4g0b7xrt0"
    127.0.0.1:6379> georadiusbymember kcityGeo beijing 1200 km withdist withcoord asc count 5
    1) 1) "beijing"
       2) "0.0000"
       3) 1) "116.40528291463851929"
          2) "39.9049884229125027"
    2) 1) "shanghai"
       2) "1067.5980"
       3) 1) "121.47264629602432251"
          2) "31.23170490709807012"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 内部编码
      但是,需要说明的是,Geo本身不是一种数据结构,它本质上还是借助于Sorted Set(ZSET),并且使用GeoHash技术进行填充。Redis中将经纬度使用52位的整数进行编码,放进zset中,score就是GeoHash的52位整数值。在使用Redis进行Geo查询时,其内部对应的操作其实就是zset(skiplist)的操作。通过zset的score进行排序就可以得到坐标附近的其它元素,通过将score还原成坐标值就可以得到元素的原始坐标。

    总之,Redis中处理这些地理位置坐标点的思想是:二维平面坐标点 --> 一维整数编码值 --> zset(score为编码值) --> zrangebyrank(获取score相近的元素)、zrangebyscore --> 通过score(整数编码值)反解坐标点 --> 附近点的地理位置坐标。

    • 应用场景
      • 比如现在比较火的直播业务,我们需要检索附近的主播,那么GEO就可以很好的实现这个功能。
        一是主播开播的时候写入主播Id的经纬度,
        二是主播关播的时候删除主播Id元素,这样就维护了一个具有位置信息的在线主播集合提供给线上检索。
      • 滴滴叫车:
        • 记录车位置:GEOADD cars:locations 116.034579 39.030452 33
        • 用户读取附近的车:GEORADIUS cars:locations 116.054579 39.030452 5 km ASC COUNT 10

    九、Streams 流

    这是Redis5.0引入的全新数据结构,用一句话概括Streams就是Redis实现的内存版kafka。支持多播的可持久化的消息队列,用于实现发布订阅功能,借鉴了 kafka 的设计。Redis Stream的结构有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的ID和对应的内容。消息是持久化的,Redis重启后,内容还在。

    在这里插入图片描述

    每个Stream都有唯一的名称,它就是Redis的key,在我们首次使用xadd指令追加消息时自动创建。

    每个Stream都可以挂多个消费组,每个消费组会有个游标last_delivered_id在Stream数组之上往前移动,表示当前消费组已经消费到哪条消息了。每个消费组都有一个Stream内唯一的名称,消费组不会自动创建,它需要单独的指令xgroup create进行创建,需要指定从Stream的某个消息ID开始消费,这个ID用来初始化last_delivered_id变量。

    每个消费组(Consumer Group)的状态都是独立的,相互不受影响。也就是说同一份Stream内部的消息会被每个消费组都消费到。

    同一个消费组(Consumer Group)可以挂接多个消费者(Consumer),这些消费者之间是竞争关系,任意一个消费者读取了消息都会使游标last_delivered_id往前移动。每个消费者者有一个组内唯一名称。

    消费者(Consumer)内部会有个状态变量pending_ids,它记录了当前已经被客户端读取的消息,但是还没有ack。如果客户端没有ack,这个变量里面的消息ID会越来越多,一旦某个消息被ack,它就开始减少。这个pending_ids变量在Redis官方被称之为PEL,也就是Pending Entries List,这是一个很核心的数据结构,它用来确保客户端至少消费了消息一次,而不会在网络传输的中途丢失了没处理。

    • 消息ID:消息ID的形式是timestampInMillis-sequence,例如1527846880572-5,它表示当前的消息在毫米时间戳1527846880572时产生,并且是该毫秒内产生的第5条消息。消息ID可以由服务器自动生成,也可以由客户端自己指定,但是形式必须是整数-整数,而且必须是后面加入的消息的ID要大于前面的消息ID。
    • 消息内容:消息内容就是键值对,形如hash结构的键值对,这没什么特别之处。
    127.0.0.1:6379> XADD mystream * field1 value1 field2 value2 field3 value3
    "1588491680862-0"
    127.0.0.1:6379> XADD mystream * username lisi age 18
    "1588491854070-0"
    127.0.0.1:6379> xlen mystream
    (integer) 2
    127.0.0.1:6379> XADD mystream * username lisi age 18
    "1588491861215-0"
    127.0.0.1:6379> xrange mystream - + 
    1) 1) "1588491680862-0"
       2) 1) "field1"
          2) "value1"
          3) "field2"
          4) "value2"
          5) "field3"
          6) "value3"
    2) 1) "1588491854070-0"
       2) 1) "username"
          2) "lisi"
          3) "age"
          4) "18"
    3) 1) "1588491861215-0"
       2) 1) "username"
          2) "lisi"
          3) "age"
          4) "18"
    127.0.0.1:6379> xdel mystream 1588491854070-0 
    (integer) 1
    127.0.0.1:6379> xrange mystream - + 
    1) 1) "1588491680862-0"
       2) 1) "field1"
          2) "value1"
          3) "field2"
          4) "value2"
          5) "field3"
          6) "value3"
    2) 1) "1588491861215-0"
       2) 1) "username"
          2) "lisi"
          3) "age"
          4) "18"
    127.0.0.1:6379> xlen mystream
    (integer) 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    内部编码
    streams底层的数据结构是radix tree:Radix Tree(基数树) 事实上就几乎相同是传统的二叉树。仅仅是在寻找方式上,以一个unsigned int类型数为例,利用这个数的每个比特位作为树节点的推断。能够这样说,比方一个数10001010101010110101010,那么依照Radix 树的插入就是在根节点,假设遇到0,就指向左节点,假设遇到1就指向右节点,在插入过程中构造树节点,在删除过程中删除树节点。如下是一个保存了7个单词的Radix Tree:

    应用场景总结

    实际上,所谓的应用场景,其实就是合理的利用Redis本身的数据结构的特性来完成相关业务功能,可参考我我之前写的文章:学了redis不会实战?看这篇就够了

  • 相关阅读:
    Python顺序表
    ubuntu配置ffmpeg环境
    【AUTOSAR-Nm】-2.1-APP SWC如何获取CanNm/LinNm...状态机的跳转
    Arduino与Proteus仿真-WiFi网络仿真环境搭建
    【软件测试从0到1】第三篇:用例篇
    别再用 System.currentTimeMillis 统计耗时了,太 Low,试试 Spring Boot 源码在用的 StopWatch吧,够优雅!
    python 裁剪图片并保存
    SMBGhost漏洞技术分析与防御方案
    SBT40100VFCT-ASEMI塑封肖特基二极管SBT40100VFCT
    Python数据结构(栈)
  • 原文地址:https://blog.csdn.net/u011397981/article/details/127915568