专栏首页互扯程序Redis 五种数据类型及应用场景

Redis 五种数据类型及应用场景

Redis 特点

1. 所有数据存储在内存中,高速读写

2. 提供丰富多样的数据类型:string、 hash、 list、set、 sorted set

3. 提供了 AOF 和 RDB 两种数据的持久化保存方式,保证了 Redis 重启后数据不丢失

4. Redis 的所有操作都是原子性的,还支持对几个操作合并后的原子性操作,支持事务

通常我们都把数据存到关系型数据库中,但为了提升应用的性能,我们应该把访频率高且不会经常变动的数据缓存到内存中。

Redis 没有像 MySQL 这类关系型数据库那样强大的查询功能,需要考虑如何把关系型数据库中的数据,合理的对应到缓存的 key-value 数据结构中。

Redis 数据类型

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

String(字符串)

简介

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

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

3. string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。

应用场景

1. 存储 MySQL 中某个字段的值

把 key 设计为 表名:主键名:主键值:字段名

set user:id:1:name 互扯程序

2. 存储对象

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

set user:id:1 '[{"id":1,"name":"互扯","email":"huche@qq.com"},{"id":1,"name":"程序","email":"chengxu@qq.com"}]'

3. 生成自增 id

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

Hash(哈希)

简介

1. Redis hash 是一个键值(key=>value)对集合。

2. Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

应用场景

存储对象:刚才我们讲到,String类型也可以存储对象,但我们为什么不推荐呢?

比如一个用户对象,属性包括姓名、年龄、性别、学号、学分等,因为客户端会先把这个对象序列化后存储为一个字符串的值,这时候在需要修改其中某一项时,通常需要将所有值取出反序列化后,修改某一项的值,再序列化存储回去。

这样不仅增大了开销,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改学分)。而Redis的Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。

Redis的Hash实际是内部存储的Value为一个HashMap(如果对HashMap不是很了解,可以移步到这里“Java集合深度解析之HashMap”),并提供了直接存取这个Map成员的接口。

实现方式

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

注意

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

List(列表)

简介

1.list 是按照插入顺序排序的string字符串链表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),它是一个有序集合。

2. 双向链表实现,两端添加元素的时间复杂度为 O(1)

3. 插入元素时,如果 key 不存在,redis 会为该 key 创建一个新的链表,如果链表中所有的元素都被移除,该 key 也会从 redis 中移除。

4. 列表最多可存储 2的32方 - 1 元素 (4294967295, 每个列表可存储40多亿)。

应用场景

1. 消息队列:redis 的 list 数据类型对于大部分使用者来说,是实现队列服务的最经济,最简单的方式。

2. 任务池:可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出进行执行,其实也有点类似消息队列。

3. “最新内容”:因为 list 结构的数据查询两端附近的数据性能非常好,所以适合一些需要获取最新数据的场景,比如新闻类应用的 “最近新闻”。

注意

list 是链表结构,所有如果在头部和尾部插入数据,性能会非常高,不受链表长度的影响;但如果在链表中插入数据,性能就会越来越差。这点可以看看java里的ArrayList和LinkedList的区别就明白了。

Set(集合)

简介

1. Set是一个无序string类型集合。

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

3. set 集合不允许数据重复,如果添加的数据在 set 中已经存在,将只保留一份

4. set 类型提供了多个 set 之间的聚合运算,如求交集、并集、补集,这些操作在 redis 内部完成,效率很高。

5. 集合最多可存储 2的32方 - 1 元素 (4294967295, 每个列表可存储40多亿)。

应用场景

set 类型的特点是“不重复且无序的一组数据”,并且具有丰富的计算功能,在一些特定的场景中可以高效的解决一般关系型数据库不方便做的工作。

“共同好友列表”:社交类应用中,获取两个人或多个人的共同好友,两个人或多个人共同关注的微博这样类似的功能,用 MySQL 的话操作很复杂,可以把每个人的好友 id 存到集合中,获取共同好友的操作就可以简单到一个取交集的命令就搞定。

zset(sorted set:有序集合)

简介

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

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

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

应用场景

在集合类型的场景上加入排序就是有序集合的应用场景了。

1. 根据好友的“亲密度”排序显示好友列表。

2. 直播间里,粉丝打赏金额排序。

Redis Key设计

使用冒号把 key 中要表达的多种含义分开表示,步骤如下:

1. 把表名转化为 key 前缀

2. 主键名(或其他常用于搜索的字段)

3. 主键值

4. 要存储的字段。

id

num

name

1

111111

互扯

2

222222

程序

这个简单的表可能经常会有这个的需求:根据学生学号查询学生名字,可以选择把名字这个数据存到 redis 中:

set user:num:111111:name 互扯 set user:num:222222:name 程序

本文分享自微信公众号 - 互扯程序(chat_routine),作者:互扯程序

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-03-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 推荐一款很不错的设计工具

    之前写了一篇文章设计图都不会画,还想做”架构师“?给大家推荐了很多不错的设计工具,有mac的,像OmniGraffle。也有windows的,像visio,但这...

    互扯程序
  • Spring 的 BeanUtils 的 copyProperties 方法需要注意的点

    最近项目中在和第三方进行联调一个接口,我们这边发送http请求给对方,然后接收对方的回应,代码都是老代码。

    互扯程序
  • Linux常用Shell脚本,值得学习及收藏

    在运维中,尤其是linux运维,都知道脚本的重要性,脚本会让我们的 运维事半功倍,所以学会写脚本是我们每个linux运维必须学会的一门功课,这里收藏linux运...

    互扯程序
  • 从零开始学C++之标准库类型(一):string 类简介和例程

    一、标准库string类型 string类型支持长度可变的字符串,C++标准库将负责管理与存储字符相关的内存,以及提供各种有用的操作 ,在VC中直接F1查看 ...

    s1mba
  • DevOps之软件配置协作化管理

    ? 大家好,我是许二虎,现在负责新一代数字化企业云平台 “The Platform” 的各业务领域系统的设计和开发。很荣幸有这次机会和大家分享交流“DevOp...

    yuanyi928
  • Avro序列化&反序列化和Spark读取Avro数据

    本篇文章主要讲如何使用java生成Avro格式数据以及如何通过spark将Avro数据文件转换成DataSet和DataFrame进行操作。

    Fayson
  • 由__future__中unicode_literals引起的错误来研究python中的编码问题

    在py2.7的项目中用了future模块中的 unicode_literals 来为兼容py3.x做准备,今天遇到一个UnicodeEncodeError的错误...

    the5fire
  • python生成随机密码串

       今天修改服务器密码,想来想去不知道设置什么密码比较好,索性设置随机数吧。python当中的random模块可以生成随机数,主要用这个生成随机密码。

    py3study
  • 学生管理系统-C++

    汐楓
  • 在 .NET Core 中运行 JavaScript

    在 .NET Framework 时,我们可以通过V8.NET等组件来运行 JavaScript,不过目前我看了好几个开源组件包括V8.NET都还不支持 .NE...

    晓晨

扫码关注云+社区

领取腾讯云代金券