Redis数据类型及使用场景有哪些

60次阅读
没有评论

共计 4166 个字符,预计需要花费 11 分钟才能阅读完成。

这篇文章主要介绍“Redis 数据类型及使用场景有哪些”,在日常操作中,相信很多人在 Redis 数据类型及使用场景有哪些问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Redis 数据类型及使用场景有哪些”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!

Redis 数据类型及使用场景

Redis 数据类型及使用场景
Redis 相比其它的 KV 数据库,其一大特点是支持丰富的数据类型。它一共支持 5 种数据类型,下面逐一介绍这 5 种数据类型及其使用场景和内部实现方式。

string
简介:string 类型是 Redis 中最基本的数据类型,最常用的数据类型,甚至被很多玩家当成 redis 唯一的数据类型去使用。string 类型在 redis 中是二进制安全 (binary safe) 的, 这意味着 string 值关心二进制的字符串,不关心具体格式,你可以用它存储 json 格式或 JPEG 图片格式的字符串。

获取字符串长度

往字符串 append 内容

设置和获取字符串的某一段内容

设置及获取字符串的某一位(bit)

批量设置一系列字符串的内容

常用命令: set,get,decr,incr,mget 等。

应用场景:

(1) 存储 MySQL 中某个字段的值
把 key 设计为 表名:主键名:主键值:字段名

(2) 存储对象
string 类型支持任何格式的字符串,应用最多的就是存储 json 或其他对象格式化的字符串。(这种场景下推荐使用 hash 数据类型)

set user:id:1  [{id :1, name : zj , email : 156577812@qq.com},{id :1, name : zj , email : 156577812@qq.com}]

(3) 生成自增 id
当 redis 的 string 类型的值为整数形式时,redis 可以把它当做是整数一样进行自增(incr)自减(decr)操作。由于 redis 所有的操作都是原子性的,所以不必担心多客户端连接时可能出现的事务问题。

Hash
简介:Hash 存的是字符串和字符串值之间的映射。Hash 将对象的各个属性存入 Map 里,可以只读取 / 更新对象的某些属性。这样有些属性超长就让它一边呆着不动,另外不同的模块可以只更新自己关心的属性而不会互相并发导致覆盖冲突。

常用命令:hget,hset,hgetall 等。

应用场景:

存放结构化数据,比如用户信息。在 Memcached 或 CKV 中,对于用户信息比如用户的昵称、年龄、性别、积分等,我们需要先序列化后存储为一个字符串的值,这时候在需要修改其中某一项时,通常需要将所有值取出反序列化后,修改某一项的值,再序列化存储回去。这样不仅增大了开销,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改积分)。而 Redis 的 Hash 结构可以使你像在数据库中 Update 一个属性一样只修改某一项属性值。如下图:

Key 是用户 ID, value 是一个 Map,这个 Map 的 key 是成员的属性名,value 是属性值,这样对数据的修改和存取都可以直接通过其内部 Map 的 Key(Redis 里称内部 Map 的 key 为 field), 也就是通过 key(用户 ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。

不过这里需要注意,Redis 提供了接口 (hgetall) 可以直接取到全部的属性数据, 但是如果内部 Map 的成员很多,那么涉及到遍历整个内部 Map 的操作,由于 Redis 单线程模型的缘故,这个遍历操作可能会比较耗时,而对其它客户端的请求完全不响应,这点需要格外注意。

可用来建索引。比如 User 对象,除了 id 有时还要按 name 来查询,可以建一个 Key 为 user:name:id 的 Hash,在插入 User 对象时(set user:101{“id”:101,“name”:“calvin”}),顺便往这个 hash 插入一条(hset user:name:id calvin 101),这时 calvin 作为 hash 里的一个 key,值为 101。按 name 查询的时候,用 hgetuser:name:id calvin 就能从名为 calvin 的 key 里取出 id。假如需要使用多种索引来查找某条数据时可以使用,一个 hash key 搞定,避免使用多个 string key 存放索引值。

HINCRBY 同样可用于实现 idmaker。相对 string 类型的 idmaker 每一个类型需要一个 key,hash 类型的用一个 key 即可。

hash 数据类型在存储上述类型的数据时具有比 string 类型更灵活、更快的优势,具体的说,使用 string 类型存储,必然需要转换和解析 json 格式的字符串,即便不需要转换,在内存开销方面,还是 hash 占优势。

实现方式:

Redis Hash 对应 Value 内部实际就是一个 HashMap,这里会有 2 种不同实现,这个 Hash 的成员比较少时 Redis 为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的 HashMap 结构,对应的 value redisObject 的 encoding 为 zipmap, 当成员数量增大时会自动转成真正的 HashMap, 此时 encoding 为 ht。

List

简介:
list 是按照插入顺序排序的字符串链表,可以在头部和尾部插入新的元素(双向链表实现,两端添加元素的时间复杂度为 O(1))。插入元素时,如果 key 不存在,redis 会为该 key 创建一个新的链表,如果链表中所有的元素都被移除,该 key 也会从 redis 中移除。

常用命令:lpush,rpush,lpop,rpop,lrange 等。

应用场景:

各种列表,比如 twitter 的关注列表、粉丝列表等,最新消息排行、每篇文章的评论等也可以用 Redis 的 list 结构来实现。

消息队列,可以利用 Lists 的 PUSH 操作,将任务存在 Lists 中,然后工作线程再用 POP 操作将任务取出执行。这里的消息队列并没有 ack 机制,如果消费者把任务给 Pop 走了又没处理完就死机了怎么办?解决方法之一是加多一个 sorted set,分发的时候同时发到 list 与 sorted set,以分发时间为 score,用户把任务做完了之后要用 ZREM 消掉 sorted set 里的 job,并且定时从 sorted set 中取出超时没有完成的任务,重新放回 list。另一个做法是为每个 worker 多加一个的 list,弹出任务时改用 RPopLPush,将 job 同时放到 worker 自己的 list 中,完成时用 LREM 消掉。如果集群管理 (如 zookeeper) 发现 worker 已经挂掉,就将 worker 的 list 内容重新放回主 list。

利用 LRANGE 可以很方便的实现 list 内容分页的功能。

取最新 N 个数据的操作:LPUSH 用来插入一个内容 ID,作为关键字存储在列表头部。LTRIM 用来限制列表中的项目数最多为 5000。如果用户需要的检索的数据量超越这个缓存容量,这时才需要把请求发送到数据库。

实现方式:

Redis list 的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis 内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

Set

简介:是一种无序的集合,集合中的元素没有先后顺序,不重复。将重复的元素放入 Set 会自动去重。

常用命令:

sadd,spop,smembers,sunion 等。

应用场景:

某些需要去重的列表,并且 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是 list 所不能提供的。

可以存储一些集合性的数据,比如在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis 还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。又比如 QQ 有一个社交功能叫做“好友标签”,大家可以给你的好友贴标签,比如“大美女”、“土豪”、“欧巴”等等,这里也可以把每一个用户的标签都存储在一个集合之中。

想要知道某些特定的注册用户或 IP 地址,他们到底有多少访问了某个页面,可以这样实现:SADD page:day1: page_id user_id。想知道特定用户的数量,使用 SCARD page:day1: page_id。需要测试某个特定用户是否访问了这个页面?SISMEMBER page:day1: page_id。

实现方式:

set 的内部实现是一个 value 永远为 null 的 HashMap,实际就是通过计算 hash 的方式来快速排重的,这也是 set 能提供判断一个成员是否在集合内的原因。

Sorted Set

简介:有序集合,相比 set,元素放入集合时还要提供该元素的分数,可根据分数自动排序。

常用命令:

zadd,zrange,zrem,zcard 等

使用场景:

存放一个有序的并且不重复的集合列表,比如 twitter 的 public timeline 可以以发表时间作为 score 来存储,这样获取时就是自动按时间排好序的。

可以做带权重的队列,比如普通消息的 score 为 1,重要消息的 score 为 2,然后工作线程可以选择按 score 的倒序来获取工作任务。让重要的任务优先执行。

过期项目处理:使用 unix 时间作为关键字,用来保持列表能够按时间排序。对 current_time 和 time_to_live 进行检索,完成查找过期项目的艰巨任务。另一项后台任务使用 ZRANGE…WITHSCORES 进行查询,删除过期的条目。

实现方式:

Redis sorted set 的内部使用 HashMap 和跳跃表 (SkipList) 来保证数据的存储和有序,HashMap 里放的是成员到 score 的映射,而跳跃表里存放的是所有的成员,排序依据是 HashMap 里存的 score, 使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

到此,关于“Redis 数据类型及使用场景有哪些”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注丸趣 TV 网站,丸趣 TV 小编会继续努力为大家带来更多实用的文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-15发表,共计4166字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)