当前位置:网站首页>Redis + Guava 本地缓存 API 组合,性能炸裂!
Redis + Guava 本地缓存 API 组合,性能炸裂!
2022-06-26 20:38:00 【Java精选】
前言
我们开发中经常用到 Redis 作为缓存,将高频数据放在 Redis 中能够提高业务性能,降低 MySQL 等关系型数据库压力,甚至一些系统使用 Redis 进行数据持久化,Redis 松散的文档结构非常适合业务系统开发,在精确查询,数据统计业务有着很大的优势。

但是高频数据流处理系统中,Redis 的压力也会很大,同时 I/O 开销才是耗时的主要原因,这时候为了降低 Redis 读写压力我们可以用到本地缓存,Guava 为我们提供了优秀的本地缓存 API,包含了过期策略等等,编码难度低,个人非常推荐。
设计示例
Redis 懒加载缓存
数据在新增到 MySQL 不进行缓存,在精确查找进行缓存,做到查询即缓存,不查询不缓存。
流程图如下:
代码示例:
// 伪代码示例 Xx代表你的的业务对象 如User Goods等等
public class XxLazyCache {
@Autowired
private RedisTemplate<String, Xx> redisTemplate;
@Autowired
private XxService xxService;// 你的业务service
/**
* 查询 通过查询缓存是否存在驱动缓存加载 建议在前置业务保证id对应数据是绝对存在于数据库中的
*/
public Xx getXx(int id) {
// 1.查询缓存里面有没有数据
Xx xxCache = getXxFromCache(id);
if(xxCache != null) {
return xxCache;// 卫语句使代码更有利于阅读
}
// 2.查询数据库获取数据 我们假定到业务这一步,传过来的id都在数据库中有对应数据
Xx xx = xxService.getXxById(id);
// 3.设置缓存、这一步相当于Redis缓存懒加载,下次再查询此id,则会走缓存
setXxFromCache(xx);
return xx;
}
}
/**
* 对xx数据进行修改或者删除操作 操作数据库成功后 删除缓存
* 删除请求 - 删除数据库数据 删除缓存
* 修改请求 - 更新数据库数据 删除缓存 下次在查询时候就会从数据库拉取新的数据到缓存中
*/
public void deleteXxFromCache(long id) {
String key = "Xx:" + xx.getId();
redisTemplate.delete(key);
}
private void setXxFromCache(Xx xx) {
String key = "Xx:" + xx.getId();
redisTemplate.opsForValue().set(key, xx);
}
private Xx getXxFromCache(int id) {
// 通过缓存前缀拼装唯一主键作为缓存Key 如Xxx信息 就是Xxx:id
String key = "Xx:" + id;
return redisTemplate.opsForValue().get(key);
}
}
// 业务类
public class XxServie {
@Autowired
private XxLazyCache xxLazyCache;
// 查询数据库
public Xx getXxById(long id) {
// 省略实现
return xx;
}
public void updateXx(Xx xx) {
// 更新MySQL数据 省略
// 删除缓存
xxLazyCache.deleteXxFromCache(xx.getId());
}
public void deleteXx(long id) {
// 删除MySQL数据 省略
// 删除缓存
xxLazyCache.deleteXxFromCache(xx.getId());
}
}
// 实体类
@Data
public class Xx {
// 业务主键
private Long id;
// ...省略
}优点如下:
保证最小的缓存量满足精确查询业务,避免冷数据占用宝贵的内存空间
对增删改查业务入侵小、删除即同步
可插拔,对于老系统升级,历史数据无需在启动时初始化缓存
缺点如下:
数据量需可控,在无限增长业务场景不适用
在微服务场景不利于全局缓存应用
总结:
空间最小化
满足精确查询场景
总数据量可控推荐使用
微服务场景不适用
Redis 结合本地缓存
微服务场景下,多个微服务使用一个大缓存,流数据业务下,高频读取缓存对 Redis 压力很大,我们使用本地缓存结合 Redis 缓存使用,降低 Redis 压力,同时本地缓存没有连接开销,性能更优。
流程图如下:

业务场景:在流处数处理过程中,微服务对多个设备上传的数据进行处理,每个设备有一个 code,流数据的频率高,在消息队列发送过程中使用分区发送,我们需要为设备 code 生成对应的自增号,用自增号对 kafka 中 topic 分区数进行取模。
这样如果有 10000 台设备,自增号就是 0~9999,在取模后就进行分区发送就可以做到每个分区均匀分布。
这个自增号我们使用 redis 的自增数生成,生成后放到 redis 的 hash 结构进行缓存,每次来一个设备,我们就去这个 hash 缓存中取,没有取到就使用自增数生成一个,然后放到 redis 的 hash 缓存中。
这时候每个设备的自增数一经生成是不会再发生改变的,我们就想到使用本地缓存进行优化,避免高频的调用 redis 去获取,降低 redis 压力。
代码示例:
/**
* 此缓存演示如何结合redis自增数 hash 本地缓存使用进行设备自增数的生成、缓存、本地缓存
* 本地缓存使用Guava Cache
*/
public class DeviceIncCache {
/**
* 本地缓存
*/
private Cache<String, Integer> localCache = CacheBuilder.newBuilder()
.concurrencyLevel(16) // 并发级别
.initialCapacity(1000) // 初始容量
.maximumSize(10000) // 缓存最大长度
.expireAfterAccess(1, TimeUnit.HOURS) // 缓存1小时没被使用就过期
.build();
@Autowired
private RedisTemplate<String, Integer> redisTemplate;
/**
* redis自增数缓存的key
*/
private static final String DEVICE_INC_COUNT = "device_inc_count";
/**
* redis设备编码对应自增数的hash缓存key
*/
private static final String DEVICE_INC_VALUE = "device_inc_value";
/**
* 获取设备自增数
*/
public int getInc(String deviceCode){
// 1.从本地缓存获取
Integer inc = localCache.get(deviceCode);
if(inc != null) {
return inc;
}
// 2.本地缓存未命中,从redis的hash缓存获取
inc = (Integer)redisTemplate.opsForHash().get(DEVICE_INC_VALUE, deviceCode);
// 3. redis的hash缓存中没有,说明是新设备,先为设备生成一个自增号
if(inc == null) {
inc = redisTemplate.opsForValue().increment(DEVICE_INC_COUNT).intValue;
// 添加到redis hash缓存
redisTemplate.opsForHash().put(DEVICE_INC_VALUE, deviceCode, inc);
}
// 4.添加到本地缓存
localCache.put(deviceCode, inc);
// 4.返回自增数
return inc;
}
}优点如下:
redis 保证数据可持久,本地缓存保证超高的读取性能,微服务共用 redis 大缓存的场景能有效降低 redis 压力
guava 作为本地缓存,提供了丰富的 api,过期策略,最大容量,保证服务内存可控,冷数据不会长期占据内存空间
服务重启导致的本地缓存清空不会影响业务进行。另外,公众号java精选,回复java面试,获取面试题资料。
微服务及分布式场景使用,分布式情况下每个服务实例只会缓存自己接入的那一部分设备的自增号,本地内存空间最优
在示例业务中,自增数满足了分布区发送的均匀分布需求,也可以满足统计设备接入数目的业务场景,一举两得
缺点如下:
增加编码复杂度,不直接
只适用于缓存内容只增不改的场景
总结:
本地缓存空间可控,过期策略优
适用于微服务及分布式场景
缓存内容不能发生改变
性能优
后记
redis 提供了丰富的数据类型及 api,非常适合业务系统开发,统计计数(increment,decrement),标记位(bitmap),松散数据(hash),先进先出、队列式读取(list)。
guava 缓存作为本地缓存,能够高效的读取的同时,提供了大量 api 方便我们控制本地缓存的数据量及冷数据淘汰。
作者:热黄油啤酒
https://juejin.cn/post/7000263632151904293
公众号“Java精选”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理!
最近有很多人问,有没有读者交流群!加入方式很简单,公众号Java精选,回复“加群”,即可入群!
Java精选面试题(微信小程序):3000+道面试题,包含Java基础、并发、JVM、线程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架构设计等,在线随时刷题!
------ 特别推荐 ------
特别推荐:专注分享最前沿的技术与资讯,为弯道超车做好准备及各种开源项目与高效率软件的公众号,「大咖笔记」,专注挖掘好东西,非常值得大家关注。点击下方公众号卡片关注。
文章有帮助的话,点在看,转发吧!
边栏推荐
- Good thing recommendation: mobile terminal development security tool
- Tiktok practice ~ search page ~ scan QR code
- swagger:如何生成漂亮的静态文档说明页
- Separate save file for debug symbols after strip
- MySQL stored procedure
- 与 MySQL 建立连接
- [Bayesian classification 3] semi naive Bayesian classifier
- 【最详细】最新最全Redis面试大全(42道)
- leetcode刷题:字符串04(颠倒字符串中的单词)
- 0基础学c语言(3)
猜你喜欢
![[Bayesian classification 4] Bayesian network](/img/5b/348e00c920028e33ca457196586d36.png)
[Bayesian classification 4] Bayesian network
![[serial] shuotou O & M monitoring system 01 overview of monitoring system](/img/b2/bc75a4d0c8d98056d93ba99b3e6193.png)
[serial] shuotou O & M monitoring system 01 overview of monitoring system

leetcode刷题:字符串03(剑指 Offer 05. 替换空格)

On the origin of the dispute between the tradition and the future of database -- AWS series column

好物推荐:移动端开发安全工具

Good thing recommendation: mobile terminal development security tool

回首望月

记录一次Redis大Key的排查

Looking back at the moon

论数据库的传统与未来之争之溯源溯本----AWS系列专栏
随机推荐
C primer plus learning notes - 3. Character IO (input / output)
Browser event loop
Stop being a giant baby
Development of NFT for digital collection platform
leetcode刷题:哈希表08 (四数之和)
Keep alive cache component in Vue
Gamefi active users, transaction volume, financing amount and new projects continue to decline. Can axie and stepn get rid of the death spiral? Where is the chain tour?
基于Qt实现的“合成大西瓜”小游戏
StringUtils判断字符串是否为空
Establish a connection with MySQL
Case description: the competition score management system needs to count the competition scores obtained by previous champions and record them in the file. The system has the following requirements: -
清华大学就光刻机发声,ASML立马加紧向中国出口光刻机
[most detailed] the latest and complete redis interview (70)
飞天+CIPU体为元宇宙带来更大想象空间
【山东大学】考研初试复试资料分享
0基础c语言(0)
[Bayesian classification 2] naive Bayesian classifier
云计算技术的发展与芯片处理器的关系
慕课11、微服务的用户认证与授权
Two methods of QT to realize timer
