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

64e226e7ac6e4f738a0be66882967caa.gif1、数据类型

 

String(字符串,整数,浮点数):做简单的键值对缓存

List(列表):储存一些列表类型的数据结构

Hash(哈希):包含键值对的无序散列表,结构化的数据

Set(无序集合):交集,并集,差集的操作

Zset(有序集合)(Sorted sets):去重同时也可以排序

 

 

先通过一张图了解下Redis内部内存管理中是如何描述这些不同数据类型的:

 

 

 

 

 

 

 

 

 

首先Redis内部使用一个redisObject对象来表示所有的key和value,redisObject最主要的信息如上图所示:type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式,比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:"123" "456"这样的字符串。

 

  这里需要特殊说明一下vm字段,只有打开了Redis的虚拟内存功能,此字段才会真正的分配内存,该功能默认是关闭状态的。通过上图我们可以发现Redis使用redisObject来表示所有的key/value数据是比较浪费内存的,当然这些内存管理成本的付出主要也是为了给Redis不同数据类型提供一个统一的管理接口,实际作者也提供了多种方法帮助我们尽量节省内存使用,我们随后会具体讨论。

 

一、string

string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。value其实不仅是String,也可以是数字。string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。

 

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

 

应用场景:String是最常用的一种数据类型,普通的key/ value 存储都可以归为此类,即可以完全实现目前 Memcached 的功能,并且效率更高。还可以享受Redis的定时持久化,操作日志及 Replication等功能。除了提供与 Memcached 一样的get、set、incr、decr 等操作外,Redis还提供了下面一些操作:

 

获取字符串长度

往字符串append内容

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

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

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

使用场景:常规key-value缓存应用。常规计数: 微博数, 粉丝数。 实现方式:String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。

 

redis 127.0.0.1:6379> SET name "runoob"

"OK" redis 127.0.0.1:6379> GET name

"runoob"

在以上实例中我们使用了 Redis 的 SET 和 GET 命令。键为 name,对应的值为 runoob。

 

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

 

二、Hash

Hash 是一个键值(key => value)对集合。Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。 常用命令:hget,hset,hgetall 等。 应用场景:我们简单举个实例来描述下Hash的应用场景,比如我们要存储一个用户信息对象数据,包含以下信息:

 

用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储,主要有以下2种存储方式:

 

 

 

image

 

 

第一种方式将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。

 

 

 

image

 

 

第二种方法是这个用户信息对象有多少成员就存成多少个key-value对儿,用用户ID+对应属性的名称作为唯一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的。

 

那么Redis提供的Hash很好的解决了这个问题,Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口,如下图:

 

 

 

image

 

 

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

 

这里同时需要注意,Redis提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部Map的成员很多,那么涉及到遍历整个内部Map的操作,由于Redis单线程模型的缘故,这个遍历操作可能会比较耗时,而另其它客户端的请求完全不响应,这点需要格外注意。 使用场景:存储部分变更数据,如用户信息等。 实现方式:上面已经说到Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。

 

redis> HSET myhash field1 "Hello" field2 "World"

"OK" redis> HGET myhash field1

"Hello" redis> HGET myhash field2

"World"

实例中我们使用了 Redis HMSET, HGET 命令,HMSET 设置了两个 field=>value 对, HGET 获取对应 field 对应的 value。每个 hash 可以存储 232 -1 键值对(40多亿)。

 

 

三、list

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

 

常用命令:lpush(添加左边元素),rpush,lpop(移除左边第一个元素),rpop,lrange(获取列表片段,LRANGE key start stop)等。

 

应用场景:Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。

 

List 就是链表,相信略有数据结构知识的人都应该能理解其结构。使用List结构,我们可以轻松地实现最新消息排行等功能。List的另一个应用就是消息队列, 可以利用List的PUSH操作,将任务存在List中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作List中某一段的api,你可以直接查询,删除List中某一段的元素。

 

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

 

