Redis——存储优化

Redis中不支持嵌套数据结构,只支持字符串类型的k-v数据结构

1.对象存储

  1. 在项目中以前对对象的存储才用的是序列化操作,每次存入Redis都需要先将对象序列化,然后在存入,取出时再反序列化。
    优点:虽然需要序列化和反序列化,但是可以直接操作对象的方法,方便快捷
    缺点:需要序列化和反序列化,并且修改单个字段,需要获取整个json,修改后,序列化保存,浪费空间,浪费时间,效率低

  2. 后来为了节约内存空间,以及进度类需要实时更新其中某个字段,而非全部,所以为了提升效率,于是采用redis的hash数据类型重构。Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
    考虑到实际情况,比如多用户任务进度信息,需要userId与taskName唯一标志一个进度信息,因此对应的进度key为:userId:taskName value:cnt、count、finish、breakdown
    Redis——存储优化_第1张图片

    另外需要快速查询每个用户对应的所有进度信息,因此还需要存储每个用户所对应的的任务名

Redis——存储优化_第2张图片

2.大key优化

大key即某个key所对应的的value空间巨大,由于Redis单线程运行的原因,造成读取时间过长,阻塞其它程序的运行。
这里有一个优化标准 https://blog.csdn.net/wwd0501/article/details/92702238

  1. 单个简单的key存储的value很大
    【对象需要每次都整存整取】
    可以尝试将对象分拆成几个key-value, 使用multiGet获取值,这样分拆的意义在于分拆单次操作的压力,将操作压力平摊到多个redis实例中,降低对单个redis的IO影响;
    【对象每次只需要存取部分数据】
    可以像第一种做法一样,分拆成几个key-value, 也可以将这个存储在一个hash中(就像上面的对象存储优化方案一样),每个field代表一个具体的属性,使用hget,hmget来获取部分的value,使用hset,hmset来更新部分属性

  2. hash, set,zset,list 中存储过多的元素
    类似于场景一种的第一个做法,可以将这些元素分拆。
    以hash为例,原先的正常存取流程是 hget(hashKey, field) ; hset(hashKey, field, value)
    现在,固定一个桶的数量,比如 10000, 每次存取的时候,先在本地计算field的hash值,模除 10000, 确定了该field落在哪个key上。

    newHashKey  =  hashKey + (*hash*(field) % 10000;   
    hset (newHashKey, field, value) ;  
    hget(newHashKey, field)
    

    set, zset, list 也可以类似上述做法.
    但有些不适合的场景,比如,要保证 lpop 的数据的确是最早push到list中去的,这个就需要一些附加的属性,或者是在 key的拼接上做一些工作(比如list按照时间来分拆)。

你可能感兴趣的:(Redis)