目录前言设计示例Redis懒加载缓存流程图代码示例优点缺点总结Redis结合本地缓存流程图代码示例优点缺点总结后记前言 我们开发中经常用到Redis作为缓存,将高频数据放在Redis
数据在新增到mysql不进行缓存,在精确查找进行缓存,做到查询即缓存,不查询不缓存
// 伪代码示例 Xx代表你的的业务对象 如User Goods等等
public class XxLazyCache {
@Autowired
private RedisTemplate<String, Xx> redisTemplate;
@Autowired
private XxService xxService;// 你的业务service
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;
}
}
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压力,同时本地缓存没有连接开销,性能更优
在流处数处理过程中,微服务对多个设备上传的数据进行处理,每个设备有一个code,流数据的频率高,在消息队列发送过程中使用分区发送,我们需要为设备code生成对应的自增号,用自增号对kafka中topic分区数进行取模,这样如果有10000台设备,自增号就是0~9999,在取模后就进行分区发送就可以做到每个分区均匀分布,这个自增号我们使用redis的自增数生成,生成后放到redis的hash结构进行缓存,每次来一个设备,我们就去这个hash缓存中取,没有取到就使用自增数生成一个,然后放到redis的hash缓存中,这时候每个设备的自增数一经生成是不会再发生改变的,我们就想到使用本地缓存进行优化,避免高频的调用redis去获取,降低redis压力,下面链接为我写的关于kafka分区消费的文章,大家可以去看看 Kafka分区发送及消费实战
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;
private static final String DEVICE_INC_COUNT = "device_inc_count";
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提供了丰富的数据类型及api,非常适合业务系统开发,统计计数(increment,decrement),标记位(bitmap),松散数据(hash),先进先出、队列式读取(list);guava缓存作为本地缓存,能够高效的读取的同时,提供了大量api方便我们控制本地缓存的数据量及冷数据淘汰;我们充分的学习这些特性能够帮助我们在业务开发中更加轻松灵活,在空间与时间上找到一个平衡点。
到此这篇关于Redis与本地缓存的结合实现的文章就介绍到这了,更多相关Redis本地缓存内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: Redis与本地缓存的结合实现
本文链接: http://www.lsjlt.com/news/164213.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0