Nresource服务之接口缓存化
1、 背景
Nresource服务日均4.5亿流量,考虑到未来流量急增场景,我们打算对大流量接口进行缓存化处理;根据服务管理平台数据统计显示getUsableResoureCount接口调用量很大,接近40%,故对此接口进行缓存化处理。

2、 方案调研
getUsableResoureCount接口用途:获取用户的可用资源数,契约为:Map<String, Integer> getUsableResoureCount(long userId, int resourceType, ResourceCountTypeEnum typeEnum, List<Integer> cities, List<Integer> caties) throws Exception;支持传入资源数类型(全国/本地)多城市和多类目按照包含的策略进行资源过滤;
由于资源库存表设计字段:城市和类目写入格式为:1,2,3,即以逗号组合的字符串,所以如果缓存用户对应城市和类目的所有余量,实现难度大且意义不大。
通过对接口返回值的观察,我们发现getUsableResoureCount接口返回值很多都是查询用户所有资源余量,不区分城市和类目,且查询结果都为0,所以我们切换思路:是不是可以把这些无余量的数据缓存起来?
通过2021-07-27 10:00:00数据统计我们发现,单节点一分钟getUsableResoureCount接口调用量为395,其中查询所有资源余量的微287,返回值为0的为183,接近46%的请求是无数据的,所以缓存用户无余量的数据是有意义的,能挡住接近50%的无用请求。
缓存用户无余量的数据,我们需要在所有涉及余量增减的操作,同时维护redis中余量变化,如何维护db与缓存中数据的一致性,也是面临的问题,所以我们想:可不可以不缓存余量,只缓存一个余量标识,这样既能挡住无用请求,又不需要维护db与缓存的数据一致性呢?参考布隆过滤器,我们决定对此接口进行缓存余量标识,只记录有还是没有,即1和0。
3、 方案实施
getUsableResoureCount接口先查询缓存,如果返回值为0,则放入缓存,所有增加余量的操作均需要更新redis标识为1。基本目标就是:保证更新标识为有的操作一定成功。考虑到服务并发,写操作(更新redis标识为1)可能会被读操作(更新redis标识为0)覆盖,所以更新redis标识为0的时候,先增加时间校验即晚一分钟更新,因为redis标识更新为0或null,不会影响最终查询,而是会查询db,晚一分钟又可以避免读写覆盖的问题。最终采用lua脚本实现读操作,而写操作采用同步set异步重试保证最终成功;
lua脚本如下:

4、最终效果
接口响应耗时:
2021.9.2 VS 2021.9.9

2021.9.8 VS 2021.9.9

性能提升(ms):1.4 -> 0.9 提升超过30%
整体服务响应耗时:
2021.9.8 VS 2021.9.9

性能提升(ms):1.8 -> 1.6 提升超过10%
缓存命中率统计:
服务节点:10.***.60.***

