无名阁,只为技术而生。流水不争先,争的是滔滔不绝。

Redis缓存设计 (hgetall命令详解_1)

后端 Micheal 1年前 (2023-11-23) 221次浏览 已收录 0个评论 扫描二维码

Redis缓存设计 (hgetall命令详解_1)

Redis缓存设计 (hgetall命令详解)

一、命令使用

1、hgetall,lrange,smembers,zrange,sinter等并非不能使用,要指定明确的值,遍历的话要使用hscan、sscan、zscan代替。

2、禁止使用keys,flushall,flushdb等,通过rename禁止掉,或者用scan方式渐进。

3、合理的使用select:

redis多DB较弱,而且如果每个都有很大的高并发访问,而都接入一个redis,效率是底下且会造成干扰。(不想干的业务进行拆分,不共用)

4、可以采用pipeline代替mget,mset:

前者是非原生的,后者是原生的,原生有原子性,非原生没有,pipeline可以打包不同命令,并且他需要客户端服务端都支持。

5、redis事务比较弱建议用lua脚本实现。

二、核心命令

Redis HGETALL命令详解

Redis是一个高性能的key-value存储系统,支持多种数据类型。其中,哈希(Hash)数据类型是一种将多个键值对存储在一个Redis键下的复合类型数据结构。在哈希数据类型中,HGETALL是常用的一个命令。

HGETALL命令作用

HGETALL命令用于获取指定哈希字段(field)的所有键值对(key-value)。对于一个哈希类型的键,它可以存储多个字段(field)和相应的值(value),这些字段和值可以通过HSET命令进行设置。当需要获取一个哈希键的全部信息时,HGETALL命令是一个非常实用的命令。

HGETALL命令使用方法

下面是HGETALL命令的语法格式:

HGETALL key

其中,key表示哈希键名。

下面是一个使用HGETALL命令获取哈希键的所有信息的实例:

redis> HSET student name Tom age 20 sex male 
(integer) 3
redis> HGETALL student
1) "name"
2) "Tom"
3) "age"
4) "20"
5) "sex"
6) "male"

上述示例中,我们通过HGETALL命令获取student哈希键的所有信息,即获取键名为name,age,sex的所有键值对。

HGETALL命令的实例应用

下面是两个使用HGETALL命令的实例:

示例1:

我们模拟一个购物车功能,使用哈希数据类型存储用户的购物车信息。我们通过loadCart(userId)函数获取某个用户的购物车信息并返回一个Map对象,其中Map的key为商品名,value为商品数量。我们可以使用HGETALL命令将这个Map对象存储到Redis中。

Map<String, String> cart = loadCart("10001");
String key = "cart:10001"
Jedis jedis = new Jedis("localhost");
jedis.hmset(key, cart);

使用HGETALL命令获取存储在Redis中的购物车信息:

cart:10001
1) "apple"
2) "3"
3) "banana"
4) "2"
5) "orange"
6) "1"

示例2:

假设我们有一个名为president的哈希,存储了某个学校班级的所有成员及其个人信息。想要获取名字以“Zhang”开头的所有学生的信息,可以在代码中执行如下查询语句:

Jedis jedis = new Jedis("localhost");
Map<String, String> memberInfo = jedis.hgetAll("president");
List<String> members = new ArrayList<>();
for (Map.Entry<String, String> entry : memberInfo.entrySet()) {
    if (entry.getValue().startsWith("Zhang")) {
        members.add(entry.getKey());
    }
}
Map<String, String> result = jedis.hmget("president", members.toArray(new String[0]));

三、核心参数

1、maxTotal

最大连接数,早期较maxActive

一般maxTotal*nodes 小于 maxclients

为什么呢?

因为如果每个客户端处理的是1000,而我们有10个客户端,那么可以处理10000,即使maxclients设计的再大,剩余的也不会存储。

如果我们要求业务QPS是50000?

那么根据每个客户处理1000,则需要配置50个客户端就可以完成QPS5000的业务,但实际要考虑一些网络消耗时间,所以实际要比这个值稍微大一点。

但又不是越大越好,占用太多服务器和客户端资源,而且如果有一个大的阻塞key,对于配置再多也无济于事。

2、maxIdle和minIdle

最大空闲连接 和 最小空闲连接

当redis在业务峰值期间连接了几十个redis连接,这时候峰值过后,redis会慢慢关闭连接,留下maxIdle空闲连接数,正常配置默认都是maxIdle。

连接池预热,当redis刚启动的时候,就有大量并发访问,这时候可以采用ping命令先连接redis,保证先有空闲连接数。(预热的时候千万别执行jedis.close)

当我们并发量很高,或者并发量很频繁的时候,maxIdle和maxTotal设置可以保持一致,这样避免连接创建和关闭造成的性能损耗,并发量不是特别高就没必要。

三、redis删除策略

删除分为 被动删除 和 主动删除

1、被动删除:又叫惰性删除,当我们删除一个key的时候不会立马删掉,会在下一次访问的时候,触发惰性删除策略。(获取前判断key是否过期,过期则删除返回null)

这种情况下会出现一个问题是冷数据无法及时清理,如果一个数据不被访问了,不是一直不会被删除吗。

2、主动删除:所以redis会定期清理一些已过期的key。

3、当已用内存超过maxmemory时,触发主动删除策略。

主动删除策略在4.0之前有6种,redis4.0之后8种。

针对过期key:

1)volitile-ttl:在筛选时候,会针对过期时间,越早过期的先删除。

2)Volitile-random:对设置过期的key,随机删除。

3)Volatile-lru:采用lru算法对过期key删除。

4)Volatile-lfu:采用lfu算法对过期key删除。

针对所有key

5)allkeys-random:对所有key随机删除。

6)Allkeys-lru:lru算法对所有key进行删除。

7)Allkeys-lfu:lfu算法对所有key进行删除。

不删除

8)noeviction:不删除任何数据,提示OOM,这时候redis只支持读数据。

Lru算法:用最近一次访问时间作为参考,淘汰很久时间之前访问的数据。

Lfu算法:以访问次数参考,淘汰次数少的数据。

热点数据如果用lru算法,效率可能会更高,但如果是偶发、周期性的批量操作导致LRU命中率急剧下降,缓存污染比较严重,这时候LFU更好。

(比如热点数据访问100次,但是冷数据访问就2次,但因为是按访问时间来淘汰的,所以这时候可能会把热点数据淘汰,所以这时候采用lfu更好)

默认推荐用lru算法,maxmemory-policy默认是noeviction。这里maxmemory一定要设置,如果不设置,redis超过物理内存限制,内存数据和磁盘会频繁swap,会导致性能下降。

对于主从节点,主节点是策略删除,从节点是被同步的del key删除。

谷歌视频搜索(详细攻略)

喜欢 (0)
[]
分享 (0)
关于作者:
流水不争先,争的是滔滔不绝
发表我的评论
取消评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

表情 贴图 加粗 删除线 居中 斜体 签到