redis妙用-hash类型
hash类型,又叫作散列类型,它类似hashmap,通过一定的hash算法得到对应的索引位置,然后将数据保存在该索引所在的地方。本章讲述的东西,重点不在于应用场景,因为hash能做的事情,string也都能做。所以本章分享的是,试图揣测redis官方推出hash的意义,以及实现原理。
api
针对字符串的操作
命令 |
说明 |
---|---|
HSET key fieId value |
存储一个散列键 |
HMSETNX key fieId valuefieId value ... |
批量一个key的多个fieId |
HSETNX key fieId value |
存入一个不存在的散列键 |
HGET key fieId |
获取key的一个键的值 |
HMGET key fieIdfieId ... |
批量获取key的值 |
HDEL key fieId |
删除一个散列键 |
针对数字的操作
命令 |
说明 |
---|---|
HINCRBY key fieId increment |
对key散列中的fieId进行{increment}的增加 |
应用场景
缓存
像string类型一样,它的第一个应用场景作为缓存,我们考虑一下该表存在redis中怎么存储合适。
-- 约定key生成规则为
{table} {id}::name {id}::age
-- 写入缓存
HMSET user 1::name ally 1::age 18
-- 读取缓存
HMGET user 1::name 1::age
hash键意义何在?
看完hash键的api,我们看到hash类型存在的命令,string类型都提供了,就连上面举例的缓存的应用场景,string类型也可以实现,那么这个时候hash类型的意义存在哪里?
- hash键可以将信息凝聚在一起,而不是直接分散的存储在整个redis中,方便管理数据,还可以避免一定的误操作
- 避免键名冲突
- 减少内存/cpu的消耗
这里仅解释第三点,第三点怎么理解,当你给key设置一个过期时间的时候,redis会对所有的key进行扫描它有没有过期,而这种机制只会对hash键的key进行扫描,它的fieId层是不会被扫描的,所以减少的消耗。当你有一批key它们的过期时间一致,你使用string类型,他会扫描所有的key,而使用hash类型,redis只需扫描hash的第一层。
哪些情况不适用hash?
- 需要使用过期功能,过期功能只能使用在key上
- 二进制操作命令不适用hash,如:SETBIT,GETBIT,BITOP
- 需要考虑数据量分布问题
这里仅解释第三点,第三点怎么理解,需要先了解redis集群存储方式(预分配hash槽),redis会将集群分为16384个槽,16384不会根据集群的数量而改变。然后将16384个槽平均分配给每一个redis节点去管理。如图所示
当一个key需要存储时,会对key进行取模计算,得到一个槽的位置,假如这个槽由redis的节点1管理,那么这个key的数据就会真正落在节点1的物理内存上。
这个时候来解释第三点的原因,假如我们使用hash类型,缓存的key约定为以上举例的情况,那么user表的所有数据都会落在某一个节点上,假如这个表的数据有一千万,那么一千万都落在一个节点上,其他的节点上没有数据,这肯定是不合适的。这个节点内存是会撑爆的。
那么回过头来,为什么redis要采用预分配hash槽作为集群管理的方案?
主要是为了解决快速扩缩容的问题。假如我现在新加入一个节点,根据预分配hash槽的方案,该新加入的节点管理的槽为16384,16284...那么redis要做的操作只需将这些槽的数据迁移到新节点上就行了,不用像hashmap那样rehash的操作。
- PostgreSQL的PDF.NET驱动程序构建过程
- 基于Docker的PHP开发环境
- 以太坊·物流场景初探
- Python接口自动化-3-POST请求
- 【Python环境】Python中的结构化数据分析利器-Pandas简介
- JAVA中使用Jedis操作Redis
- Tomcat搭建文件服务器
- Windows下SLmail邮件服务器缓冲区溢出理解及实验
- java使用mina和websocket通信
- 【机器学习】10 种机器学习算法的要点
- 写一个BASIC认证的https协议
- java发送邮件功能,以发送qq邮件为例
- spring boot加载复杂的yml文件获取不到值的问题
- JUC包下的CountDownLatch,CyclicBarrier,Semaphore
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Java——static关键字总结(含义、定义属性或方法、使用时机)
- Java——try catch finally异常的捕获及处理逻辑实例详解大全
- Java——String类使用详解(实例化、字符串比较、匿名对象、两种实例化方法的区别)
- Java——数组的定义与使用(基本概念、引用分析、初始化方式、二维数组、对象数组)
- Java——单例设计模式
- Java——包的定义及使用
- Java——Object类(基本概念、toString()方法、equals()方法、可以接收所有引用类型)
- JavaWeb——MyBatis框架之对数据库的增删改查操作CRUD实践及MyBatis参数的深入详解
- JavaWeb——MyBatis框架之入门总结及案例实战,常见坑处理:Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.0.0
- JavaWeb——MyBatis框架之执行过程原理与解析(通过自定义MyBatis查询所有操作的实现来观察整个过程)
- Java——抽象类(基本概念、使用原则、模板设计模式)
- Java——覆写(概念、覆写的意义、覆写的要求)
- Java——继承性(继承的作用、实现、限制)
- JavaWeb——JSON语法讲解与Jackson解析器完成JSON数据与Java对象的转换(应用Ajax与JSON实现校验用户名是否在的功能)
- JavaWeb——JQuery之高级案例实战(打开网页自动弹出广告效果、抽奖效果实现)