Redis的list是每个子元素都是String类型的双向链表,可以通过push和pop操作从列表的头部或者尾部添加或者删除元素,这样List即可以作为栈,也可以作为队列。 获取越接近两端的元素速度越快,但通过索引访问时会比较慢。

 

使用场景: 消息队列系统:使用list可以构建队列系统,使用sorted set甚至可以构建有优先级的队列系统。比如:将Redis用作日志收集器,实际上还是一个队列,多个端点将日志信息写入Redis,然后一个worker统一将所有日志写到磁盘。

 

取最新N个数据的操作:记录前N个最新登陆的用户Id列表,超出的范围可以从数据库中获得。

 

复制代码

//把当前登录人添加到链表里

ret = r.lpush("login:last_login_times", uid) //保持链表只有N位

ret = redis.ltrim("login:last_login_times", 0, N-1) //获得前N个最新登陆的用户Id列表

last_login_list = r.lrange("login:last_login_times", 0, N-1)

复制代码

比如微博: 在Redis中我们的最新微博ID使用了常驻缓存,这是一直更新的。但是我们做了限制不能超过5000个ID,因此我们的获取ID函数会一直询问Redis。只有在start/count参数超出了这个范围的时候,才需要去访问数据库。我们的系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。SQL数据库(或是硬盘上的其他类型数据库)只是在用户需要获取“很远”的数据时才会被触发,而主页或第一个评论页是不会麻烦到硬盘上的数据库了。

复制代码

redis 127.0.0.1:6379> lpush runoob redis

(integer) 1 redis 127.0.0.1:6379> lpush runoob mongodb

(integer) 2 redis 127.0.0.1:6379> lpush runoob rabitmq

(integer) 3 redis 127.0.0.1:6379> lrange runoob 0 10

1) "rabitmq"

2) "mongodb"

3) "redis" redis 127.0.0.1:6379>

复制代码

列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。

 

四、 set

set 是string类型的无序集合。集合是通过hashtable实现的,概念和数学中个的集合基本类似,可以交集,并集,差集等等,set中的元素是没有顺序的。所以添加,删除,查找的复杂度都是O(1)。

 

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

 

常用命令:sadd,spop,smembers,sunion 等。

 

应用场景:Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。

 

Set 就是一个集合,集合的概念就是一堆不重复值的组合。利用Redis提供的Set数据结构,可以存储一些集合性的数据。

 

案例:在微博中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。

 

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

 

使用场景: ①交集,并集,差集:(Set)

 

复制代码

//book表存储book名称

set book:1:name ”The Ruby Programming Language”

set book:2:name ”Ruby on rail”

set book:3:name ”Programming Erlang” //tag表使用集合来存储数据,因为集合擅长求交集、并集

sadd tag:ruby 1 sadd tag:ruby 2 sadd tag:web 2 sadd tag:erlang 3

//即属于ruby又属于web的书?

inter_list = redis.sinter("tag.web", "tag:ruby") //即属于ruby,但不属于web的书?

inter_list = redis.sdiff("tag.ruby", "tag:web") //属于ruby和属于web的书的合集?

inter_list = redis.sunion("tag.ruby", "tag:web")

复制代码

②获取某段时间所有数据去重值 这个使用Redis的set数据结构最合适了,只需要不断地将数据往set中扔就行了,set意为集合,所以会自动排重。

 

sadd key member

复制代码

redis 127.0.0.1:6379> sadd runoob redis

(integer) 1 redis 127.0.0.1:6379> sadd runoob mongodb

(integer) 1 redis 127.0.0.1:6379> sadd runoob rabitmq

(integer) 1 redis 127.0.0.1:6379> sadd runoob rabitmq

(integer) 0 redis 127.0.0.1:6379> smembers runoob

1) "redis"

2) "rabitmq"

3) "mongodb"

复制代码

**注意**: 以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个成员)。

 

五 、zset

zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。 *zadd 命令:*添加元素到集合,元素在集合中存在则更新对应score。 常用命令:zadd,zrange,zrem,zcard等

 

使用场景:Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。和Set相比,Sorted Set关联了一个double类型权重参数score,使得集合中的元素能够按score进行有序排列,redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。比如一个存储全班同学成绩的Sorted Set,其集合value可以是同学的学号,而score就可以是其考试得分,这样在数据插入集合的时候,就已经进行了天然的排序。另外还可以用Sorted Set来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/359474.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java多线程--同步机制解决线程安全问题方式二:同步方法

文章目录 一、同步方法(1)同步方法--案例11、案例12、案例1之同步监视器 (2)同步方法--案例21、案例2之同步监视器的问题2、案例2的补充说明 二、代码及重要说明(1)代码(2)重要说明 …

云计算HCIE备考经验分享

大家好,我是来自深圳信息职业技术学院22级鲲鹏3-1班的刘同学,在2023年9月19日成功通过了华为云计算HCIE认证,并且取得了A的成绩。下面把我的考证经验分享给大家。 转专业进鲲鹏班考HCIE 大一上学期的时候,在上Linux课程的时候&…

代码随想录 Leetcode222.完全二叉树的节点个数

题目&#xff1a; 代码&#xff08;首刷自解 2024年1月30日&#xff09;&#xff1a; class Solution { public:int countNodes(TreeNode* root) {int res 0;if (root nullptr) return res;queue<TreeNode*> deque;TreeNode* cur root;deque.push(cur);int size 0;w…

注册亚马逊店铺用动态IP可以吗?

注册亚马逊店铺可以用动态IP&#xff0c;只要是独立且干净的网线就没问题&#xff0c;亚马逊规则要求一个IP地址只能出现一个亚马逊店铺&#xff0c;若使用不当会导致关联账户。 固定ip可以给我们的账户带来更多的安全&#xff0c;要知道关联问题是亚马逊上的一个大问题&#…

DBCO-PEG8-Amine,二苯并环辛炔 PEG8 氨基,具有良好反应活性

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;二苯并环辛炔-八聚乙二醇-氨基&#xff0c;二苯并环辛炔 PEG8 氨基&#xff0c;DBCO-PEG8-NH2&#xff0c;DBCO-PEG8-Amine 一、基本信息 产品简介&#xff1a;DBCO-PEG8-NH2 is a compound with good reactivity. …

ubuntu20.04安装sumo

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 有问题&#xff0c;请大家指出&#xff0c;争取使方法更完善。这只是ubuntu安装sumo的一种方法。一、注意事项1、首先明确你的ubuntu的用户名是什么 二、sumo安装1.…

Python爬虫实践指南:利用cpr库爬取技巧

引言 在信息时代&#xff0c;数据是无价之宝。为了获取网络上的丰富数据&#xff0c;网络爬虫成为了不可或缺的工具。在Python这个强大的编程语言中&#xff0c;cpr库崭露头角&#xff0c;为网络爬虫提供了便捷而高效的解决方案。本文将深入探讨如何利用cpr库实现数据爬取的各…

Ruff应用:打破传统,IoT技术赋能工业制造数字化转型之路

近年来&#xff0c;随着物联网、大数据、云计算、5G等数字技术的快速应用&#xff0c;工业制造领域正在经历着前所未有的变革。工业4.0时代&#xff0c;各种数字技术与工业制造的结合&#xff0c;不仅提高了工业生产效率、降低运营成本&#xff0c;更是极大地推动了传统工业数字…

智能小程序事件系统——SJS响应事件实现方案

背景信息 如有频繁用户交互&#xff0c;在小程序上表现是比较卡顿的。例如&#xff0c;页面有 2 个元素 A 和 B&#xff0c;用户在 A 上做 touchmove 手势&#xff0c;要求 B 也跟随移动&#xff0c;movable-view 就是一个典型的例子。一次 touchmove 事件的响应过程为&#x…

GPT-4 Vision调试任何应用,即使缺少文本日志 升级Streamlit七

GPT-4 Vision 系列: 翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式二翻译: GPT-4 Vision静态图表转换为动态数据可视化 升级Streamlit 三翻译: GPT-4 Vision从图像转换为完全可编辑的表格 升级St…

