Redis 数据类型

Redis支持多种数据类型:string(字符串)hash(哈希)list(列表)set(集合)zset(sorted set 有序集合)streams(流)geospatial(地理空间)HyperLogLogbitmaps(位图)bitfields(位字段)

String(字符串)

string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。

string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象 。

string 类型是 Redis 最基本的数据类型,一个键最大能存储 512MB。

实例:

127.0.0.1:6379> set url "www.hxstrive.com"
OK
127.0.0.1:6379> get url
"www.hxstrive.com"

在以上实例中我们使用了 Redis 的 SET 和 GET 命令。键为 url,对应的值为 www.hxstrive.com。

注意:一个键最大能存储 512MB。

Hash(哈希)

Redis hash 是一个键值对集合。

Redis hash 是一个 string 类型的字段和 value 的映射表,hash 特别适合用于存储对象。例如:

id=1000
username=Tom
email=tom@163.com

实例:

127.0.0.1:6379> hmset user:1 id 1000 username Tom email tom@163.com
OK
127.0.0.1:6379> hgetall user:1
1) "id"
2) "1000"
3) "username"
4) "Tom"
5) "email"
6) "tom@163.com"

以上实例中 hash 数据类型存储了包含用户信息的用户对象(其中,用户ID 为 1000,姓名为 Tom,邮件为 tom@163.com)。实例中我们使用了 Redis HMSET, HEGTALL 命令,user:1 为键值。

注意:每个 hash 可以存储 2^32 - 1 键值对(40多亿)。

List(列表)

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

实例:

127.0.0.1:6379> lrange myKey 0 10
(empty list or set)
127.0.0.1:6379> lpush myKey mongodb
(integer) 1
127.0.0.1:6379> lpush myKey redis
(integer) 2
127.0.0.1:6379> lrange myKey 0 10
1) "redis"
2) "mongodb"

上面实例中 myKey 是键值,使用了两次 lpush 向列表添加数据,然后使用 lrange 获取列表的内容,列表中存在两个元素。

注意:列表最多可存储 2^32 - 1 元素 (4294967295,每个列表可存储40多亿)。

Set(集合)

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

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

sadd 命令

添加一个 string 元素到 key 对应的 set 集合中,成功返回 1。如果元素已经在集合中,则返回 0。如果 key 对应的 set 不存在,则返回错误。语法如下:

sadd key member

实例:

127.0.0.1:6379> sadd setKey mongodb
(integer) 1
127.0.0.1:6379> sadd setKey redis
(integer) 1
127.0.0.1:6379> sadd setKey mysql
(integer) 1
127.0.0.1:6379> smembers setKey
1) "mysql"
2) "redis"
3) "mongodb"

上面实例分别使用 sadd 命令向名为 setKey 的集合中添加了三个不重复的值,然后使用 smembers 命令获取集合中所有元素。

如果我们向 setKey 集合中再次添加 redis 值,会发生什么呢?

127.0.0.1:6379> sadd setKey redis
(integer) 0

以上实例再次向 setKey 集合中添加 redis 值,但根据集合内元素的唯一性,本次插入的元素将被忽略,因此 sadd 命令返回 0。

注意:集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储 40 多亿个成员)。

zset(sorted set 有序集合)

Redis zset 和 set 一样也是 string 类型元素的集合,且不允许重复的成员。

不同的是每个元素都会关联一个 double 类型的分数,redis 正是通过分数来为集合中的成员进行从小到大的排序。

zset 的成员是唯一的,但分数(score)却可以重复。

zadd 命令

添加元素到集合,元素在集合中存在则更新对应 score(分数):

zadd key score member

实例:

127.0.0.1:6379> zadd zsetkey 0 redis
(integer) 1
127.0.0.1:6379> zadd zsetkey 0 mongodb
(integer) 1
127.0.0.1:6379> zadd zsetkey 0 rabbitmq
(integer) 1
127.0.0.1:6379> zadd zsetkey 0 rabbitmq
(integer) 0
127.0.0.1:6379> zrangebyscore zsetkey 0 1000
1) "redis"
2) "mongodb"
3) "rabbitmq"

上面实例中,添加了两次 rabbitmq 值到 zsekey 中,然而集合中只有一个 rabbitmq 值。

Streams(流)

流(stream)是 redist 5.0 版本新增加的数据结构,也是该版本最重要的更新,专门用于实现消息队列,事件系统。

Redis 之前的其他的数据结构实现消息队列,各有缺点:

(1)列表(list)可以快速地将新消息追加到列表的尾部,但是不适合范围查找;

(2)集合(set)有序集合(zset)虽然可以快速进行查找,但是缺少列表(list)和发布订阅等数据结构提供的阻塞弹出原语;

(3)发布订阅虽然可以将消息主动传递给多个客户端,也拥有阻塞弹出的原语,但是其发送即忘(send and forget)的策略,会导致离线的客户端丢失消息,这非常严重

其他数据结构共同的缺点,即是所有的元素都只能是单个值,如果你想传递多项信息,必须使用序列化工具比如 json,先序列化压入,取出后再序列化才能使用。

