【redis】hash 类型应用场景
文章目录
- 作为缓存
- 伪代码实现
- 缓存方式对比
作为缓存
使用 string
也是可以作为缓存使用的。存储结构化数据,使用 hash
类型更适合一些
关系型数据表保存用户信息:
映射关系表示用户信息:
上述场景使用
string
类型也能做到,就是需要使用JSON
这样的数据格式
伪代码实现
UserInfo getUserInfo(long uid) {
// 根据 uid 得到 Redis 的值
String key = "user:" + uid;
// 尝试从 Redis 中获取对应的值
userInfoMap = Redis 执行命令: hgetall key;
// 如果缓存命中(hit)
if(value != null) {
// 将映射关系还原为对象形式
UserInfo userInfo = 利用映射关系构建对象(userInfoMap);
return userInfo;
}
// 如果缓存未命中(miss)
// 从数据库中,根据 uid 获取用户信息
UserInfo userInfo = MySQL 执行 SQL: select * from user_info whiere uid = <uid>
// 如果列表中没有 uid 对应的用户信息
if(userInfo == null) {
响应404
return null;
}
}
缓存方式对比
如果使用 string
(JSON
)的格式来表示 UserInfo
。万一只想获取其中的某个 field
,或者修改某个 field
的时候,就需要把整个 JSON
都读出来,解析成对象,操作 field
,再重新转成 JSON
字符,再写回去
如果使用 hash
的方式来表示 UserInfo
,就可以使用 field
表示对象的每个属性(数据表的每个列),此时就可以非常方便的修改/获取任何一个属性的值了
使用 hash
的方式,确实读写 field
更直观高效,但是付出的是空间的代价
- 需要控制哈希在
ziplist
和hashtable
两种内部编码的转换,可能会造成内存的较大消耗 - 具体操作还是看需求,是更关注速度,时间上的(
hash
);还是内存,空间上的(string
)
到目前位置,我们能够使用三种方法缓存用户信息,还有一种原生字符串类型——使用字符串类型,每个属性一个键
set user:1:name James
set user:1:age 23
set user:1:city BJ
- 这种方式,一般不推荐使用。相当于把同一个数据的各个属性,给分散开了,低内聚
我们在写代码/管理数据,更追求的是高内聚
- 内聚:把有关联的东西放在一起,最好能放在指定的地方(好找)
- 耦合:两个模块/代码之间的关联关系,关联关系越大,越容易相互影响,认为耦合越大。
- 追求的是“低耦合”,避免“牵一发而动全身”,这边一改出
bug
,就影响到了其他地方
- 哈希类型是稀疏的,而关系型数据库是完全结构化的,例如哈希类型每个键可以有不同的
field
,而关系型数据库一旦添加新的列,所有行都要为期设置值,即使为null
- 关系数据库可以做复杂的关系查询,而
Redis
去模拟关系型复杂查询,例如联表查询、聚合查询等基本不可能,维护成本高