redis的数据类型有哪些redis 五种数据类型使用方法




redis的数据类型有哪些redis 五种数据类型使用方法

2022-07-21 2:24:09 网络知识 官方管理员

  redis有5种基本数据结构,它们是String(string)、列表(list)、hash(字典)、set(集合)和zset(有序集合),redis的所有数据结构都使用惟一的key字符串作为名称,接着,根据这个惟一的key值得到对应的值,不同的数据结构的差异就在于value的数据结构的差异

  Redis基本数据类型

  String

  字符串常用操作

SETkeyvalue//存入字符串键值对MSETkeyvalue[keyvalue...]//批量存储字符串键值对SETNXkeyvalue//存入一个不存在的字符串键值对GETkey//获取一个字符串键值MGETkey[key...]//批量获取字符串键值DELkey[key...]//删除一个键EXPIREkeyseconds//设置一个键的过期时间(秒)1234567复制代码类型:[java]

  原子加减

INCRkey//将key中储存的数字值加1DECRkey//将key中储存的数字值减1INCRBYkeyincrement//将key所储存的值加上incrementDECRBYkeydecrement//将key所储存的值减去decrement1234复制代码类型:[java]

  String应用场景

  单值缓存

SETkeyvalueGETkeySETuser:1value(json格式数据)MSETuser:1:nameAuser:1:age18MGETuser:1:nameuser:1:age12345复制代码类型:[java]

  分布式锁

SETNXproduct:10001true//返回1代表获取锁成功SETNXproduct:10001true//返回0代表获取锁失败...//业务操作DELproduct:10001//执行完业务释放锁SETproduct:10001trueex10nx//防止程序意外终止导致死锁12345复制代码类型:[java]

  计数器

INCRarticle:readcount:{文章id}GETarticle:readcount:{文章id}12复制代码类型:[java]

  Web集群session共享

springsession+redis实现session共享1复制代码类型:[java]

  分布式系统全局序列号

INCRBYorderId1000//redis批量生成序列号提升性能1复制代码类型:[java]

  List

  List常用操作

LPUSHkeyvalue[value...]//将一个或多个值value插入到key列表的表头(最左边)RPUSHkeyvalue[value...]//将一个或多个值value插入到key列表的表尾(最右边)LPOPkey//移除并返回key列表的头元素RPOPkey//移除并返回key列表的尾元素LRANGEkeystartstop//返回列表key中指定区间内的元素,区间以偏移量start和stop指定BLPOPkey[key...]timeout//从key列表表头弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待BRPOPkey[key...]timeout//从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞1234567复制代码类型:[java]

redis的数据类型有哪些(redis五种数据类型使用方法)(1)

  List应用场景

  常用数据结构

  Stack(栈)=LPUSH+LPOP

  Queue(队列)=LPUSH+RPOP

  BlockingMQ(阻塞队列)=LPUSH+BRPOP

  微博消息和微信公众号消息

A关注了B,C1)B发微博,消息ID为10001LPUSHmsg:{A-ID}100012)C发微博,消息ID为10002LPUSHmsg:{A-ID}100023)A查看最新微博消息LRANGEmsg:{A-ID}041234567复制代码类型:[java]

  Hash

  常用操作

HSETkeyfieldvalue//存储一个哈希表key的键值HSETNXkeyfieldvalue//存储一个不存在的哈希表key的键值HMSETkeyfieldvalue[fieldvalue...]//在一个哈希表key中存储多个键值对HGETkeyfield//获取哈希表key对应的field键值HMGETkeyfield[field...]//批量获取哈希表key中多个field键值HDELkeyfield[field...]//删除哈希表key中的field键值HLENkey//返回哈希表key中field的数量HGETALLkey//返回哈希表key中所有的键值HINCRBYkeyfieldincrement//为哈希表key中field键的值加上增量increment123456789复制代码类型:[java]

  Hash应用场景

  对象缓存

INCRkey//将key中储存的数字值加1DECRkey//将key中储存的数字值减1INCRBYkeyincrement//将key所储存的值加上incrementDECRBYkeydecrement//将key所储存的值减去decrement1234复制代码类型:[java]0

  电商购物车

INCRkey//将key中储存的数字值加1DECRkey//将key中储存的数字值减1INCRBYkeyincrement//将key所储存的值加上incrementDECRBYkeydecrement//将key所储存的值减去decrement1234复制代码类型:[java]1

  Hash结构优缺点

  优点

  1)同类数据归类整合储存,方便数据管理

  2)相比string操作消耗内存与cpu更小

  3)相比string储存更节省空间

  缺点

  1)过期功能不能使用在field上,只能用在key上

  2)Redis集群架构下不适合大规模使用

  Set

  Set常用操作

