云数据库 GEMINIDB-GeminiDB Redis广告频控业务exHash方案:应用场景

时间:2024-10-29 15:29:47

应用场景

  • 频控场景

    频控指的是对用户在一定时间内(例如一天、一周、一个月)进行某种操作的次数进行限制,可以控制特定广告或信息在一定时间内在特定平台上的展示次数,以避免过度曝光和广告疲劳,同时优化广告效果和用户体验;对于广告来说,也可以提高广告的效果和转化率。此外,频控还可以避免恶意行为,如刷流量、刷评论、刷点赞等。

    频控的3个要素包含用户ID、广告ID、触发次数;以用户ID为key,广告ID为field,指定时间内的触发次数为value,恰好构成频控的三要素。先配置好各个广告的指定频控策略,如下图所示即可根据如下的方式来实现频控:

    图1 频控Hash方案
    • 最左边通过Hash类型来实现,通过expire命令设置User_1的过期时间为一天,每推送一次通过hincrby来增加指定广告的推送次数,每次推送指定广告前在一天内的推送次数则可以通过hget获取进行判断,一天后该用户的数据自动过期无需手动清理,这样便可以简单地实现频控。但这个方案的缺点在于对于每个用户(即每个key)只能设置一个过期时间,无法做到例如8小时3次这样指定时间段内的灵活的频控策略。
    • 为了做到对每个广告都配置指定时间段内的灵活频控,如中间图所示可以通过将时间戳拼接在value里的方式用Hash类型来实现,但这种方案无疑是增加了业务侧开发的工作量。
    • 如最右图所示,支持给field设置过期时间的exHash类型可以很完美地解决Hash类型面对频控场景的缺点。由于Field支持过期时间设置,那么该场景下,平台可以给每个广告都配置不同时间段内的频次要求,假设此时给AD_2配置的频控策略为8小时内2次,那么如图所示在下一次再准备给User_1推送AD_2广告前,先通过exhget User_1 AD_2命令获取到了该值已经是2时,便可以判断出此时根据平台频控策略,不应该再给User_1推送AD_2广告了。而当8小时一过,User_1的AD_2这个field过期后,exhget无法再获取到这个field的信息,则可以继续给User_1推送AD_2广告了。
  • 购物车场景

    双十一期间,相信很多同学购物车里都填满了各种想要清空的宝贝,这里就以购物车场景为例介绍该场景的几种不同Redis类型的实现,并比较这几种实现方案的优缺点。

    1. 基于String实现购物车功能

      如图图2所示,基于String可以轻松地实现各个用户的购物车功能,该方案需要将用户ID与商品ID进行拼接作为key,例如User_1#Earphones_1,key对应的value为购物车中用户准备购买的数量,其中可能有部分商品为限时特购,所以有过期时间,为key对应的过期时间。

      图2 String方案
      • 涉及命令如下:
        incrby User_N#Product_N [Number] # 增加商品数量
        set User_N#Product_N [Number] # 设置商品数量
        expire User_N#Product_N Time_N # 设置指定用户购物车中指定物品的过期时间
        get User_N#Product_N # 获取商品数量
        scan 0 match User_N* # 查找所有User_N下的所有商品
        del User_N#Product_N # 删除指定用户购物车中的指定商品
      • 该方案会存在如下问题:
        • 额外拼接增加编、解码开发工作量。
        • 某个用户获取自己的购物车清单时还需要通过scan命令前缀匹配扫描所有key,并通过get命令去获取对应的值。
        • 想要直接获取清单长度时,仍然需要遍历整个前缀key的数目,方法复杂。
        • 存在大量重复的用户名前缀,浪费存储空间。
    2. 基于Hash实现购物车功能

      可以根据如图3所示的Hash类型来实现购物车的管理,用户ID作为key,商品ID作为field,value为购物车中对应商品的数量。其中对于部分限时特购的商品,其过期时间通过拼接的方式放到field对应的value里。

      图3 Hash方案
      • 涉及命令如下:
        hset User_N Product_N [Number#Time_N] # 设置指定用户购物车中指定商品的数量和过期时间
        hincrby User_N Product_N [Number] # 增加指定用户购物车中的指定商品数量
        hgetUser_N Product_N # 获取指定用户购物车中指定商品的信息
        hgetall User_N # 获取指定用户的所有商品信息
        hlen User_N # 获取指定用户购物车中的总商品数量
        hdel User_N Product_N # 删除指定用户购物车中的指定商品
      • 该方案相对于String类型的方案有了不少优化:
        • 获取某个用户购物车中的所有商品清单仅需要一个hgetall命令即可。
        • 获取某个用户的清单长度时直接hlen获取即可。
        • 不存在大量重复的用户名前缀问题。

      然而该方案仍存在一个明显的缺点,即对于部分限时特购的商品处理起来复杂:对于User_1的Keyboard_1商品,如果要再加一个数量,不能直接使用hincrby,而是需要先hget获取Keyboard_1商品的值并解码,再加上指定的数量再编码后hset对应的值。

    3. 基于exHash实现购物车功能

      根据如图4所示的exHash类型来实现购物车的管理,同Hash类型一样,用户ID作为key,商品ID作为field,value为购物车中对应商品的数量。其中对于部分限时特购的商品,由于exHash类型可以为Field设置过期时间,其过期时间可通过hset命令直接设置。

      图4 exHash方案
      • 涉及命令如下:
        exhset User_N Product_N ex Time_N # 设置指定用户购物车中指定商品的数量和过期时间
        exhincrby User_N Product_N [Number] keepttl # 增加指定用户购物车中的指定商品数量,保留原先过期时间exhget  User_N Product_N # 获取指定用户购物车中指定商品的信息
        exhgetall User_N # 获取指定用户的所有商品信息
        exhlen User_N # 获取指定用户购物车中的总商品数量
        exhdel User_N Product_N # 删除指定用户购物车中的指定商品
        del User_N # 清空指定用户的购物车
      • 该方案相对于Hash类型的优化主要体现在可以直接为各field设置过期时间,使业务侧使用起来简单又高效。可以看到exHash类型相关的命令和Hash类型是类似的,使用起来学习成本很低,业务侧改造成本相对也比较低。
support.huaweicloud.com/redisug-nosql/nosql_01_0001.html