命中率接近80%
5、未来考量
1)缓存的扩展性,未来新的写接口需要更新redis标识为1;
2)缓存的接口适配性,考虑更多查询接口应用缓存;
ps: 整体思路,由于业务原因,没有采用传统缓存用redis存有效数据的思路,我们是反其道行之,用redis来挡住无效流量
Nresource服务之接口缓存化的更多相关文章
- java接口入参模板化,适用于企业化服务远程调度模板化的场景,接口入参实现高度可配置化
需求:远程服务接口模板化配置提供接入服务 模板接口分为三个模块:功能路由.参数校验.模板入库 路由:这里的实现方式很简单,就是根据业务标识找到对应的处理方法 参数校验: 参数校验这步涉及模板和校验类两 ...
- 唯品会RPC服务框架与容器化演进--转
原文地址:http://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=405781868&idx=1&sn=cbb10d37e25 ...
- vue服务端渲染缓存应用
vue缓存分为页面缓存.组建缓存.接口缓存,这里我主要说到了页面缓存和组建缓存 页面缓存: 在server.js中设置 const LRU = require('lru-cache') const m ...
- 在 WPF 客户端实现 AOP 和接口缓存
随着业务越来越复杂,最近决定把一些频繁查询但是数据不会怎么变更的接口做一下缓存,这种功能一般用 AOP 就能实现了,找了一下客户端又没现成的直接可以用,嗐,就只能自己开发了. 代理模式和AOP 理解代 ...
- .NET实现微博粉丝服务平台接口
[文章摘要]Senparc.Weixin.MP虽然是微信公众号的SDK,但由于易信公众号和新浪微博粉丝服务平台也提供了微信兼容接口,所以也可以使用其快速实现相应的服务,当然微博由于与微信存在差异,如果 ...
- 戏说WSGI(Python Web服务网关接口)--[转载]
戏说WSGI(Python Web服务网关接口) 当你在Python的世界中冒险,突然遭遇一只Web怪兽,你会选择什么武器对付它?在兵器谱上,下列兵器可谓名列前茅: Zope,厚重的长枪.较早出现的武 ...
- Axis2创建WebService服务端接口+SoupUI以及Client端demo测试调用
第一步:引入axis2相关jar包,如果是pom项目,直接在pom文件中引入依赖就好 <dependency> <groupId>org.apache.axis2</gr ...
- Spring Cloud开发实践 - 02 - Eureka服务和接口定义
服务注册 EurekaServer Eureka服务模块只有三个文件, 分别是pom.xml, application.yml 和 EurekaServerApplication.java, 内容如下 ...
- 接口缓存--把接口放在redis数据库中,减少访问量
针对访问量大,且数据较固定的接口,建议建立接口缓存,建立了缓存之后,不会再直接去访问接口了. 比如下面的轮播图接口,每刷新一下首页都会访问一下轮播图接口,所以我们用接口缓存来处理,减少访问量. 视图模 ...
随机推荐
- bootstrap导航条报错 Uncaught TypeError: Cannot convert object to primitive value
原文: https://feiffy.cc/uncaught-typeerror-cannot-convert-object-to-primitive-value 最近发现我的博客页面移动端上下拉菜单 ...
- 查询liunx上磁盘占用情况
查询挂载盘磁盘情况 df -h 查询指定目录下的文件夹内存占用情况 du -hs /*
- 接口和包--Java学习笔记
接口 定义及基础用法 interface定义:没有字段的抽象类 interface person{ void hello(); String getName(); } /*接口本质上就是抽象类 abs ...
- 服务器程序动态加载自定义jar包的过程
需求: 用过hive的都知道,可以自定义hive的一个udf jar,然后将这个jar add到hive服务端,就会加载这个jar实现用户自定义逻辑.现在的需求就是实现这么一个服务端所做的事情! 场景 ...
- Python - 面向对象编程 - 实例方法、静态方法、类方法
实例方法 在类中定义的方法默认都是实例方法,前面几篇文章已经大量使用到实例方法 实例方法栗子 class PoloBlog: def __init__(self, name, age): print( ...
- The First Week luckyzpp
一 ,LINUX系列有很多版本,只是我们很少去了解到更多,我们熟知红帽CentOS,Ubuntu,Debian, Kali, Rocky各种版本系列. 二 目前Linux 生产主流版本如下: C ...
- redis百万级数据存取
Jedis jedis0 = new Jedis("localhost", 6379); jedis0.auth("123456"); Pipeline pip ...
- IT项目经理-成长手记学习笔记
无论多难,都要记住一点,只要别人不赶你走,你就厚着脸皮待下去,这样你才有可能熬到项目成功. 项目经理要管事,更要管人. 项目计划->职责分工->确定项目范围 遇事及时处理,当场处理,处理错 ...
- Learning ROS: Ubuntu16.04下kinetic开发环境安装和初体验 Install + Configure + Navigating(look around) + Creating a Package(catkin_create_pkg) + Building a Package(catkin_make) + Understanding Nodes
本文主要部分来源于ROS官网的Tutorials. Ubuntu install of ROS Kinetic # Setup your sources.list sudo sh -c 'echo & ...
- 分布式系列-分布式ID
一.数据库自增(单实例) 1.方案描述 基于数据库自增ID(auto_increment)利用其来充当分布式ID.实现方式就是用一张表来充当ID生成器,当我们需要ID时,向表中插入一条记录返回主键ID ...