百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

缓存神器Redis的五种数据类型及使用

mhr18 2024-11-05 10:22 18 浏览 0 评论

Redis作为Nosql的代表,想必大家已经再熟悉不过了,除了作为缓存来使用,Redis还提供了其他很多有用的功能,例如可作为消息队列、分布式锁、不隆过滤器、限流等功能使用。今天先来说一说redis作为缓存使用,提供了5 种基础数据结构,分别为:string (字符串)、list (列表)、set (集合)、hash (哈 希) 和 zset (有序集合)。


一、string (字符串)

字符串 string 是 Redis 最简单的数据结构。Redis 所有的数据结构都是以唯一的 key 字符串作为名称,然后通过这个唯一key值来获取相应的 value 数据。不同类型的数据结构的差异就在于value 的结构不一样。字符串结构使用非常广泛,一个常见的用途就是缓存用户信息。我们将用户信息结构体 使用 JSON 序列化成字符串,然后将序列化后的字符串塞进 Redis 来缓存。同样,取用户 信息会经过一次反序列化的过程。Redis 的字符串是动态字符串,是可以修改的字符串,内部结构实现上类似于 Java 的 ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配,字符串最大长度为 512M。使用命令如下:

设置键值对:set [key] [value]

获取对应键的值:get [key]

批量操作键值对:mset [key] [value] [key] [value] [key] [value] ...

批量获取对应键的值:mget [key] [key] [key]...

批量操作可以节省网络耗时开销。

可以对 key 设置过期时间,到点自动删除,这个功能常用来控制缓存的失效时间。在保证缓存是热点数据或者保证缓存和数据库一致性的解决方案时,设置失效时间是必不可少的。还有就是整数的自增或者自减功能,如果 value 值是一个整数,可以对它进行自增操作。自增是有范围的,它的范围是signed long 的最大最小值,超过了这个值,Redis 会报错。

设置过期可以用set+expire的组合,但是保证不了原子性,如果想保证原子性,就用setex命令:


关于自增和自减:

incr/decr:自增/自减 1

incrby/decrby [key] [num]:自增/自减 num


二、list (列表)

Redis 的列表相当于 Java 语言里面的 LinkedList,注意它是链表而不是数组。链表由于有前后节点,特点是插入和删除快,查询慢;数组由于有索引,所以特点是查询快,但是插入和删除慢;这意味着 list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为 O(n)。当列表弹出了最后一个元素之后,该数据结构自动被删除,内存被回收。Redis 的列表结构常用来做异步队列使用。将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理。

操作命令:

Lpush——先进后出,在列表头部插入元素
Rpush——先进先出,在列表的尾部插入元素
Lrange——出栈,根据索引,获取列表元素
Lpop——左边出栈,获取列表的第一个元素
Rpop——右边出栈,获取列表的最后一个元素
Lindex——根据索引,取出元素
Llen——链表长度,元素个数
Lrem——根据key,删除n个value
Ltrim——根据索引,删除指定元素
Lset——根据index,设置value
Linsert before——根据value,在之前插入值
Linsert after——根据value,在之后插入值
BLPOP/BRPOP key -- 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
BRPOPLPUSH source destination timeout -- 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
LPUSHX -- 将一个值插入到已存在的列表头部


命令lindex 相当于 Java 链表的 get(int index)方法,它需要对链表进行遍历,性能随着参数 index 增大而变差。如果再深入一点,你会发现 Redis 底层存储的还不是一个简单的linkedlist, 而是称之为快速链表 quicklist 的一个结构。首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是 ziplist,也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成 quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间,而且会加重内存的碎片化。快速列表既满足了快速的插入删除性能,又不会出现太大的空间冗余。

三、hash (字典)

Redis 的字典相当于 Java 语言里面的 HashMap,它是无序字典。内部实现结构上同 Java 的 HashMap 也是一致的,同样的数组 + 链表二维结构。第一维 hash 的数组位置碰撞时,就会将碰撞的元素使用链表串接起来。所以特点也是和Java中Map结构相似。不同的是,Redis 的字典的值只能是字符串,另外它们 rehash 的方式不一样,因为 Java 的 HashMap 在字典很大时,rehash 是个耗时的操作,需要一次性全部 rehash。Redis 为了高性能,不能堵塞服务,所以采用了渐进式 rehash 策略。渐进式 rehash 会在 rehash 的同时,保留新旧两个 hash 结构,查询时会同时查询两个 hash 结构,然后在后续的定时任务中以及 hash 的子指令中,循序渐进地将旧 hash 的内容 一点点迁移到新的 hash 结构中。当 hash 移除了最后一个元素之后,该数据结构自动被删除,内存被回收。

操作命令:

HSET key field value -- 将哈希表 key 中的字段 field 的值设为 value 
HSETNX key field value -- 只有在字段 field 不存在时,设置哈希表字段的值。
HVALS key -- 获取哈希表中所有值
HSCAN key cursor [MATCH pattern] [COUNT count] -- 迭代哈希表中的键值对。
HMSET key field1 value1 [field2 value2 ] -- 同时将多个 field-value (域-值)对设置到哈希表 key 中。
HMGET key field1 [field2] -- 获取所有给定字段的值
HLEN key -- 获取哈希表中字段的数量
HKEYS key -- 获取所有哈希表中的字段
HINCRBYFLOAT key field increment -- 为哈希表 key 中的指定字段的浮点数值加上增量 increment 
HINCRBY key field increment -- 为哈希表 key 中的指定字段的整数值加上增量 increment 
HGETALL key -- 获取在哈希表中指定 key 的所有字段和值
HGET key field -- 获取存储在哈希表中指定字段的值
HEXISTS key field -- 查看哈希表 key 中,指定的字段是否存在
HDEL key field1 [field2] -- 删除一个或多个哈希表字段


四、set (集合)

Redis 的集合相当于 Java 语言里面的 HashSet,它内部的键值对是无序的唯一的。它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值 NULL,Java中的HashSet也是基于一个value为null的HashMap。当集合中最后一个元素移除之后,数据结构自动删除,内存被回收。 set 结构可以用来做有去重需求需要实现的功能,可以保证唯一性。

操作命令:

SADD key member1 [member2] -- 向集合添加一个或多个成员
SCARD key -- 获取集合的成员数
SDIFF key1 [key2] -- 返回给定所有集合的差集
SDIFFSTORE destination key1 [key2] -- 返回给定所有集合的差集并存储在 destination 中
SINTER key1 [key2] -- 返回给定所有集合的交集
SINTERSTORE destination key1 [key2] -- 返回给定所有集合的交集并存储在 destination 中
SISMEMBER key member -- 判断 member 元素是否是集合 key 的成员
SMEMBERS key -- 返回集合中的所有成员
SMOVE source destination member -- 将 member 元素从 source 集合移动到 destination 集合
SPOP key -- 移除并返回集合中的一个随机元素
SRANDMEMBER key [count] -- 返回集合中一个或多个随机数
SREM key member1 [member2] -- 移除集合中一个或多个成员
SUNION key1 [key2] -- 返回所有给定集合的并集
SUNIONSTORE destination key1 [key2] -- 所有给定集合的并集存储在 destination 集合中
SSCAN key cursor [MATCH pattern] [COUNT count] -- 迭代集合中的元素


spop命令是随机移除一个value,这一操作,刚好是baidu从bat中给移除去了,冥冥之中自有天意呀!不过baidu的技术还是最牛逼的!

五、zset (有序列表)

zset 是 Redis 提供的最为特色的数据结构,它类似于 Java 的 SortedSet 和 HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 score,代表这个 value 的排序权重。它的内部实现用的是一种叫着“跳跃列表”的数据结构。当zset 中最后一个 value 被移除后,数据结构自动删除,内存被回收。

操作命令:

ZADD key score1 member1 [score2 member2] -- 向有序集合添加一个或多个成员,或者更新已存在成员的分数
ZCARD key -- 获取有序集合的成员数
ZCOUNT key min max -- 计算在有序集合中指定区间分数的成员数
ZINCRBY key increment member -- 有序集合中对指定成员的分数加上增量 increment
ZINTERSTORE destination numkeys key [key ...] -- 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中
ZLEXCOUNT key min max -- 在有序集合中计算指定字典区间内成员数量
ZRANGE key start stop [WITHSCORES] -- 通过索引区间返回有序集合指定区间内的成员
ZRANGEBYLEX key min max [LIMIT offset count] -- 通过字典区间返回有序集合的成员
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] -- 通过分数返回有序集合指定区间内的成员
ZRANK key member -- 返回有序集合中指定成员的索引
ZREM key member [member ...] -- 移除有序集合中的一个或多个成员
ZREMRANGEBYLEX key min max -- 移除有序集合中给定的字典区间的所有成员
ZREMRANGEBYRANK key start stop -- 移除有序集合中给定的排名区间的所有成员
ZREMRANGEBYSCORE key min max -- 移除有序集合中给定的分数区间的所有成员
ZREVRANGE key start stop [WITHSCORES] -- 返回有序集中指定区间内的成员,通过索引,分数从高到低
ZREVRANGEBYSCORE key max min [WITHSCORES] -- 返回有序集中指定分数区间内的成员,分数从高到低排序
ZREVRANK key member -- 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
ZSCORE key member -- 返回有序集中,成员的分数值
ZUNIONSTORE destination numkeys key [key ...] -- 计算给定的一个或多个有序集的并集,并存储在新的 key 中
ZSCAN key cursor [MATCH pattern] [COUNT count] -- 迭代有序集合中的元素(包括元素成员和元素分值)


zset 内部的排序功能是通过"跳跃列表"数据结构来实现的,它的结构非常特殊,也比较复杂。因为 zset 要支持随机的插入和删除,所以它不好使用数组来实现。

