Redis5.0支持的九种数据类型及使用场景整理- Redis学习

Redis简介

Redis是一个开源的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。JAVA客户端是jedis。Redis6.0已经支持多线程了(面试提问redis是单线程还是多线程问题的时候要注意了)。

redis稳定版下载地址

Redis数据结构(罗列)

  • String:二进制安全的字符串

  • Lists:安插入顺序排序的字符串元素集合。基本是链表。

  • Sets:无序不重复集合。

  • Sorted sets(zset):里面的元素总是通过score进行排序。有序集合。

  • Hashes:键值都是字符串的哈希表。

  • Bit arrays:位集合(可以实现类似布隆过滤器的功能结构)

  • HyperLogLog:是用来做基数统计的算法。用于估计一个set中元素数量的概率性的数据结构。

  • Geospatial Indexes:地理空间索引

  • Streams:流信息

Redis keys

Redis key值是二进制安全的。(二进制安全 是指,在传输数据时,保证二进制数据的信息安全,也就是不被篡改、破译等,如果被攻击,能够及时检测出来。),可以是空值,也可以是任何二进制序列。

key的自动创建和删除

在实践中或例子里可以看到,我们没有在推入元素之前创建空的list,或者在list没有元素时删除它。在list为null删除key,并使用lpush时而创建空list. 这是Redis的职责。适用于list,zset,set,hash类型。

概括如下:

1当我们向一个聚合数据类型中添加元素时,如果目标键不存在,就在添加元素前创建空的聚合数据类型。
2当我们从聚合数据类型中移除元素时,如果值仍然是空的,键自动被销毁。
3对一个空的 key 3调用一个只读的命令,比如 LLEN (返回 list 的长度),或者一个删除元素的命令,将总是产生同样的结果。该结果和对一个空的聚合类型做同个操作的结果是一样的。

一、string 字符串

可以在一个键下保存一个图片,值的长度不能超过512MB.

//设置键值
> set mykey somevalue
OK
//获取键值
> get mykey
"somevalue"
//也可以通过命令进行递增操作
> set counter 100
OK
> incr counter //+1
(integer) 101
> incr counter
(integer) 102
> incrby counter 50   //+50
(integer) 152

INCR 命令将字符串值解析成整型后加一,然后在保存为字符串。类似命令有INCRBY,DECR,DECRBY。都是原子性操作,不会导致竞争的情况。

redis也可以做批量的操作,一次性设置获取多个值。

> mset a 10 b 20 c 30
OK
 
> mget a b c
"10"
"20"
"30"

其他命令

exists key:返回1或0标识给定key的值是否存在。

del key:返回1或0标识给定key的值是否存在

type key:返回key对应值的存储类型。

expire key time:给值设定存活时间。time可以是毫秒或者秒。(如果用rename命令修改key,相关时间也会转移到新名称上。针对已有过期时间的key进行操作,会刷新过期时间)

ttl key:用来查看key所对应值的剩余时间。

redis没有设置过期时间,ttl返回-1。
redis已经大于过期时间,ttl返回-2.

设置了剩余时间,且没过期的。ttl返回剩余时间。

没有设置过期时间的值可以通过del进行删除。

redis keys的过期有两种方式

1. 主动过期
当一些客户端尝访问它时,key会被发现并主动过期。

2. 被动过期

如果有一些keys,可能永远也不会访问。所以定时随机测试设置keys的过期时间。所有过期的keys将会从密钥空间删除。具体就是Redis每秒10次的操作。

a. 测试随机的20个keys进行相关过期检测。
b. 删除所有已经过期的keys
c. 如果有多于25%的keys过期,重复a



Redis String 使用场景: 普通key/value存储,比如统计IP访问次数(利用key名 + incr)

二、Redis Lists

Redis lists基于Linked List实现。在头部或者尾部添加一个元素的操作的时间复杂度是常数级别的。用LPUSH命令在十个元素的list头部添加元素和在千万级list头部添加元素的速度相同。

对于数据库来说,一个重要特性是能非常快的在列表上添加元素。而且redis lists能在常数时间内取得常数长度。所以用linked list实现。

rpush key value:向list的右边/尾部添加一个新元素。

lpush key value:向list的左边/头部添加一个新元素。

lrange key index index:从list中取出范围内元素,index可以为负数,表示从右边/尾部计数。

当然也可以批量处理数据

> rpush mylist 1 2 3 4 5 "foo bar"
(integer) 9
> lrange mylist 0 -1
1) "first"
2) "A"
3) "B"
4) "1"
5) "2"
6) "3"
7) "4"
8) "5"
9) "foo bar"

**rpop/lpop key **:从list中删除元素并返回删除元素的值。可以在头部/尾部操作。

**ltrim key index index **:把list从左边截取指定长度

