redis hash删除所有key_一文详解Redis面试中常见的5种数据结构及对应使用场景
欢迎关注专栏《Java架构筑基》——专注于Java技术的研究与分享!
Java架构筑基zhuanlan.zhihu.com
- Java架构筑基——专注于Java技术的研究与分享!
- 后续文章将首发此专栏!
- 欢迎各位Java工程师朋友投稿和关注
- # 链接 Java程序员福利"常用资料分享"
写在前边
也当过面试官,面试过不少应聘者,因为是我自己招人自己用,所以我不会看应聘者造火箭的技术有多牛比,只看拧螺丝的手艺瓷不瓷实。毕竟以后是一个整体,拖了大家后腿团队都很难受。面试的题目一般也不会太难,就像问Redis
,我只是想确认他真正用过就够了。Redis
5种基础数据结构和简单操作要知道,最基本的要求,如果这个时候他会说出每种数据结构大致的应用场景,那么这一定是加分的,起码要比那些只会说出几种数据结构后,在那干瞪眼等我问下一个问题的强很多,千万别冷场。
Redis基础数据结构有哪些?
一、String(字符串)
在任何一种编程语言里,字符串String
都是最基础的数据结构, 那你有想过Redis
中存储一个字符串都进行了哪些操作嘛?
在Redis
中String
是可以修改的,称为动态字符串
(Simple Dynamic String
简称 SDS
)(快拿小本本记名词,要考的),说是字符串但它的内部结构更像是一个 ArrayList
,内部维护着一个字节数组,并且在其内部预分配了一定的空间,以减少内存的频繁分配。
Redis
的内存分配机制是这样:
- 当字符串的长度小于 1MB时,每次扩容都是加倍现有的空间。
- 如果字符串长度超过 1MB时,每次扩容时只会扩展 1MB 的空间。
这样既保证了内存空间够用,还不至于造成内存的浪费,字符串最大长度为 512MB
.。
上图就是字符串的基本结构,其中 content
里面保存的是字符串内容,0x0
作为结束字符不会被计算len
中。
分析一下字符串的数据结构
struct SDS{T capacity; //数组容量T len; //实际长度byte flages; //标志位,低三位表示类型byte[] content; //数组内容
}
capacity
和 len
两个属性都是泛型,为什么不直接用int类型
?因为Redis
内部有很多优化方案,为更合理的使用内存,不同长度的字符串采用不同的数据类型表示,且在创建字符串的时候 len
会和 capacity
一样大,不产生冗余的空间,所以String
值可以是字符串、数字(整数、浮点数) 或者 二进制。
1. 应用场景:
存储key-value键值对,这个比较简单不细说了
2. 字符串(String)常用的命令:
set [key] [value] 给指定key设置值(set 可覆盖老的值)get [key] 获取指定key 的值del [key] 删除指定keyexists [key] 判断是否存在指定keymset [key1] [value1] [key2] [value2] ...... 批量存键值对mget [key1] [key2] ...... 批量取keyexpire [key] [time] 给指定key 设置过期时间 单位秒setex [key] [time] [value] 等价于 set + expire 命令组合setnx [key] [value] 如果key不存在则set 创建,否则返回0incr [key] 如果value为整数 可用 incr命令每次自增1incrby [key] [number] 使用incrby命令对整数值 进行增加 number
二、list(列表)
Redis
中的list
和Java
中的LinkedList
很像,底层都是一种链表结构, list
的插入和删除操作非常快,时间复杂度为 0(1),不像数组结构插入、删除操作需要移动数据。
像归像,但是redis
中的list
底层可不是一个双向链表那么简单。
当数据量较少的时候它的底层存储结构为一块连续内存,称之为ziplist(压缩列表)
,它将所有的元素紧挨着一起存储,分配的是一块连续的内存;当数据量较多的时候将会变成quicklist(快速链表)
结构。
可单纯的链表也是有缺陷的,链表的前后指针 prev
和 next
会占用较多的内存,会比较浪费空间,而且会加重内存的碎片化。在redis 3.2之后就都改用ziplist+链表
的混合结构,称之为 quicklist(快速链表)
。
下面具体介绍下两种链表
ziplist(压缩列表)
先看一下ziplist
的数据结构,
struct ziplist<T>{int32 zlbytes; //压缩列表占用字节数int32 zltail_offset; //最后一个元素距离起始位置的偏移量,用于快速定位到最后一个节点int16 zllength; //元素个数T[] entries; //元素内容int8 zlend; //结束位 0xFF
}
int32 zlbytes
: 压缩列表占用字节数int32 zltail_offset
: 最后一个元素距离起始位置的偏移量,用于快速定位到最后一个节点int16 zllength
:元素个数T[] entries
:元素内容int8 zlend
:结束位 0xFF
压缩列表为了支持双向遍历,所以才会有 ztail_offset
这个字段,用来快速定位到最后一
个元素,然后倒着遍历
entry
的数据结构:
struct entry{int<var> prevlen; //前一个 entry 的长度int<var> encoding; //元素类型编码optional byte[] content; //元素内容
}
entry
它的 prevlen
字段表示前一个 entry
的字节长度,当压缩列表倒着遍历时,需要通过这
个字段来快速定位到下一个元素的位置。
1. 应用场景:
由于list它是一个按照插入顺序排序的列表,所以应用场景相对还较多的,例如:
- 消息队列:
lpop
和rpush
(或者反过来,lpush
和rpop
)能实现队列的功能 - 朋友圈的点赞列表、评论列表、排行榜:
lpush
命令和lrange
命令能实现最新列表的功能,每次通过lpush
命令往列表里插入新的元素,然后通过lrange
命令读取最新的元素列表。
2. list操作的常用命名:
rpush [key] [value1] [value2] ...... 链表右侧插入rpop [key] 移除右侧列表头元素,并返回该元素lpop [key] 移除左侧列表头元素,并返回该元素llen [key] 返回该列表的元素个数lrem [key] [count] [value] 删除列表中与value相等的元素,count是删除的个数。 count>0 表示从左侧开始查找,删除count个元素,count<0 表示从右侧开始查找,删除count个相同元素,count=0 表示删除全部相同的元素(PS: index 代表元素下标,index 可以为负数, index= 表示倒数第一个元素,同理 index=-2 表示倒数第二 个元素。)lindex [key] [index] 获取list指定下标的元素 (需要遍历,时间复杂度为O(n))lrange [key] [start_index] [end_index] 获取list 区间内的所有元素 (时间复杂度为 O(n))ltrim [key] [start_index] [end_index] 保留区间内的元素,其他元素删除(时间复杂度为 O(n))
三、hash (字典)
Redis
中的 Hash
和 Java的 HashMap
更加相似,都是数组+链表
的结构,当发生 hash 碰撞时将会把元素追加到链表上,值得注意的是在 Redis
的 Hash
中 value
只能是字符串.
hset books java "Effective java" (integer) 1
hset books golang "concurrency in go" (integer) 1
hget books java "Effective java"
hset user age 17 (integer) 1
hincrby user age 1 #单个 key 可以进行计数 和 incr 命令基本一致 (integer) 18
Hash
和String
都可以用来存储用户信息 ,但不同的是Hash
可以对用户信息的每个字段单独存储;String
存的是用户全部信息经过序列化后的字符串,如果想要修改某个用户字段必须将用户信息字符串全部查询出来,解析成相应的用户信息对象,修改完后在序列化成字符串存入。而 hash可以只对某个字段修改,从而节约网络流量,不过hash内存占用要大于 String
,这是 hash
的缺点。
1. 应用场景:
- 购物车:
hset [key] [field] [value]
命令, 可以实现以用户Id
,商品Id
为field
,商品数量为value
,恰好构成了购物车的3个要素。 - 存储对象:
hash
类型的(key, field, value)
的结构与对象的(对象id, 属性, 值)
的结构相似,也可以用来存储对象。
2. hash常用的操作命令:
hset [key] [field] [value] 新建字段信息hget [key] [field] 获取字段信息hdel [key] [field] 删除字段hlen [key] 保存的字段个数hgetall [key] 获取指定key 字典里的所有字段和值 (字段信息过多,会导致慢查询 慎用:亲身经历 曾经用过这个这个指令导致线上服务故障)hmset [key] [field1] [value1] [field2] [value2] ...... 批量创建hincr [key] [field] 对字段值自增hincrby [key] [field] [number] 对字段值增加number
四、set(集合)
Redis
中的 set
和Java
中的HashSet
有些类似,它内部的键值对是无序的、唯一 的。它的内部实现相当于一个特殊的字典,字典中所有的value都是一个值 NULL。当集合中最后一个元素被移除之后,数据结构被自动删除,内存被回收。
1. 应用场景:
- 好友、关注、粉丝、感兴趣的人集合:
sinter
命令可以获得A和B两个用户的共同好友;sismember
命令可以判断A是否是B的好友;scard
命令可以获取好友数量;- 关注时,
smove
命令可以将B从A的粉丝集合转移到A的好友集合
- 首页展示随机:美团首页有很多推荐商家,但是并不能全部展示,set类型适合存放所有需要展示的内容,而
srandmember
命令则可以从中随机获取几个。 - 存储某活动中中奖的用户ID ,因为有去重功能,可以保证同一个用户不会中奖两次。
2. set的常用命令:
sadd [key] [value] 向指定key的set中添加元素smembers [key] 获取指定key 集合中的所有元素sismember [key] [value] 判断集合中是否存在某个valuescard [key] 获取集合的长度spop [key] 弹出一个元素srem [key] [value] 删除指定元素
五、zset(有序集合)
zset
也叫SortedSet
一方面它是个 set
,保证了内部 value 的唯一性,另方面它可以给每个 value 赋予一个score
,代表这个value的排序权重。它的内部实现用的是一种叫作“跳跃列表
”的数据结构。
1. 应用场景:
zset
可以用做排行榜,但是和list
不同的是zset
它能够实现动态的排序,例如: 可以用来存储粉丝列表,value 值是粉丝的用户 ID,score 是关注时间,我们可以对粉丝列表按关注时间进行排序。
zset
还可以用来存储学生的成绩, value
值是学生的 ID, score
是他的考试成绩。 我们对成绩按分数进行排序就可以得到他的名次。
2. zset有序集合的常用操作命令:
zadd [key] [score] [value] 向指定key的集合中增加元素zrange [key] [start_index] [end_index] 获取下标范围内的元素列表,按score 排序输出zrevrange [key] [start_index] [end_index] 获取范围内的元素列表 ,按score排序 逆序输出zcard [key] 获取集合列表的元素个数zrank [key] [value] 获取元素再集合中的排名zrangebyscore [key] [score1] [score2] 输出score范围内的元素列表zrem [key] [value] 删除元素zscore [key] [value] 获取元素的score
总结
本文很多概念都一带而过了,只是给大家粗略的讲述一下Redis五种基础数据结构和应用场景,旨在给小伙伴们一个面试备题的方向,后续会持续输出Redis方面的文章,欢迎关注,咱们一起学习拿offer
# 链接 Java程序员福利"常用资料分享"
redis hash删除所有key_一文详解Redis面试中常见的5种数据结构及对应使用场景相关推荐
- 一文详解Redis企业版软件!
一.Redis企业版软件概述 Redis企业版软件(Redis Enterprise)是企业级的数据库软件,也是一款实时数据平台,为全球超过8500家知名企业提供实时数据服务.具有线性可扩展性.高可用 ...
- 一文详解Redis中BigKey、HotKey的发现与处理
简介: 在Redis的使用过程中,我们经常会遇到BigKey(下文将其称为"大key")及HotKey(下文将其称为"热key").大Key与热Key如果未能及 ...
- Redis为什么变慢了?一文详解Redis性能问题 | 万字长文
Redis 作为优秀的内存数据库,其拥有非常高的性能,单个实例的 OPS 能够达到 10W 左右.但也正因此如此,当我们在使用 Redis 时,如果发现操作延迟变大的情况,就会与我们的预期不符. 你也 ...
- 一文详解Redis键过期策略
1 设置带过期时间的 key # 时间复杂度:O(1),最常用方式 expire key seconds# 字符串独有方式 setex(String key, int seconds, String ...
- java集群解析文件_干货:一文详解Redis集群原理核心内容
集群原理 一个系统建立集群主要需要解决两个问题:数据同步问题和集群容错问题. Naive方案 一个简单粗暴的方案是部署多台一模一样的Redis服务,再用负载均衡来分摊压力以及监控服务状态.这种方案的优 ...
- 一文详解目标跟踪中的相关滤波
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 本文来源:AI干货知识库 / 导读 / 目标跟踪是计算机视觉领域的一个重要问题,目前广泛应用在体育赛事 ...
- 一文详解工业视觉中的光源及应用
来源丨新机器视觉 光源 机器视觉系统主要由三部分组成:图像的获取.图像的处理和分析.输出或显示.而图像的获取是机器视觉的核心,图像的获取系统则是由光源.镜头.相机三部分组成.光源的选取与打光合理与否可 ...
- 一文详解启发式对话中的知识管理 | 公开课笔记
来源 | AI科技大本营在线公开课 分享嘉宾 | 葛付江(思必驰 NLP 部门负责人) 整理 | Jane [导读]自然语言对话系统正在覆盖越来越多的生活和服务场景,同时,自然语言对话的理解能力和对精 ...
- 一文详解PHP连接MySQL数据库的三种方式
PHP与MySQL的连接有三种API接口,分别是:PHP的MySQL扩展 .PHP的mysqli扩展 .PHP数据对象(PDO). 1.MySQL扩展 PHP 的 MySQL 扩展是设计开发允许 PH ...
最新文章
- java.sql在哪_我的Java访问MS SQL的程序错在哪了?谢谢!
- poj1256(贪心+并查集)
- 34.16.159(zz)
- 设计模式之装饰模式20170726
- Redis 持久化之RDB和AOF
- 源于 Node.js的HTML 模板引擎Jade的一个hello world项目
- Java手写HashSet
- MySQL数据查询新人须知
- OpenGL ES (三)着色器和程序
- java内存管理(堆、栈、方法区)
- WCF开发实战系列四:使用Windows服务发布WCF服务
- dsh linux,通过dsh批量管理Linux服务器(一)【感谢作者的无私分享】
- SWOT分析》思维导图,帮助你做好企业优势劣势分析图
- python爬虫猫眼电影TOP100(爬虫入门基础,同步入库)
- linux查看进程的代码,Linux ps 查看进程(示例代码)
- Java的全局异常处理(统一异常处理)+登陆拦截鉴权+注解实现记录日志
- 移动端300ms延迟_移动端延迟300ms的原因以及解决方案
- 安卓执法仪录像之进程间共享内存
- POI java导出Excel设置自适应行高
- 为什么RSA公钥每次加密得到的结果都不一样?