springboot 个人网盘系统 java web网盘文件分享系统 web在线云盘

springboot 个人网盘系统 java web网盘文件分享系统 web在线云盘 开发工具&#xff1a;Eclipse/idea Java开发环境&#xff1a;JDK8.0 Web服务器:Tomcate9.0。 数据库&#xff1a;MySQL数据库。 技术框架&#xff1a;Struts2SpringHibernate和JSP 有详细的源码&#xff0…

人脸识别技术在网络安全中有哪些应用前景?

人脸识别技术在网络安全中有广泛的应用前景。以下是一些主要的应用方向&#xff1a; 1. 身份验证和访问控制&#xff1a;人脸识别可以用作一种更安全和方便的身份验证方法。通过将用户的人脸与事先注册的人脸进行比对&#xff0c;可以实现强大的身份验证&#xff0c;避免了传统…

自动驾驶:Apollo如何塑造人类的未来出行

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言1. 什么是自定义指令&#xff1f;2. Apollo中的自定义指令2.1 查询中的自定…

开源博客项目Blog .NET Core源码学习(8:EasyCaching使用浅析)

开源博客项目Blog使用EasyCaching模块实现缓存功能&#xff0c;主要是在App.Framwork项目中引用了多类包&#xff0c;包括内存缓存&#xff08;EasyCaching.InMemory&#xff09;、Redis缓存&#xff08;EasyCaching.CSRedis&#xff09;&#xff0c;同时支持多种序列化方式&am…

微软Office Plus与WPS Office的较量:办公软件市场将迎来巨变?

微软Office Plus在功能表现上远超WPS Office&#xff1f; 微软出品的Office套件实力强劲&#xff0c;其不仅在办公场景中扮演着不可或缺的角色&#xff0c;为用户带来高效便捷的体验&#xff0c;而且在娱乐生活管理等多元领域中同样展现出了卓越的应用价值 作为中国本土办公软…

GPT-4 Vision根据应用程序截图生成博客和Readme 升级Streamlit八

GPT-4 Vision 系列: 翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式二翻译: GPT-4 Vision静态图表转换为动态数据可视化 升级Streamlit 三翻译: GPT-4 Vision从图像转换为完全可编辑的表格 升级St…

回归预测 | Matlab实现CPO-BiLSTM【24年新算法】冠豪猪优化双向长短期记忆神经网络多变量回归预测

回归预测 | Matlab实现CPO-BiLSTM【24年新算法】冠豪猪优化双向长短期记忆神经网络多变量回归预测 目录 回归预测 | Matlab实现CPO-BiLSTM【24年新算法】冠豪猪优化双向长短期记忆神经网络多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现CPO-B…

python中的josn方法相关介绍

如果需要在不同的编程语言之间传递对象&#xff0c;就必须把对象序列化为标准格式&#xff0c;比如XML&#xff0c;但更好的方法是序列化为JSON&#xff0c;因为JSON表示出来就是一个字符串&#xff0c;可以被所有语言读取&#xff0c;也可以方便地存储到磁盘或者通过网络传输。…

maven helper 解决jar包冲突方法

一 概要说明 1.1 说明 首先&#xff0c;解决idea中jar包冲突&#xff0c;使用maven的插件&#xff1a;maven helper插件&#xff0c;它能够给我们罗列出来同一个jar包的不同版本&#xff0c;以及他们的来源&#xff0c;但是对不同jar包中同名的类没有办法。 1.2 依赖顺序 …

[嵌入式系统-6]:龙芯1B 开发学习套件 -3-软件层次架构

目录 一、龙芯软件架构 1.1 通用软件架构 1.2 龙芯软件架构 1.3 龙芯各种应用程序 1.4 龙芯SOC芯片硬件&#xff1a;龙芯1B 1.5 PMON软件 1.6 龙芯IDE管辖的软件 &#xff08;1&#xff09;CPU Core驱动程序 &#xff08;2&#xff09;SOC芯片外设驱动程序 &#xff…