相关推荐

Redis合集-使用benchmark性能测试

采用开源Redis的redis-benchmark工具进行压测,它是Redis官方的性能测试工具,可以有效地测试Redis服务的性能。本次测试使用Redis官方最新的代码进行编译,详情请参见Redis...

Java简历总被已读不回?面试挂到怀疑人生?这几点你可能真没做好

最近看了几十份简历,发现大部分人不是技术差,而是不会“卖自己”——一、简历死穴:你写的不是经验,是岗位说明书!反面教材:ד使用SpringBoot开发项目”ד负责用户模块功能实现”救命写法:...

redission YYDS(redission官网)

每天分享一个架构知识Redission是一个基于Redis的分布式Java锁框架,它提供了各种锁实现,包括可重入锁、公平锁、读写锁等。使用Redission可以方便地实现分布式锁。red...

从数据库行锁到分布式事务:电商库存防超卖的九重劫难与破局之道

2023年6月18日我们维护的电商平台在零点刚过3秒就遭遇了严重事故。监控大屏显示某爆款手机SKU_IPHONE13_PRO_MAX在库存仅剩500台时,订单系统却产生了1200笔有效订单。事故复盘发...

SpringBoot系列——实战11:接口幂等性的形而上思...

欢迎关注、点赞、收藏。幂等性不仅是一种技术需求,更是数字文明对确定性追求的体现。在充满不确定性的网络世界中,它为我们建立起可依赖的存在秩序,这或许正是技术哲学最深刻的价值所在。幂等性的本质困境在支付系...

如何优化系统架构设计缓解流量压力提升并发性能?Java实战分享

如何优化系统架构设计缓解流量压力提升并发性能?Java实战分享在高流量场景下。首先,我需要回忆一下常见的优化策略,比如负载均衡、缓存、数据库优化、微服务拆分这些。不过,可能还需要考虑用户的具体情况,比...

Java面试题: 项目开发中的有哪些成长?该如何回答

在Java面试中,当被问到“项目中的成长点”时,面试官不仅想了解你的技术能力,更希望看到你的问题解决能力、学习迭代意识以及对项目的深度思考。以下是回答的策略和示例,帮助你清晰、有说服力地展示成长点:一...

互联网大厂后端必看!Spring Boot 如何实现高并发抢券逻辑?

你有没有遇到过这样的情况?在电商大促时,系统上线了抢券活动,结果活动刚一开始,服务器就不堪重负,出现超卖、系统崩溃等问题。又或者用户疯狂点击抢券按钮,最后却被告知无券可抢,体验极差。作为互联网大厂的后...

每日一题 |10W QPS高并发限流方案设计(含真实代码)

面试场景还原面试官:“如果系统要承载10WQPS的高并发流量,你会如何设计限流方案?”你:“(稳住,我要从限流算法到分布式架构全盘分析)…”一、为什么需要限流?核心矛盾:系统资源(CPU/内存/数据...

Java面试题:服务雪崩如何解决?90%人栽了

服务雪崩是指微服务架构中,由于某个服务出现故障,导致故障在服务之间不断传递和扩散,最终造成整个系统崩溃的现象。以下是一些解决服务雪崩问题的常见方法:限流限制请求速率:通过限流算法(如令牌桶算法、漏桶算...

面试题官:高并发经验有吗,并发量多少,如何回复?

一、有实际高并发经验(建议结构)直接量化"在XX项目中,系统日活用户约XX万,核心接口峰值QPS达到XX,TPS处理能力为XX/秒。通过压力测试验证过XX并发线程下的稳定性。"技术方案...

瞬时流量高并发“保命指南”:这样做系统稳如泰山,老板跪求加薪

“系统崩了,用户骂了,年终奖飞了!”——这是多少程序员在瞬时大流量下的真实噩梦?双11秒杀、春运抢票、直播带货……每秒百万请求的冲击,你的代码扛得住吗?2025年了,为什么你的系统一遇高并发就“躺平”...

其实很多Java工程师不是能力不够,是没找到展示自己的正确姿势。

其实很多Java工程师不是能力不够,是没找到展示自己的正确姿势。比如上周有个小伙伴找我,五年经验但简历全是'参与系统设计''优化接口性能'这种空话。我就问他:你做的秒杀...

PHP技能评测(php等级考试)

公司出了一些自我评测的PHP题目,现将题目和答案记录于此,以方便记忆。1.魔术函数有哪些,分别在什么时候调用?__construct(),类的构造函数__destruct(),类的析构函数__cal...

你的简历在HR眼里是青铜还是王者?

你的简历在HR眼里是青铜还是王者?兄弟,简历投了100份没反应?面试总在第三轮被刷?别急着怀疑人生,你可能只是踩了这些"隐形求职雷"。帮3630+程序员改简历+面试指导和处理空窗期时间...

取消回复欢迎 发表评论: