推荐缓存服务

日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)


5.6 推荐缓存服务

学习目标

  • 目标
  • 应用

5.6.1 待推荐结果的redis缓存

  • 目的:对待推荐结果进行二级缓存,多级缓存减少数据库读取压力
  • 缓存存储:redis:'reco:{}:{}art' ,对应某个用户,某个频道的缓存结果
  • 步骤:
    • 1、获取redis结果,进行判断
      • 如果redis有,读取需要推荐的文章数量放回,并删除这些文章,并且放入推荐历史推荐结果中
      • 如果redis当中不存在,则从wait_recommend中读取
        • 如果wait_recommend中也没有,直接返回
        • 如果wait_recommend有,从wait_recommend取出所有结果,定一个数量(如100篇)存入redis,剩下放回wait_recommend,不够100,全部放入redis,然后清空wait_recommend
        • 从redis中拿出要推荐的文章结果,然后放入历史推荐结果中

增加一个缓存数据库

# 缓存在8号当中
cache_client = redis.StrictRedis(host=DefaultConfig.REDIS_HOST,
                                 port=DefaultConfig.REDIS_PORT,
                                 db=8,
                                 decode_responses=True)

1、redis 8 号数据库读取

# 1、直接去redis拿取对应的键,如果为空
 # - 首先从获取redis结果,进行判断(缓存拿)
    key = 'reco:{}:{}:art'.format(temp.user_id, temp.channel_id)
    res = cache_client.zrevrange(key, 0, temp.article_num - 1)
    # - 如果redis有,读取需要推荐的文章数量放回,并删除这些文章,并且放入推荐历史推荐结果中
    if res:
        cache_client.zrem(key, *res)

2、redis没有数据,进行wait_recommend读取,放入redis中

# - 如果redis当中不存在,则从wait_recommend中读取
        # 删除redis这个键
        cache_client.delete(key)
        try:
            # 字符串编程列表
            hbase_cache = eval(hbu.get_table_row('wait_recommend',
                                                 'reco:{}'.format(temp.user_id).encode(),
                                                 'channel:{}'.format(temp.channel_id).encode()))

        except Exception as e:
            logger.warning("{} WARN read user_id:{} wait_recommend exception:{} not exist".format(
                datetime.now().strftime('%Y-%m-%d %H:%M:%S'), temp.user_id, e))

            hbase_cache = []
        if not hbase_cache:
            #   - 如果wait_recommend中也没有,直接返回空,去进行一次召回读取、排序然后推荐
            return hbase_cache
        #   - wait_recommend有,从wait_recommend取出所有结果,定一个数量(如100篇)的文章存入redis
        if len(hbase_cache) > 100:
            logger.info(
                "{} INFO reduce user_id:{} channel:{} wait_recommend data".format(
                    datetime.now().strftime('%Y-%m-%d %H:%M:%S'), temp.user_id, temp.channel_id))
            # 拿出固定数量(100)给redis
            cache_redis = hbase_cache[:100]
            # 放入redis缓存
            cache_client.zadd(key, dict(zip(cache_redis, range(len(cache_redis)))))
            # 剩下的放回wait hbase结果
            hbu.get_table_put('wait_recommend',
                              'reco:{}'.format(temp.user_id).encode(),
                              'channel:{}'.format(temp.channel_id).encode(),
                              str(hbase_cache[100:]).encode())
        else:
            logger.info(
                "{} INFO delete user_id:{} channel:{} wait_recommend data".format(
                    datetime.now().strftime('%Y-%m-%d %H:%M:%S'), temp.user_id, temp.channel_id))
            # - wait_recommend不够一定数量,全部取出放入redis当中,直接推荐出去
            # 清空wait_recommend
            hbu.get_table_put('wait_recommend',
                              'reco:{}'.format(temp.user_id).encode(),
                              'channel:{}'.format(temp.channel_id).encode(),
                              str([]).encode())

            # 放入redis缓存
            cache_client.zadd(key, dict(zip(hbase_cache, range(len(hbase_cache)))))

        res = cache_client.zrevrange(key, 0, temp.article_num - 1)
        if res:
            cache_client.zrem(key, *res)

3、推荐出去的结果放入历史结果

# 进行类型转换
    res = list(map(int, res))
    logger.info("{} INFO get cache data and store user_id:{} channel:{} cache history data".format(
        datetime.now().strftime('%Y-%m-%d %H:%M:%S'), temp.user_id, temp.channel_id))

    # 放入历史记录
    hbu.get_table_put('history_recommend',
                      'reco:his:{}'.format(temp.user_id).encode(),
                      'channel:{}'.format(temp.channel_id).encode(),
                      str(res).encode(),
                      timestamp=temp.time_stamp)
    return res