流(stream)解决了上面提到的所有问题,每个元素可以包含任意多项信息,且每个元素都包含一个ID,这些元素会根据ID大小在流中有序排列。

实例:将多个温度读数添加到流中,如下:

127.0.0.1:6379> XADD temperatures:us-ny:10007 * temp_f 87.2 pressure 29.69 humidity 46
"1675660136488-0"
127.0.0.1:6379> XADD temperatures:us-ny:10007 * temp_f 83.1 pressure 29.21 humidity 46.5
"1675660145283-0"
127.0.0.1:6379> XADD temperatures:us-ny:10007 * temp_f 81.9 pressure 28.37 humidity 43.7
"1675660154395-0"
127.0.0.1:6379> XRANGE temperatures:us-ny:10007 1658354934941-0 + COUNT 2
1) 1) "1675660136488-0"
   2) 1) "temp_f"
      2) "87.2"
      3) "pressure"
      4) "29.69"
      5) "humidity"
      6) "46"
2) 1) "1675660145283-0"
   2) 1) "temp_f"
      2) "83.1"
      3) "pressure"
      4) "29.21"
      5) "humidity"
      6) "46.5"

Geospatial(地理空间)

在 Redis 的 3.2 版本中加入了地理空间(geospatial)以及索引半径查询的功能,这在需要地理位置的应用上或许可以一展身手。

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

这个命令 (指 GEOADD) 的参数使用标准的 x,y 形式,所以经度(longitude)必须放在纬度(latitude)之前,对于可被索引的坐标位置是有一定限制条件的。

实例:

127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqin
(integer) 1
127.0.0.1:6379> geopos china:city beijing
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"

上面实例中,使用 geoadd 命令添加地点的经纬度,如:beijing。使用 geopos 命令用来获取指定地点的经纬度地址。

HyperLogLog

HyperLogLog 是一种数据结构,用于估计一个集合的基数。作为一个概率数据结构,HyperLog 以完美的准确性换取有效的空间利用。

Redis HyperLog 的实现最多使用 12KB,提供 0.81% 的标准误差。

实例:将一些项目添加到HyperLogLog。例如:

127.0.0.1:6379> pfadd members 123
(integer) 1
127.0.0.1:6379> pfadd members 500
(integer) 1
127.0.0.1:6379> pfadd members 50012
(integer) 1

估计集合中的成员数:

127.0.0.1:6379> pfcount members
(integer) 3

bitmap(位图)

Redis 的位图(bitmap)是由多个二进制位组成的数组,数组中的每个二进制位都有与之对应的偏移量(从 0 开始),通过这些偏移量可以对位图中指定的一个或多个二进制位进行操作。

实际上,位图并不是 Redis 提供的一种新的数据类型,它是字符串类型的扩展。所以位图的命令可以直接使用在字符串类型的键上,位图命令操作的键也可以被字符串类型命令操作。一些位图用例的例子包括:

• 高效的集合表示法,适用于集合的成员对应于整数 0-N 的情况。

• 对象权限,其中每个比特代表一个特定的权限,类似于文件系统存储权限的方式。

实例:假设您在现场部署了 1000 个传感器,标记为 0-999。您需要快速确定给定的传感器是否在一小时内对服务器发出了 ping。您可以使用其键引用当前小时的位图来表示此场景。

(1)传感器 123 在 2024-01-01 00:00 小时内 ping 服务器。

127.0.0.1:6379> SETBIT pings:2024-01-01-00:00 123 1
(integer) 0

(2)传感器 123 是否在 2024-01-01 00:00 小时内 ping 服务器?

127.0.0.1:6379> GETBIT pings:2024-01-01-00:00 123
(integer) 1

(3)服务器 456 怎么样?

127.0.0.1:6379> GETBIT pings:2024-01-01-00:00 456
(integer) 0

bitfields(位字段)

Redis 位字段(bitfields)允许您设置、递增和获取任意位长度的整数值。例如:可以对从无符号 1 位整数到有符号 63 位整数的任何对象进行操作。

这些值使用二进制编码的 Redis 字符串存储。位字段支持原子读取、写入和增量操作,使其成为管理计数器和类似数值的好选择。

实例:假设您正在跟踪在线游戏中的活动。你需要为每个玩家保持两个关键指标:黄金总量和被杀死的怪物数量。因为你的游戏很容易上瘾,所以这些计数器应该至少有32位宽。

您可以为每个玩家用一个位特字段来表示这些计数器。

(1)新玩家以 1000 金币开始(计数器偏移量为0)。

> BITFIELD player:1:stats SET u32 #0 1000
1) (integer) 0

(2)杀死囚禁王子的妖精后,加上所赚的 50 金币,并增加“被杀”计数器(偏移1)。

> BITFIELD player:1:stats INCRBY u32 #0 50 INCRBY u32 #1 1
1) (integer) 1050
2) (integer) 1

(3)支付铁匠 999 金购买一把传说中的生锈匕首。

> BITFIELD player:1:stats INCRBY u32 #0 -999
1) (integer) 51

(4)查看玩家的统计数据:

> BITFIELD player:1:stats GET u32 #0 GET u32 #1
1) (integer) 51
2) (integer) 1
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号