阐述背景

缓存是应对高并发绝对的利器,在很多业务场景允许的情况下,都可以使用缓存来提供性能。

既然用了缓存,那对缓存进行监控必不可少。比如缓存加载耗时,新增耗时等。

在 JetCache 中进行埋点操作,对于 Redis 的缓存没有问题,埋点之后的 Key 是完整的,完整的也就是 Cache 的 name+key,如下图:

除了对 Redis 的缓存做埋点,还对本地 缓存 Caffeine 也做了埋点操作,然后发现 Caffeine 的埋点有问题,问题在于 Cache 的 name 丢失了,如下图:

然后去官方的钉钉群了问了下维护人员,让我升级版本。然后我升级到最新的 2.6.0 还是不行,这不是坑我么 !

找出原因

正所谓自己动手,丰衣足食。直接看代码吧,首先看 Redis 为何 Cache name 没有丢失,原因是 Redis 的 Config 中有 keyPrefix,如下图:

然后在对 Redis 进行操作的时候,会构建缓存的 Key,构建 Key 的时候会带上 keyPrefix,所以 Redis 的 Key 是正常的。

com.alicp.jetcache.external.AbstractExternalCache

public byte[] buildKey(K key) {
try {
Object newKey = key;
if (key instanceof byte[]) {
newKey = key;
} else if (key instanceof String) {
newKey = key;
} else if (this.config.getKeyConvertor() != null) {
newKey = this.config.getKeyConvertor().apply(key);
}
return ExternalKeyUtil.buildKeyAfterConvert(newKey, this.config.getKeyPrefix());
} catch (IOException var3) {
throw new CacheException(var3);
}
}

然后来看 Caffeine 的 config 中是没有 Keyprefix 的,如下图:

然后在构建缓存 Key 的时候,也就是没有 Keyprefix,所以问题就出在这里。

com.alicp.jetcache.embedded.AbstractEmbeddedCache

public Object buildKey(K key) {
if (key == null) {
return null;
} else {
Object newKey = key;
Function<K, Object> keyConvertor = this.config.getKeyConvertor();
if (keyConvertor != null) {
newKey = keyConvertor.apply(key);
}
return newKey;
}
}

RedisCacheConfig 继承了 ExternalCacheConfig,ExternalCacheConfig 继承了 CacheConfig。

keyPrefix 定义在 ExternalCacheConfig 中。

而 EmbeddedCacheConfig 只继承了 CacheConfig,所以它自然就没有 keyPrefix 字段。

解决方案

原因找出来了,想要解决肯定是可以的。问题是这是个开源的框架,不是自己公司内部的代码。不过也可以直接将源码克隆下来,进行改造,然后打包发布到自己的私服中去就可以了。

将 EmbeddedCacheConfig 也继承 ExternalCacheConfig 就可以将 keyPrefix 透传下去,然后在 buildKey 的地方进行拼接。

还有一种比较投机取巧的方案,可以不用改变配置类的关系,在 config 中有 monitors 这个信息,里面存放的是缓存的监控信息,主要是记录缓存对应的操作类型,GET, PUT 这种,然后就是每个操作的执行时间,操作次数等一些统计的信息,最终会有一个线程定时将这些信息输出到日志中。

所以我们可以通过获取 monitors 中的 cacheName 来临时解决这个问题。

private String getCacheName() {
List<CacheMonitor> monitors = config.getMonitors();
if (CollectionUtils.isEmpty(monitors)) {
return "";
}
DefaultCacheMonitor cacheMonitor = (DefaultCacheMonitor) monitors.get(0);
String cacheName = cacheMonitor.getCacheName();
return cacheName;
}

功能代码: https://github.com/yinjihuan/kitty

关于作者 :尹吉欢,简单的技术爱好者,《Spring Cloud 微服务-全栈技术与案例解析》, 《Spring Cloud 微服务 入门 实战与进阶》作者, 公众号 猿天地 发起人。个人微信 jihuan900 ,欢迎勾搭。

我整理了一份很全的学习资料,感兴趣的可以微信搜索 「猿天地 」,回复关键字 「学习资料 」获取我整理好了的Spring Cloud,Spring Cloud Alibaba,Sharding-JDBC分库分表,任务调度框架XXL-JOB,MongoDB,爬虫等相关资料。