INCRkey//将key中储存的数字值加1DECRkey//将key中储存的数字值减1INCRBYkeyincrement//将key所储存的值加上incrementDECRBYkeydecrement//将key所储存的值减去decrement1234复制代码类型:[java]2

  Set运算操作

INCRkey//将key中储存的数字值加1DECRkey//将key中储存的数字值减1INCRBYkeyincrement//将key所储存的值加上incrementDECRBYkeydecrement//将key所储存的值减去decrement1234复制代码类型:[java]3

  Set应用场景

  微信抽奖小程序

INCRkey//将key中储存的数字值加1DECRkey//将key中储存的数字值减1INCRBYkeyincrement//将key所储存的值加上incrementDECRBYkeydecrement//将key所储存的值减去decrement1234复制代码类型:[java]4

  微信微博点赞,收藏,标签

INCRkey//将key中储存的数字值加1DECRkey//将key中储存的数字值减1INCRBYkeyincrement//将key所储存的值加上incrementDECRBYkeydecrement//将key所储存的值减去decrement1234复制代码类型:[java]5

  集合操作

INCRkey//将key中储存的数字值加1DECRkey//将key中储存的数字值减1INCRBYkeyincrement//将key所储存的值加上incrementDECRBYkeydecrement//将key所储存的值减去decrement1234复制代码类型:[java]6

redis的数据类型有哪些(redis五种数据类型使用方法)(2)

  集合操作实现微博微信关注模型

INCRkey//将key中储存的数字值加1DECRkey//将key中储存的数字值减1INCRBYkeyincrement//将key所储存的值加上incrementDECRBYkeydecrement//将key所储存的值减去decrement1234复制代码类型:[java]7

  集合操作实现电商商品筛选

INCRkey//将key中储存的数字值加1DECRkey//将key中储存的数字值减1INCRBYkeyincrement//将key所储存的值加上incrementDECRBYkeydecrement//将key所储存的值减去decrement1234复制代码类型:[java]8

redis的数据类型有哪些(redis五种数据类型使用方法)(3)

  ZSet(SortedSet)

  ZSet常用操作

INCRkey//将key中储存的数字值加1DECRkey//将key中储存的数字值减1INCRBYkeyincrement//将key所储存的值加上incrementDECRBYkeydecrement//将key所储存的值减去decrement1234复制代码类型:[java]9

  Zset集合操作

SETkeyvalueGETkeySETuser:1value(json格式数据)MSETuser:1:nameAuser:1:age18MGETuser:1:nameuser:1:age12345复制代码类型:[java]0

redis的数据类型有哪些(redis五种数据类型使用方法)(4)

  Zset集合操作实现排行榜

SETkeyvalueGETkeySETuser:1value(json格式数据)MSETuser:1:nameAuser:1:age18MGETuser:1:nameuser:1:age12345复制代码类型:[java]1

  Redis的补充数据类型

  BitMap

  BitMap就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身,实际上底层也是通过对字符串的操作来实现。Redis从2.2版本之后新增了setbit,getbit,bitcount等几个bitmap相关命令。虽然是新命令,但是本身都是对字符串的操作,我们先来看看语法:

SETkeyvalueGETkeySETuser:1value(json格式数据)MSETuser:1:nameAuser:1:age18MGETuser:1:nameuser:1:age12345复制代码类型:[java]2

  其中offset必须是数字,value只能是0或者1.offset参数要求大于或等于0.并且小于2^32(4.294.967.296),这将位图限制在512MB

  设置最后一个可能的位时(偏移量等于2^32-1)和存储在键中的字符串值尚不保存字符串值,或持有一个小字符串值,Redis需要分配所有中间内存,这些中间内存可能会阻塞服务器一段时间。在2010年MacbookPro上,设置位号2^32-1(512MB分配)需要300毫秒,设置位数2^30-1(128MB分配)需要80毫秒,设置位数2^28-1(32MB分配)需要30毫秒并设置位号2^26-1(8MB分配)需要±8毫秒。请注意,完成第一次分配后,对同一key的SETBIT的后续调用将不具有分配开销。

SETkeyvalueGETkeySETuser:1value(json格式数据)MSETuser:1:nameAuser:1:age18MGETuser:1:nameuser:1:age12345复制代码类型:[java]3

  其中offset必须是数字,value只能是0或者1.通过bitcount可以很快速的统计,比传统的关系型数据库效率高很多

