redis怎么实现页面实时更新自动上线

需求描述

某些页面需要配置广告或活动宣传图,广告或活动需满足随时上下线、过期自动下线及到时自动上线。

如:现在时间2019-2-22 16:16:13,要在支付完成页面配置领奖活动,活动要在2019-3-10 00:00:00准时上线,在2019-3-30 23:59:59结束活动。

因此,期望实现的效果是在活动上线前的任何时间配置完活动后,页面会在指定时间自动上线该活动。也可能会是其他的多个活动或广告,每个页面广告的个数可变,不同上下线时间可不同,其他页面也需要实现这样的功能,页面与页面之间的活动不一定一样。

需求分析

需求简单的几句话,那么我们来具体的分析一下。

提取关键词

广告或活动宣传图

随时上下线、过期自动下线及到时自动上线

每个页面广告的个数可变

不同广告上下线时间可不同

页面与页面之间的活动不一定一样

数据库分析

1、【广告或活动宣传图】

要为不同页面设置不同的广告,有的页面广告可能一样,也就是广告会复用,所有要有广告表。

2、【每个页面广告的个数可变】【不同广告上下线时间可不同】【页面与页面之间的活动不一定一样】

页面可配置多个广告,所有要有页面配置表,以及广告和页面的关系表,即页面广告表。

页面配置表主要配置页面的广告个数,实现【每个页面广告的个数可变】,页面广告表主要配置页面的每个广告上下线时间,实现【不同广告上下线时间可不同】

根据简单的分析,我得出以下表格构造:广告表(adv),页面配置表(page_config)和页面广告表(page_adv)

redis怎么实现页面实时更新自动上线

思考

这些页面配置的广告在一段时间内是不会变的,如果页面请求次数较多,广告查询次数就会很频繁,对数据库造成不必要的压力。所以可以引入缓存,降低数据库请求次数,缓解数据库压力。这里使用的Redis。

何时入缓存?

可以选择在服务启动时异步把已在上下线时间区间内的广告先加载至缓存,或选择在请求时取缓存,缓存内没有时再查库然后放缓存。缓存时间视情况而定。

这里选择的是,项目启动时异步把符合条件的页面广告配置信息存入Redis,那些还没到指定时间的先不放Redis,等到访问页面加载广告时,先查Redis,若无则按条件(>=nowtime)查库,查到后存Redis。

在接口中拿到广告配置信息后,判断当前时间是否在配置的时间区间内,由于一个页面配置多个广告,不同广告时间也不同,所以要迭代,把符合的返回,有过期的就做标记,然后把整个页面的配置信息在Redis里删除。(或者不选择在启动时加载,就在用户请求时加入缓存,但是下面的第1步的方法在刷新加载时会用到,故不能删)

具体实现

第1步、项目启动时先把页面广告配置信息存入Redis

a、查询所有pageId

SELECT pageId FROM page_config page_adv WHERE nowtime<=endtime AND GROUP BY pageId

登录后复制

两个表内连接,得List,得到的都是配置的有广告的并且广告还没过期的pageId。

b、查询pegeId对应的广告图片及跳转链接

SELECT 字段名 FROM page_adv adv WHERE begintime<=nowtime<=endtime AND pageId={#pageId}

登录后复制

然后把查到的配置信息List(为空时不做操作),以pageId为KEY放入缓存。

第2步、给前端写接口查询页面广告

按标准的控制层,业务层,数据访问层写,第一步中的逻辑就是在业务层完成的。

控制层:

控制层接参pageId,调用业务层查询对应页面配置的广告信息,判空,直接返回状态码0,即无广告前端不展示。

不为空就根据业务逻辑处理数据(如img的URL加域名),然后返回状态码1,前端展示广告。这里控制层还可以加逻辑,迭代广告list,把当前时间在广告起始时间内的返回,不在的不返回,并且只要有一个广告过期,就把这个页面的广告list缓存清掉。这个逻辑是把过期的清掉。

业务层:

先取缓存,没有再查库判断不为空(本页面配置的有广告),放入缓存(pageId为KEY),然后返回。

数据访问层:

SQL:

SELECT 字段名 FROM page_config adv page_adv WHERE begintime<=nowtime<=endtime AND pageId=#{pageId}

登录后复制

三表联查,根据pageId查询当前页面配置的广告活动信息(已在广告活动时间内)

第3步、刷新加载

为什么使用刷新加载?

因为有这样的场景:给页面A配置了一个广告(当前时间在广告的起始时间内),那么这个页面的广告已经在缓存里了,假如此时A页面要新加一个广告,在后台配置后如果不做其他操作,这个广告不会显示(假设缓存时间较长,为一天),因为库更新了,缓存没有同步更新。

解决方案

使用Redis的发布订阅机制实现缓存的刷新加载,使新配置的广告及时能够显示。刷新加载的回调方法即第1步中的方法。

进一步优化

想一想,目前的实现存在什么问题?

存在的问题

假如有页面需要配置广告,但是还没有配(前端已经开发完上线,每次都会调接口查广告信息),那么数据库肯定查不到,缓存也没有。如果这个页面访问量很大,那么缓存没命中就查库,这样对库的压力就会很大,这就是缓存穿透,请求上来了很容易击垮数据库。那怎么办呢?

解决方案

当页面没有配置广告时,在缓存存标志,查询时先看标志,在决定是否往下走。

具体方案

这时,上面的第1步就要改了。

1、首先改第1步的步骤a的SQL,把所有的pageId都查询出来。

使用左连接

SELECT pageId FROM page_config LEFT JOIN page_adv ON ...  GROUP BY pageId

登录后复制

或者干脆查page_config

SELECT pageId FROM page_config

登录后复制

目的是把已在page_config表中配置,但关系表中page_adv未配置广告的pageId也查出来,这样才能给未配置广告的pageId在缓存里放标志

2、第1步的步骤b的SQL改为

SELECT 字段名 FROM page_adv adv WHERE nowtime<=endtime AND pageId={#pageId}

登录后复制

然后把查到的配置信息放入缓存之前判断【为空时的不做操作】改为【为空时存入一个标志】假如这个标志KEY为pageId+”_EMPTY_FLAG”,value为”DB_IS_NULL”

为什么只判断小于结束时间

因为如果该页面配置的广告开始时间大于当前时间,那么这个是查不到的,会被处理为DATABASE_IS_NULL,如果在这个标志还没失效之前就到了配置的开始时间了,那么这个广告不会被展示。所有要让未到开始时间的也放入缓存,然后让控制层去判断在不在时间区间。

3、所以要在第2步也修改一下

在业务层里取缓存中的广告列表之前,先从缓存取pageId+”EMPTY_FLAG”的value判断为”DB_IS_NULL”直接返回空,这样就能避免缓存穿透的问题了。

继续修改第2步的业务层,查库的SQL同样要改:

SELECT 字段名 FROM page_config adv page_adv WHERE nowtime<=endtime AND pageId=#{pageId}

登录后复制

然后判断为空的话,同上面的黄字那样处理。

4、最后,第3步的刷新加载调的是第1步的方法,不用改。

当然这个缓存穿透的优化方案只是其中一种。还可以这样:

1、控制层拦截:根据pageId查询page_adv表,查不到说明没配置,直接返回。

2、page_config 表增加字段,表示当前页面已经配置的广告个数,默认0,每配置一个该字段加1,把大于0的pageId缓存起来,调接口时前判断在不在缓存里。

以上就是redis怎么实现页面实时更新自动上线的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2030689.html

(0)
上一篇 2025年2月23日 21:56:53
下一篇 2025年2月23日 21:57:10

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • redis使用实例分析

    第一part:原生jedis连接redis 首先我们为要先了解,我们在原先使用mysql的时候,用jdbc连接数据库。同理这里我们连接redis,就要使用jedis。 第一步:新建java项目,导包 新建java项目,导包     redi…

    2025年2月23日 数据库
    100
  • Python Redis数据处理的方法

    1. 前言 Redis:Remote Dictionary Server,即:远程字典服务,Redis 底层使用 C 语言编写,是一款开源的、基于内存的 NoSql 数据库 由于 Redis 性能远超其他数据库,并且支持集群、分布式及主从同…

    2025年2月23日
    100
  • 宝塔中ThinkPHP框架使用Redis的方法是什么

    redis是一种常用的非关系型数据库,主要用作数据缓存,数据保存形式为key-value,键值相互映射。它的数据存储跟mysql不同,它数据存储在内存之中,所以数据读取相对而言很快,用来做高并发非常不错。 关于redis的安装,在服务器或者…

    2025年2月23日
    100
  • springboot连接不上redis怎么解决

    第一种 查看防火墙是否打开6379端口 查看防火墙状态 systemctl status firewalld 登录后复制 如果防火墙没有启动的话。可以选择直接看后面两种方法。 或者就是打开防火墙,然后继续下面的步骤: 开启端口 firewa…

    2025年2月23日
    100
  • redis延迟双删策略怎么使用

    通常情况下,我们会优先选择使用redis缓存来降低数据库访问负担。但是也会遇到以下这种情况:大量用户来访问我们系统,首先会去查询缓存, 如果缓存中没有数据,则去查询数据库,然后更新数据到缓存中,并且如果数据库中的数据发生了改变则需要同步到r…

    2025年2月23日
    100
  • Redis+SpringBoot案例分析

    一、项目环境 前端技术栈:vue-cli 前端软体:WebStorm 2020.3 前端样式: Bootstrap 后端技术栈:SpringBoot 后端软体:IntelliJ IEDA2019 JavaJDK:1.8 服务器:阿里云Cen…

    2025年2月23日 数据库
    100
  • SpringBoot整合Redis缓存如何实现

    SpringBoot支持的缓存组件 在SpringBoot中,数据的缓存管理存储依赖于Spring框架中cache相关的org.springframework.cache.Cache和org.springframework.cache.Ca…

    2025年2月23日 数据库
    100
  • 怎么用Redis实现搜索接口

    对于后端开发人员来讲使用一条sql就可以实现列表查询的接口,如果查询条件很复杂,表库设计不合理,会导致查询很困难,这篇文章和大家分享一下用redis实现搜索接口。 下面以一个例子开始,这是某购物网站的搜索条件,如果让你实现这样的一个搜索接口…

    2025年2月23日 数据库
    100
  • 如何使用Redis的streams

    起源 自从在 redis 4.0 引入模块后,用户开始思考如何解决这些问题。其中一个用户 timothy downs 通过 irc 和我说道: 我计划给这个模块增加一个事务日志式的数据类型 —— 这意味着大量的订阅者…

    数据库 2025年2月23日
    100
  • Redis持久化机制实现原理和流程是什么

    redis持久化机制实现原理是什么? 持久化:Redis是内存数据库,数据都是存储在内存中,为了避免进程退出导致数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现…

    数据库 2025年2月23日
    100

发表回复

登录后才能评论