> rpush mylist 1 2 3 4 5
(integer) 5
> ltrim mylist 0 2
OK
> lrange mylist 0 -1
1) "1"
2) "2"
3) "3"

list值类型,可以用来实现聊天系统,可以用来作为消息队列(按照顺序访问数据)。也可以使用lrange对结果进行分页。

用作为消息队列时,如果用lpush和rpop实现功能会出现一种情景(list为空,但是消费者一直轮询获取,会增加redis的访问压力、和cpu消耗),所以redis提供了阻塞式访问的brpop和blpop命令。可见详解:http://www.redis.cn/commands/blpop.html

三、Redis Hash

由键值对组成。适合存储对象型数据。Redis中的每个hash可以存储 2^32个键值对。

可以对散列存储的数字进行自增或自荐

> hmset user:1000 username antirez birthyear 1977 verified 1
OK
> hget user:1000 username
"antirez"
> hget user:1000 birthyear
"1977"
> hgetall user:1000
1) "username"
2) "antirez"
3) "birthyear"
4) "1977"
5) "verified"
6) "1"

hmset key value(k,v):用于设置hash的多个域。

hget key k:用于获取单个k对应的v.

hmget key k k k:用于获取多个k对应的v.

**hincrby key k 10 **:针对单独的值域进行操作。

更多指令请查看:http://redis.io/commands#hash

Redis hash应用场景:
存储对象型数据,如 人(属性,值,属性,值)

四、Redis Set

是对String的无序排列。

> sadd myset 1 2 3
(integer) 3
> smembers myset
1. 3
2. 1
3. 2

> sismember myset 3
(integer) 1

**sadd key v v v **:将新的元素添加到key中。

**smembers key **:返回所有元素,元素顺序不定。

smembers key v :检测某个元素是否存在

Sets适合用于标识对象间的关系,比如标识标记/打标签。

被打上相同标签的元素列表

> sadd tag:1:news 1000
(integer) 1
> sadd tag:2:news 1000
(integer) 1
> sadd tag:5:news 1000
(integer) 1
> sadd tag:77:news 1000
(integer) 1


## 获取一个对象的所有tag
> smembers news:1000:tags
1. 5
2. 1
3. 77
4. 2

set数据类型还有一个功能是sdiff,取差集(myset中排除myset2的值)。也可以用来对比两个集合的交集SINTER(属于A,也属于B)。可以利用这个功能处理对账数据。

> SADD myset "hello"
(integer) 1
> SADD myset "foo"
(integer) 1
> SADD myset "bar"
(integer) 1
> SADD myset2 "hello"
(integer) 1
> SADD myset2 "world"
(integer) 1
> SDIFF myset myset2
1) "foo"
2) "bar"

我在实际工作中,tag标记做法直接在数据库中做,方便多个维度的数据查询。
位运算的使用

关于redis set操作的更多命令查看:https://www.redis.net.cn/tutorial/3511.html

Redis set使用场景:
利用唯一性统计独立IP等。利用对交集、并集、差集的计算对数据进行过滤处理,如共同好友、推荐信息的数据过滤等。

五、Redis zset

Redis 有序集合和set集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

有序集合的成员是唯一的,但分数(score)却可以重复。(如果设置所有的元素score为一致的,则默认按照字典序排序。)

> zadd hackers 1940 "Alan Kay"
(integer) 1
> zadd hackers 1957 "Sophie Wilson"
(integer 1)
> zadd hackers 1953 "Richard Stallman"
(integer) 1
> zadd hackers 1949 "Anita Borg"
(integer) 1
> zadd hackers 1965 "Yukihiro Matsumoto"
(integer) 1
> zadd hackers 1914 "Hedy Lamarr"
(integer) 1
> zadd hackers 1916 "Claude Shannon"
(integer) 1
> zadd hackers 1969 "Linus Torvalds"
(integer) 1
> zadd hackers 1912 "Alan Turing"
(integer) 1
 
## 正序输出
> zrange hackers 0 -1
1) "Alan Turing"
2) "Hedy Lamarr"
3) "Claude Shannon"
4) "Alan Kay"
5) "Anita Borg"
6) "Richard Stallman"
7) "Sophie Wilson"
8) "Yukihiro Matsumoto"
9) "Linus Torvalds"

## 反序输出
> zrevrange hackers 0 -1
1) "Linus Torvalds"
2) "Yukihiro Matsumoto"
3) "Sophie Wilson"
4) "Richard Stallman"
5) "Anita Borg"
6) "Alan Kay"
7) "Claude Shannon"
8) "Hedy Lamarr"
9) "Alan Turing"

## 1950以下的数据
> zrangebyscore hackers -inf 1950
1) "Alan Turing"
2) "Hedy Lamarr"
3) "Claude Shannon"
4) "Alan Kay"
5) "Anita Borg"

## 删除1940~1960区间内的元素
> zremrangebyscore hackers 1940 1960
(integer) 4

## 查询zset中的元素index

> zrank hackers "Anita Borg"
(integer) 4

Redis ZSet使用场景:
排行榜、统计类的数据需求。

六、Redis Bitmap

位图不是实际的数据类型,而是在String类型上定义的一组面向位的操作。

由于字符串是二进制安全的,最大长度是512MB,转换成位可以设置 2^32不同的位。

512MB = 2^9 * 2^3(byte) * 2^10(kb) * 2^10(mb) = 2^32(bit)

位图的最大优点之一,存储信息时可以节省大量空间。

> set key big

位操作分为两类:
1.固定时间的单个位操作(设置位为1或0获取当前位的值)

## 设置位值为1
> setbit key 10 1
(integer) 1

## 获取
> getbit key 10
(integer) 1

## 获取没有存过的值时为0
> getbit key 11
(integer) 0

2.对位组的操作(获取范围内的位的数量、效率很高)

> setbit key 0 1
(integer) 0
> setbit key 100 1
(integer) 0
> bitcount key
(integer) 2

注: Bitmap 和 HyperLogLog是基于String类型,但是拓展了自己的语义

Redis Bitmap使用情景

  1. 各种实时分析。

例如,假设您想知道网站用户每天访问量最长的时间。您从零开始计算天数,即从您公开网站的那一天开始,并在用户每次访问该网站时对SETBIT进行设置。作为位索引,您只需花费当前的unix时间,减去初始偏移,然后除以3600 * 24。
这样,对于每个用户,您都有一个小的字符串,其中包含每天的访问信息。

> setbit key 20200310-UID 1
> setbit key 20200311-UID 1
> setbit key 20200311-UID 0

  1. 类似bloomfilter的实现,防止缓存穿透。(将存量 + 增量的标识数据进行存储,去判断)

  2. 可以通过多个bitmap的交集、并集、not(非)、xor(疑惑)操作处理一些位运算的逻辑

bitmap 可以使用RLE编码进一步压缩空间

七、Redis HyperLogLogs(HLL)

属于一种概率算法,(LC,LLC,HLL)三种越来越节省内存,降低误差率。

HyperLogLog优点,在输入元素的数量或者体积非常大时。计算基数所需的空间总是固定很小的。每个HyperLogLog的键只需要花费12KB内存,在标准误差0.81%的前提下,就可以计算接近2^64个不同的基数。

用bitmap存储1一亿个统计数据大概需要12M内存;而在HLL中,只需要不到1K内存就能做到。

了解HLL原理可以点击这里:

HyperLogLog只会根据输入元素来计算基数,而不会存储元素本身,所以不能返回各个元素。

## 添加指定元素到HLL中
> pfadd hll a b c d
  (integer) 1

## 返回给定的HLL的基数估算值
> pfcount hll
  (integer) 4
  
## 合并HLL
> pfmerge key sourceA [sourceB]

HLL的使用场景:常用来统计一个集合中不重复的元素个数,例如网站PV,搜索关键词数量,数据分析、网络监控及数据库优化等领域。

HLL比 bitmap更节省内存,但有一定误差( 标准误差 0.81%)

八、Redis Geospatial Indexes(地理空间索引)

将制定的地理空间位置(经度、纬度、名称)添加到指定的key中。这些数据将会存储到Sorted set中。目的是为了方便GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。

sorted set使用一种称为Geohash的技术进行填充。经度和纬度的位是交错的,以形成一个独特的52位整数. 我们知道,一个sorted set 的double score可以代表一个52位的整数,而不会失去精度。

这种格式允许半径查询检查的1 + 8个领域需要覆盖整个半径,并丢弃元素以外的半径。通过计算该区域的范围,通过计算所涵盖的范围,从不太重要的部分的排序集的得分,并计算得分范围为每个区域的sorted set中的查询。

官方示例

## 增加意大利西西里岛的两个城市坐标(Palermo和 卡塔尼亚)
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

## 返回两个给定位置之间的距离。(默认单位米)
redis> GEODIST Sicily Palermo Catania
"166274.1516"

## 以给定的经纬度为中心,返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
## 100m
redis> GEORADIUS Sicily 15 37 100 km
1) "Catania"

## 200m
redis> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"
redis> 

可以通过查询不同地方的坐标信息进行验证。查询点这里

Geospatial indexes使用场景:这里假设地球是一个球体,因为使用的距离公式是Haversine公式。这个公式仅适用于地球,而不是一个完美的球体。当在社交网站和其他大多数需要查询半径的应用中使用时,这些偏差都不算问题。但是,在最坏的情况下的偏差可能是0.5%,所以一些地理位置很关键的应用还是需要谨慎考虑。