SETkeyvalueGETkeySETuser:1value(json格式数据)MSETuser:1:nameAuser:1:age18MGETuser:1:nameuser:1:age12345复制代码类型:[java]4

  HyperLogLog

  Redis在2.8.9版本添加了HyperLogLog结构。RedisHyperLogLog是用来做基数统计的算法,HyperLogLog的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。

  在Redis里面,每个HyperLogLog键只需要花费12KB内存,就可以计算接近2^64个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

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

  1.基于bitmap计数

  2.基于概率基数计数

  1)线性计数算法

  2)对数计数算法(LLC)

  3)自适应计数算法

  4)超对数计数算法

  这个数据结构的命令有三个:PFADD、PFCOUNT、PFMERGE

  用途:记录网站IP注册数,每日访问的IP数,页面实时UV、在线用户人数

  局限性:只能统计数量,没有办法看具体信息

SETkeyvalueGETkeySETuser:1value(json格式数据)MSETuser:1:nameAuser:1:age18MGETuser:1:nameuser:1:age12345复制代码类型:[java]5

  Geospatial

  底层数据结构Zset

  命令:GEOADD、GEODIST、GEOHASH、GEOPOP、GEOPADUIS、GEORADIUSBYMEMBER

  可以用来保存地理位置,并作位置距离计算或者根据半径计算位置等。有没有想过用Redis来实现附近的人?或者计算最优地图路径?Geo本身不是一种数据结构,它本质上还是借助于SortedSet(ZSET)

  RedisGEO操作方法有:

  geoadd:添加地理位置的坐标。

  geopos:获取地理位置的坐标。

  geodist:计算两个位置之间的距离。

  georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。

  georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。

  geohash:返回一个或多个位置对象的geohash值。

  把某个具体的位置信息(经度,纬度,名称)添加到指定的key中,数据将会用一个sortedset存储,以便稍后能使用GEORADIUS和GEORADIUSBYMEMBER命令来根据半径来查询位置信息。

SETkeyvalueGETkeySETuser:1value(json格式数据)MSETuser:1:nameAuser:1:age18MGETuser:1:nameuser:1:age12345复制代码类型:[java]6

  精确到小数点后6位可以达到约1米精度,所以一般经纬度精确到小数点后6位即可。

  Redis消息模式

  队列模式

  使用list类型的lpush和rpop实现消息队列

redis的数据类型有哪些(redis五种数据类型使用方法)(5)

  注意事项:

  消息接收方如果不知道队列中是否有消息,会一直发送rpop命令,如果这样的话,会每一次都建立一次连接,这样显然不好。

  可以使用brpop命令,它如果从队列中取不出来数据,会一直阻塞,在一定范围内没有取出则返回null

  缺点:

  做消费者确认ACK麻烦,不能保证消费者消费消息后是否成功处理的问题(宕机或处理异常等),通常需要维护一个Pending列表,保证消息处理确认。

  不能做广播模式,如pub/sub,消息发布/订阅模型

  不能重复消费,一旦消费就会被删除

  不支持分组消费

  发布订阅模式

  SUBSCRIBE,用于订阅信道

  PUBLISH,向信道发送消息

  UNSUBSCRIBE,取消订阅

  此模式允许生产者只生产一次消息,由中间件负责将消息复制到多个消息队列,每个消息队列由对应的消费组消费。

redis的数据类型有哪些(redis五种数据类型使用方法)(6)

  优点

  典型的广播模式,一个消息可以发布到多个消费者;多信道订阅,消费者可以同时订阅多个信道,从而接收多类消息;消息即时发送,消息不用等待消费者读取,消费者会自动接收到信道发布的消息

  缺点

  消息一旦发布,不能接收。换句话就是发布时若客户端不在线,则消息丢失,不能寻回;不能保证每个消费者接收的时间是一致的;若消费者客户端出现消息积压,到一定程度,会被强制断开,导致消息意外丢失。通常发生在消息的生产远大于消费速度时

  可见,Pub/Sub模式不适合做消息存储,消息积压类的业务,而是擅长处理广播,即时通讯,即时反馈的业务。

  基于Sorted-Set的实现

  SortesSet(有序列表),类似于java的SortedSet和HashMap的结合体,一方面它是一个set,保证内部value的唯一性,另一方面它可以给每个value赋予一个score,代表这个value的排序权重。内部实现是“跳跃表”。

  有序集合的方案是在自己确定消息顺ID时比较常用,使用集合成员的Score来作为消息ID,保证顺序,还可以保证消息ID的单调递增。通常可以使用时间戳+序号的方案。确保了消息ID的单调递增,利用SortedSet的依据Score排序的特征,就可以制作一个有序的消息队列了。

  优点

  就是可以自定义消息ID,在消息ID有意义时,比较重要。

  缺点

  缺点也明显,不允许重复消息(因为是集合),同时消息ID确定有错误会导致消息的顺序出错。

  RedisStream

  Redis5.0全新的数据类型:streams,官方把它定义为:以更抽象的方式建模日志的数据结构。Redis的streams主要是一个appendonly(AOF)的数据结构,至少在概念上它是一种在内存中表示的抽象数据类型,只不过它们实现了更强大的操作,以克服日志文件本身的限制。

  如果你了解MQ,那么可以把streams当做基于内存的MQ。如果你还了解kafka,那么甚至可以把streams当做基于内存的kafka。listpack存储信息,Rax组织listpack消息链表

  listpack是对ziplist的改进,它比ziplist少了一个定位最后一个元素的属性

  另外,这个功能有点类似于redis以前的Pub/Sub,但是也有基本的不同:

  1、streams支持多个客户端(消费者)等待数据(Linux环境开多个窗口执行XREAD即可模拟),并且每个客户端得到的是完全相同的数据。

  2、Pub/Sub是发送忘记的方式,并且不存储任何数据;而streams模式下,所有消息被无限期追加在streams中,除非用于显式执行删除(XDEL)。XDEL只做一个标记位其实信息和长度还在

  3、streams的ConsumerGroups也是Pub/Sub无法实现的控制方式。

  streams数据结构本身非常简单,但是streams依然是Redis到目前为止最复杂的类型,其原因是实现的一些额外的功能:一系列的阻塞操作允许消费者等待生产者加入到streams的新数据。另外还有一个称为ConsumerGroups的概念,ConsumerGroup概念最先由kafka提出,Redis有一个类似实现,和kafka的ConsumerGroups的目的是一样的:允许一组客户端协调消费相同的信息流!

  消息队列相关命令:

SETkeyvalueGETkeySETuser:1value(json格式数据)MSETuser:1:nameAuser:1:age18MGETuser:1:nameuser:1:age12345复制代码类型:[java]7
SETkeyvalueGETkeySETuser:1value(json格式数据)MSETuser:1:nameAuser:1:age18MGETuser:1:nameuser:1:age12345复制代码类型:[java]8

  消费者组相关命令:

SETkeyvalueGETkeySETuser:1value(json格式数据)MSETuser:1:nameAuser:1:age18MGETuser:1:nameuser:1:age12345复制代码类型:[java]9
SETNXproduct:10001true//返回1代表获取锁成功SETNXproduct:10001true//返回0代表获取锁失败...//业务操作DELproduct:10001//执行完业务释放锁SETproduct:10001trueex10nx//防止程序意外终止导致死锁12345复制代码类型:[java]0

  XADD

  使用XADD向队列添加消息,如果指定的队列不存在,则创建一个队列,XADD语法格式:

SETNXproduct:10001true//返回1代表获取锁成功SETNXproduct:10001true//返回0代表获取锁失败...//业务操作DELproduct:10001//执行完业务释放锁SETproduct:10001trueex10nx//防止程序意外终止导致死锁12345复制代码类型:[java]1
SETNXproduct:10001true//返回1代表获取锁成功SETNXproduct:10001true//返回0代表获取锁失败...//业务操作DELproduct:10001//执行完业务释放锁SETproduct:10001trueex10nx//防止程序意外终止导致死锁12345复制代码类型:[java]2

  XTRIM

  使用XTRIM对流进行修剪,限制长度,语法格式:

SETNXproduct:10001true//返回1代表获取锁成功SETNXproduct:10001true//返回0代表获取锁失败...//业务操作DELproduct:10001//执行完业务释放锁SETproduct:10001trueex10nx//防止程序意外终止导致死锁12345复制代码类型:[java]3
SETNXproduct:10001true//返回1代表获取锁成功SETNXproduct:10001true//返回0代表获取锁失败...//业务操作DELproduct:10001//执行完业务释放锁SETproduct:10001trueex10nx//防止程序意外终止导致死锁12345复制代码类型:[java]4

  XDEL

  使用XDEL删除消息,语法格式:

SETNXproduct:10001true//返回1代表获取锁成功SETNXproduct:10001true//返回0代表获取锁失败...//业务操作DELproduct:10001//执行完业务释放锁SETproduct:10001trueex10nx//防止程序意外终止导致死锁12345复制代码类型:[java]5
SETNXproduct:10001true//返回1代表获取锁成功SETNXproduct:10001true//返回0代表获取锁失败...//业务操作DELproduct:10001//执行完业务释放锁SETproduct:10001trueex10nx//防止程序意外终止导致死锁12345复制代码类型:[java]6

  XLEN

  使用XLEN获取流包含的元素数量,即消息长度,语法格式:

SETNXproduct:10001true//返回1代表获取锁成功SETNXproduct:10001true//返回0代表获取锁失败...//业务操作DELproduct:10001//执行完业务释放锁SETproduct:10001trueex10nx//防止程序意外终止导致死锁12345复制代码类型:[java]7
SETNXproduct:10001true//返回1代表获取锁成功SETNXproduct:10001true//返回0代表获取锁失败...//业务操作DELproduct:10001//执行完业务释放锁SETproduct:10001trueex10nx//防止程序意外终止导致死锁12345复制代码类型:[java]8

  XRANGE

  使用XRANGE获取消息列表,会自动过滤已经删除的消息,语法格式:

SETNXproduct:10001true//返回1代表获取锁成功SETNXproduct:10001true//返回0代表获取锁失败...//业务操作DELproduct:10001//执行完业务释放锁SETproduct:10001trueex10nx//防止程序意外终止导致死锁12345复制代码类型:[java]9
INCRarticle:readcount:{文章id}GETarticle:readcount:{文章id}12复制代码类型:[java]0

  XREVRANGE

  使用XREVRANGE获取消息列表,会自动过滤已经删除的消息,语法格式:

INCRarticle:readcount:{文章id}GETarticle:readcount:{文章id}12复制代码类型:[java]1
INCRarticle:readcount:{文章id}GETarticle:readcount:{文章id}12复制代码类型:[java]2

  XREAD

  使用XREAD以阻塞或非阻塞方式获取消息列表,语法格式:

INCRarticle:readcount:{文章id}GETarticle:readcount:{文章id}12复制代码类型:[java]3
INCRarticle:readcount:{文章id}GETarticle:readcount:{文章id}12复制代码类型:[java]4

  以上是XREAD的非阻塞形式。注意COUNT选项并不是必需的,实际上这个命令唯一强制的选项是STREAMS,指定了一组key以及调用者已经看到的每个Stream相应的最大ID,以便该命令仅向客户端提供ID大于我们指定ID的消息。

  第二条命令指定了新的BLOCK选项,超时时间为0毫秒(意味着永不超时)。此外,并没有给流mystream传入一个常规的ID,而是传入了一个特殊的ID$。这个特殊的ID意思是XREAD应该使用流mystream已经存储的最大ID作为最后一个ID。

  XGROUPCREATE

  使用XGROUPCREATE创建消费者组,语法格式:

INCRarticle:readcount:{文章id}GETarticle:readcount:{文章id}12复制代码类型:[java]5
INCRarticle:readcount:{文章id}GETarticle:readcount:{文章id}12复制代码类型:[java]6

  XREADGROUPGROUP

  使用XREADGROUPGROUP读取消费组中的消息,语法格式:

INCRarticle:readcount:{文章id}GETarticle:readcount:{文章id}12复制代码类型:[java]7
INCRarticle:readcount:{文章id}GETarticle:readcount:{文章id}12复制代码类型:[java]8

  在以上命令行中还有另外一个非常重要的细节在强制选项STREAMS之后,键mystream请求的ID是特殊的ID>。这个特殊的ID只在消费者组的上下文中有效,其意思是:消息到目前为止从未传递给其他消费者。

  实例:

INCRarticle:readcount:{文章id}GETarticle:readcount:{文章id}12复制代码类型:[java]9
springsession+redis实现session共享1复制代码类型:[java]0

  通过消费组读取消息

springsession+redis实现session共享1复制代码类型:[java]1
springsession+redis实现session共享1复制代码类型:[java]2

  数据类型有几种?

  我们先创建一下几种类型,然后通过type命令来查看一下

springsession+redis实现session共享1复制代码类型:[java]3
springsession+redis实现session共享1复制代码类型:[java]4

  由此可见,redis实际是有6种数据类型的,bitmap和hyperloglog的数据类型其实是String,geo的类型其实是zset,redis5之后又加了一种stream,所以是6种,bitmap和hyperloglog还有geo的数据类型是跟他们的实现原理有关的,接下来的几次课,咱们来一起研究redis是如何实现这几种数据类型的


发表评论:

最近发表
网站分类
标签列表