JetCache埋点的骚操作,不服不行啊的更多相关文章

  1. Typescript骚操作,在TS里面直接插入HTML

    Typescript骚操作,在TS里面直接插入HTML,还有语法提示 先给大家看一个图 因为我不喜欢用很重的框架,主要是并非专业UI,但是偶尔会用到,还是觉得直接element组装受不了,想想能在ts ...

  2. 闪电侠 Netty 小册里的骚操作

    前言 即使这是一本小册,但基于"不提笔不读书"的理念,仍然有必要总结一下.此小册对于那些"硬杠 Netty 源码 却不曾在千万级生产环境上使用实操"的用户非常有 ...

  3. awk骚操作

    一.awk自加 [root@168web3 ~]# head /data/logs/cloud_monitor_rds_cpu.log |awk '{sum+=$NF}END{print sum}' ...

  4. 如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)

    0x01 问题提出 还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天我要给大家分享的是如 ...

  5. UOJ 117 欧拉回路(套圈法+欧拉回路路径输出+骚操作)

    题目链接:http://uoj.ac/problem/117 题目大意: 解题思路:先判断度数: 若G为有向图,欧拉回路的点的出度等于入度. 若G为无向图,欧拉回路的点的度数位偶数. 然后判断连通性, ...

  6. 关于map 及 map 骚操作

    关于map这个东西   很冷门..................   但是,这个博客带你稍微了解一下map:   map用法:一般当作一个下表无穷大的数组   关于它的骚操作:map的鬼畜用法,可以 ...

  7. 通过HTTP的HEADER完成各种骚操作

    作为一名专业的切图工程师,我从来不care网页的header,最多关心Status Code是不是200.但是HEADER真的很重要啊,客户端从服务器端获取内容,首先就是通过HEADER进行各种沟通! ...

  8. 洛谷 P1045 麦森数 (快速幂+高精度+算位数骚操作)

    这道题太精彩了! 我一开始想直接一波暴力算,然后叫上去只有50分,50分超时 然后我改成万位制提高运算效率,还是只有50分 然后我丧心病狂开long long用10的10次方作为一位,也就是100亿进 ...

  9. Mac OS 上的一些骚操作

    本帖记录个人在使用 Mac 操作系统上的一些骚操作,不断更新,以飨读者. 快速移动网页到顶部或底部 用双指上下划触摸板吗?NO,我们有更骚的操作: command + ↑ 回到顶部 command + ...

随机推荐

  1. 【Nginx】使用Nginx如何解决跨域问题?看完这篇原来很简单!!

    写在前面 当今互联网行业,大部分Web项目基本都是采用的前后端分离模式.前端为H5项目,后端为Java.PHP.Python等项目.而且大部分后端服务并不会只部署一套服务,而是会采用Nginx对后端服 ...

  2. Java继承多态

    一. 父类引用指向子类对象父类名(接口名) 对象名=new 子类(接口)名称() 二. 父子继承关系中,成员变量重名1.直接通过子类对象访问成员变量 =左边是谁,就优先用谁2.间接通过成员方法访问成员 ...

  3. C#和 JS的闭包

    闭包的概念是内层的函数可以引用包含在它外层的函数的变量,即使外层函数的执行已经终止.但该 变量提供的值并非变量创建时的值,而是在父函数范围内的最终值. C#闭包可理解为跨作用域访问函数内变量,那么如何 ...

  4. 题解 洛谷 P4112 【[HEOI2015]最短不公共子串】

    给定两个字符串\(A\)和\(B\),我们需要找出一个串,其在\(A\)中出现且不在\(B\)中出现,这个串为子串或者子序列,求在每种情况下,该串的最短长度. 考虑到后缀自动机可以识别一个字符串的所有 ...

  5. 拆招黑客!github代码库大牛们如何应对黑客攻击

    2019年05月,<个人电脑杂志>网站报道,GitHub(2018年被微软收购)代码库正遭到一名黑客的入侵(392个资源库受损,约1000名用户受到攻击,真实资料未知).据称,这名黑客先擦 ...

  6. Supervisor通用配置

    1.简介 supervisor是python开发的一个进程管理工具,可以将一个普通的命令行进程变为后台的守护进程,并且监控进程的运行状态,如果因为异常退出的时候会自动重启.它是通过fork/exec的 ...

  7. 黎曼函数ζ(2n)的几种求法

    \(\zeta (2n)\)的几种求法 目录 $\zeta (2n)$的几种求法 结论 欧拉的证明 进一步探索,$\zeta$ 函数.余切.伯努利数的关系 傅立叶分析证明 留数法证明 参考资料 结论 ...

  8. 利用updatexml()报错注入mysql

    基本介绍一下updatexml() updatexml(XML_document, XPath_string, new_value) XML_document是文档对象的名称 XPath_string ...

  9. 手写IOC容器

    IOC(控制翻转)是程序设计的一种思想,其本质就是上端对象不能直接依赖于下端对象,要是依赖的话就要通过抽象来依赖.这是什么意思呢?意思就是上端对象如BLL层中,需要调用下端对象的DAL层时不能直接调用 ...

  10. Python学习手册第4版 中文PDF版|网盘下载内附地址

    本书是学习Python编程语言的入门书籍.Python是一种很流行的开源编程语言,可以在各种领域中用于编写独立的程序和脚本.Python免费.可移植.功能强大,而且使用起来相当容易.来自软件产业各个角 ...