redis中记录用户id用map好还是用hash好?
Redis公共数据类型
redis最常用的数据类型主要包括以下五种:
线
混杂
目录
设置
排序集合
在详细描述这些数据类型之前,我们先通过一张图了解一下如何描述redis内存管理中这些不同的数据类型:
首先,redis使用一个redisobject对象来表示所有的键和值。Redisobject的主要信息如上图所示:type代表一。
什么数据类型是值对象?编码是不同数据类型在redis中的存储方式。例如,type=string表示值存储。
一个普通的字符串,那么对应的编码可以是raw或者int。如果是int,说明实际redis按照数值类型存储和表示这个字符串。当然,
前提是字符串本身可以用数值表示,比如“123”。
像“456”这样的字符串。
这里需要解释一下vm字段。只有打开redis的虚拟内存功能,这个字段才会真正分配内存。这个功能默认是关闭的,后面会详细介绍这个功能。及格
在上图中,我们可以发现redis使用redisobject来表示所有的键/值数据是对内存的浪费。当然,这些内存管理成本主要是给予
Redis为不同的数据类型提供了统一的管理接口,实际作者也提供了各种方法来帮助我们尽可能的节省内存,后面会详细讨论。
让我们逐一分析这五种数据类型的用途和内部实现:
线
常见命令:
设置、获取、减少、增加、管理等。
应用场景:
字符串是最常用的数据类型,普通的键/值存储都可以归入这一类,这里就不解释了。
实施模式:
存储在redis中的字符串默认是一个字符串,被redisobject引用。当遇到incr、decr等运算时,会转换成数值型进行计算。此时,redisobject的编码字段是int。
混杂
常见命令:
Hget、hset、hgetall等。
应用场景:
我们举一个简单的例子来描述hash的应用场景。例如,我们想存储一个用户信息对象数据,它包含以下信息:
用户id是要搜索的关键字,存储值用户对象包含姓名、年龄、生日等信息。如果它存储在一个公共的键/值结构中,有两种主要的存储方法:
第一种方法将用户id作为搜索关键字,并将其他信息封装到一个对象中,并以序列化的方式存储。这种方法的缺点是增加了序列化/反序列化的成本,当其中一个信息需要修改时,需要检索整个对象,修改操作需要保护并发性,引入cas等复杂问题。
第二种方法是将用户信息对象存储为有多少个成员就有多少个键-值对,并使用用户id+对应属性的名称作为惟一标识符来获取对应属性的值。虽然消除了序列化开销和并发问题,但是用户id是重复存储的,如果有大量这样的数据,内存浪费还是非常可观的。
那么redis提供的hash很好的解决了这个问题。redis的hash其实就是内部存储的值是一个hashmap,它提供了一个直接访问这个map成员的接口,如下图所示:
也就是说,密钥仍然是用户id,
Value是一个映射,这个映射的键是成员的属性名,value是属性值,这样就可以通过其内部映射的键直接修改和访问数据(内部映射的键在Redis中称为field)。
也就是通过key(用户id)+field(属性标签)。
可以操纵对应的属性数据,不需要重复存储数据,也不会带来序列化和并发修改控制的问题。它很好地解决了这个问题。
同时需要注意的是,redis提供了一个接口(hgetall),可以直接获取所有的属性数据,但是如果内部映射的成员很多,就涉及到遍历整个内部映射。
操作,由于redis单线程模型,这种遍历操作可能比较耗时,而其他客户端的请求完全没有响应,需要特别注意。
实施模式:
关于redis已经说过了
对应于hash的值实际上是一个hashmap。实际上,这里有两种不同的实现。当hash的成员数较少时,redis会使用类似一维数组的方式进行紧凑存储,而不是使用真正的hashmap结构和对应的值。
redisobject的编码是zipmap,当成员数量增加时会自动变成真正的hashmap,编码是ht。
目录
常见命令:
Lpush、rpush、lpop、rpop、lrange等。
应用场景:
雷迪斯
List有很多应用场景,也是redis最重要的数据结构之一。比如twitter的关注列表和粉丝列表,都可以通过redis的列表结构来实现,很好理解,这里不再赘述。
实施模式:
雷迪斯
list的实现是双向链表,可以支持反向搜索和遍历,更容易操作,但是带来了一些额外的内存开销。redis内部的许多实现,包括发送缓冲队列,也使用这种数据结构。
设置
常见命令:
Sadd,spop,sembers,sunion等。
应用场景:
雷迪斯
set提供的功能和list类似,但特别之处在于set可以自动复制。当你需要存储一个数据的列表,又不想要重复的数据时,set是一个很好的选择,set提供了一个判断成员是否在集合集合中的重要接口,这是list所不能提供的。
实施模式:
set的内部实现是一个。
值始终为null的Hashmap实际上是通过计算hash来快速排序的,这也是为什么set可以提供一种判断成员是否在集合中的方法。
排序集合
常见命令:
扎德、zrange、zrem、zcard等。
使用场景:
redis排序集的使用场景和set类似,只是set不自动排序,排序。
Set可以通过提供一个额外的参数score来对成员进行排序,而且是有序插入,也就是自动排序。当您需要有序且不重复的收藏列表时,您可以选择排序。
设置数据结构,比如twitter的public。