九、Redis Streams

Stream是Redis 5.0引入的一种新数据类型,是一个新的强大的支持多播的可持久化的消息队列。

相比于现有的PUB/SUB、BLOCKED LIST,其虽然也可以在简单的场景下作为消息队列来使用,但是Redis Stream无疑要完善很多。Redis Stream提供了消息的持久化和主备复制功能、新的RadixTree数据结构来支持更高效的内存使用和消息读取、甚至是类似于Kafka的Consumer Group功能。

它以更抽象的方式对日志数据结构进行建模,但是日志的本质仍然完好无损:像日志文件一样,通常实现为仅在追加模式下打开的文件, Redis流主要是仅追加数据结构。至少从概念上讲,由于Redis是流式传输在内存中表示的抽象数据类型,因此它们实现了更强大的操作,以克服日志文件本身的限制。

尽管数据结构本身非常简单,但Redis流却成为最复杂的Redis类型的原因在于它实现了其他非强制性功能:一组阻止操作,使消费者可以等待生产者将新数据添加到流中,此外还有一个称为“ 消费群体”的概念。

消费者群体最初是由流行的称为Kafka(TM)的消息传递系统引入的。Redis用完全不同的术语重新实现了一个类似的想法,但是目标是相同的:允许一组客户合作使用同一消息流的不同部分。

> XADD mystream * sensor-id 1234 temperature 19.8
1518951480106-0

##上面对XADD命令的调用使用自动生成的条目ID 
##将一个条目添加sensor-id: 1234, temperature: 19.8到key流中mystream,该条目ID是该命令返回的,具体来说是1518951480106-0。
##它以键名作为第一个参数mystream,第二个参数是标识流中每个条目的条目ID。


## 获取Stream中的项目数:
> XLEN mystream
(integer) 1


针对流的操作有很多,可以点击这里查看官方文档

Redis stream使用场景:消息队列,和kafka, RocketMq ,RabbitMq等各种消息中间件要按照当前环境的情况和要求合理使用。

整理自我的小博客 deathearth.com

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Redis支持五种数据结构类型:字符串(string)、列表(list)、哈希(hash)、集合(sets)、有序集合(sorted sets)。它们可以用于实现缓存、消息队列、计数器、在线聊天室、投票系统、排行榜等应用场景。 ### 回答2: Redis支持多种数据结构类型,常用的有字符串、哈希、列表、集合和有序集合。 1. 字符串(strings):最基本的数据结构类型,可以存储字符串、整数或浮点数等。常用场景包括缓存、计数器和分布式锁等。 2. 哈希(hashes):类似于一个关联数组,可以存储多个字段和值的映射关系。适用于存储对象的各个属性,例如用户信息、商品详情等。 3. 列表(lists):支持在头部或尾部添加或删除元素,保持了元素的插入顺序。常用于消息队列、发布订阅系统和任务队列等场景。 4. 集合(sets):无序且唯一的元素集合。适用于需要对元素进行去重或集合操作的场景,例如标签云、社交关系等。 5. 有序集合(sorted sets):元素集合,每个元素都关联了一个分数,用于排序和获取范围内的元素。常见应用包括排行榜、热门文章等。 这些数据结构类型提供了丰富的功能和灵活性,可以根据不同的场景选择适合的数据结构Redis 的快速读写性能和丰富的数据类型使得它成为了很多应用场景的首选,包括缓存、计数器、消息队列、排行榜、实时数据分析等。 ### 回答3: Redis是一款开源的、高性能的非关系型内存数据库,支持多种数据结构类型。常用的Redis数据结构类型有字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set)。 字符串类型是Redis最基本的数据结构类型,可以存储字符串和整数。它常用于缓存、计数器、共享会话等场景。 哈希类型可以存储多个字段和值的映射关系,类似于关联数组或字典。它适用于存储用户信息、商品信息等结构化的数据。 列表类型是有序的字符串列表,可以在列表的两端进行插入、删除和查找操作。它适合做消息队列、最新消息排行等场景。 集合类型是无序的字符串集合,可以对集合进行交集、并集和差集等操作,也支持添加、删除和查找元素。常用的场景包括社交关系、标签系统等。 有序集合类型是在集合类型的基础上,为每个元素关联一个分数,可以根据分数进行元素排序。它适用于排行榜、按照分数范围查找等场景。 除了以上几种数据结构类型,Redis还提供了位图、地理位置等特殊类型,可以应用于统计用户在线时长、地理位置检索等特定需求。 总而言之,Redis提供了多种数据结构类型,每种类型都有其独特的使用场景。根据具体的业务需求,选择适合的数据结构类型可以提升数据处理效率和灵活性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值