完整逻辑代码:

from server import cache_client
import logging
from datetime import datetime

logger = logging.getLogger('recommend')


def get_cache_from_redis_hbase(temp, hbu):
    """
    进行用户频道推荐缓存结果的读取
    :param temp: 用户请求的参数
    :param hbu: hbase工具
    :return:
    """

    # - 首先从获取redis结果,进行判断(缓存拿)
    key = 'reco:{}:{}:art'.format(temp.user_id, temp.channel_id)
    res = cache_client.zrevrange(key, 0, temp.article_num - 1)
    # - 如果redis有,读取需要推荐的文章数量放回,并删除这些文章,并且放入推荐历史推荐结果中
    if res:
        cache_client.zrem(key, *res)
    else:
        # - 如果redis当中不存在,则从wait_recommend中读取
        # 删除redis这个键
        cache_client.delete(key)
        try:
            # 字符串编程列表
            hbase_cache = eval(hbu.get_table_row('wait_recommend',
                                                 'reco:{}'.format(temp.user_id).encode(),
                                                 'channel:{}'.format(temp.channel_id).encode()))

        except Exception as e:
            logger.warning("{} WARN read user_id:{} wait_recommend exception:{} not exist".format(
                datetime.now().strftime('%Y-%m-%d %H:%M:%S'), temp.user_id, e))

            hbase_cache = []
        if not hbase_cache:
            #   - 如果wait_recommend中也没有,直接返回空,去进行一次召回读取、排序然后推荐
            return hbase_cache
        #   - wait_recommend有,从wait_recommend取出所有结果,定一个数量(如100篇)的文章存入redis
        if len(hbase_cache) > 100:
            logger.info(
                "{} INFO reduce user_id:{} channel:{} wait_recommend data".format(
                    datetime.now().strftime('%Y-%m-%d %H:%M:%S'), temp.user_id, temp.channel_id))
            # 拿出固定数量(100)给redis
            cache_redis = hbase_cache[:100]
            # 放入redis缓存
            cache_client.zadd(key, dict(zip(cache_redis, range(len(cache_redis)))))
            # 剩下的放回wait hbase结果
            hbu.get_table_put('wait_recommend',
                              'reco:{}'.format(temp.user_id).encode(),
                              'channel:{}'.format(temp.channel_id).encode(),
                              str(hbase_cache[100:]).encode())
        else:
            logger.info(
                "{} INFO delete user_id:{} channel:{} wait_recommend data".format(
                    datetime.now().strftime('%Y-%m-%d %H:%M:%S'), temp.user_id, temp.channel_id))
            # - wait_recommend不够一定数量,全部取出放入redis当中,直接推荐出去
            # 清空wait_recommend
            hbu.get_table_put('wait_recommend',
                              'reco:{}'.format(temp.user_id).encode(),
                              'channel:{}'.format(temp.channel_id).encode(),
                              str([]).encode())

            # 放入redis缓存
            cache_client.zadd(key, dict(zip(hbase_cache, range(len(hbase_cache)))))

        res = cache_client.zrevrange(key, 0, temp.article_num - 1)
        if res:
            cache_client.zrem(key, *res)

    # 进行执行PL,然后写入历史推荐结果
    # 进行类型转换
    res = list(map(int, res))
    logger.info("{} INFO get cache data and store user_id:{} channel:{} cache history data".format(
        datetime.now().strftime('%Y-%m-%d %H:%M:%S'), temp.user_id, temp.channel_id))

    # 放入历史记录
    hbu.get_table_put('history_recommend',
                      'reco:his:{}'.format(temp.user_id).encode(),
                      'channel:{}'.format(temp.channel_id).encode(),
                      str(res).encode(),
                      timestamp=temp.time_stamp)

    return res

5.6.2 在推荐中心加入缓存逻辑

  • from server import redis_cache
# 1、获取缓存
res = redis_cache.get_reco_from_cache(temp, self.hbu)

# 如果没有,然后走一遍算法推荐 召回+排序,同时写入到hbase待推荐结果列表
 if not res:
     logger.info("{} INFO get user_id:{} channel:{} recall/sort data".
                 format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), temp.user_id, temp.channel_id))

     res = self.user_reco_list(temp)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

あずにゃん

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值