Redis使用经验之谈

应用场景

  1. 保存用户喜欢的商品信息.

    类型: Hash,

    key: usr:${type_id}:${version_id}:${user_id}:${warehouse_id},

    field: ${sku_id},

    value: jsonstr(sku对应的brand, goods, 来源渠道等信息)  

  2.  记录用户喜欢的商品所在档期的数目.
    类型: ZSet,
    key: usr:${type_id}:${version_id}:${user_id}:${warehouse_id},
    value: ${brand_id},
    score: int(喜欢则+1, 取消喜欢则-1)
  3.  Redis同步Queue, 定期将喜欢/取消喜欢的商品同步到mysql,
    类型: List,
    key: usr:${type_id}:${version_id}:${user_id}:${warehouse_id},
    value: jsonstr(sku对应的brand, goods, 喜欢状态)

 最佳实践

1,针对商品收藏, 粒度是sku的时候, 如何更好的利用redis丰富的数据类型? 

 以user_id+warehouse_id作为查询条件, 存储的信息包括sku_id, good_id, brand_id, channel, time等信息,如果采用redis基础的 Key/Value 存储结构, 那么

  • 方案1:  user_id+warehouse作为key, value是所有喜欢的商品信息的一个集合, 这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。
  •  方案2:  user_id+warehouse+sku作为key, value是单件sku信息的序列化信息, 第二种方法是这个用户喜欢商品有多少成员就存成多少个key-value,用user_id+warehouse+sku唯一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的, 并且如果要全部取出用户所有的喜欢商品数据, 只能先用keys 正则匹配, 拿到所有key的list, 再遍历去拿每个的对应value, 性能不可接受.
 所以我们采用了redis的Hash数据结构, 也就是说,Key仍然是user_id+warehouse_id, value是一个Map,这个Map的key是sku_id,value是sku喜欢的详情信息,这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key+ field 就可以操作对应属性数据了, 获取全部喜欢信息的时候可以使用HVals或者HGETALL, 解决了数据存储冗余, CAS并发和获取麻烦的问题. 但是如果内部Map的成员很多,那么涉及到遍历整个内部Map的操作,由于Redis单线程模型的缘故,这个遍历操作可能会比较耗时

 

2,针对统计用户喜欢商品对应档期的计数,

 以user_id+warehouse作为查询条件, 存储的主要是每个brand_id下用户喜欢了多少商品,如果采用基础的K/V结构的话, 无法避免的会出现上面例子产生的问题

 如果采用HASH, key: user_id+warehouse_id,  field: brand_id, value: int 存在的问题是: CAS并发问题, 不通过Redis加锁机制, 无法保证加减操作的原子性, 而且必须与Redis通讯两次, 第一次获取并加锁, 第二次设置新值

 所以我们采用ZSET结构, Redis sorted set的可以通过提供一个优先级(score)的参数来为成员排序或计数, 并且是插入有序的, 如果需要对set中某一个brand_id的数目进行操作只需要一次redis通讯, 并且是原子性操作

3,使用pipeline, 减少调用redis通讯次数, 如果需要返回值, 则可以使用syncAndReturn方法

踩过的坑

 商品收藏一开始没有采用sharding的Redis部署架构, 导致单机Redis CPU和流量很大, 后期进行扩展的做法不知道好还是不好, 写出来大家可以讨论: 新部署结构上线前将扩容的4台新Redis实例slaveof原有实例, 将原有单机数据持续引入, 新部署结构完全上线后, 将slaveof切断, 5台实例向外提供服务.

    • 优点: 不会造成数据丢失, 扩展平滑对调用方透明

    • 缺点: 新实例上会有垃圾数据

原文地址:https://www.cnblogs.com/zhwbqd/p/3745704.html