INDEX
- 通用设计概述
- §2 优势
- §3 最佳实践
通用设计概述
通用设计思路如下图
内容分发网络(CDN)
可以理解为一些服务器的副本,这些副本服务器可以广泛的部署在服务器提供服务的区域内,并存有服务器中的一些数据。
用户访问原始服务器时,其中的静态资源(比如banner图片、图标、js脚本、css文件、静态页面等)会由 CDN 分发到距离用户较近的副本服务器上并返回对应内容,加速访问效率
原始请求经过 CDN 后,会自动按请求内容分发至距离合适的副本服务器或原始服务器
OpenResty
OpenResty,附 官网,是一个基于 Nginx + Lua 实现的服务端开发平台。
其目的旨在在合适的情况下跳过服务,直接访问服务对应的资源本身
JVM 进程缓存(caffeine)
服务级缓存(Redis)
数据持久层
§2 优势
- 分担缓存压力
- 进程缓存相对于分布式缓存,节省了网络io的开销,速度更快
- 使用时,可以减少访问redis的频率,从根源上避免缓存的穿透、击穿、雪崩
- 可用性更强,即使进程缓存、分布式缓存之一不可用,也不会导致整体缓存失效,可以争取服务恢复时间
§3 最佳实践
最佳实践
- 使用 caffeine + redis + mysql 搭建二级缓存
- 自定义缓存控制器
CacheManager
- 增设监听 redis 失效 key
- 支持断线重连
自定义缓存控制器 & redis 监听
示例代码
//缓存管理器
public class CacheManager{//redisprivate CacheFrontend cf;//香菜连接池private RedisClient rc;//本地缓存private Cache lc;//redis 连接栈StatefulRedisConnection<String,String> connection;//监听 redis 失效 key//连接正常时,通过 lisenter 监听redis事件,当事件为失效时同步清理本地缓存public void check(){if(connection != null && connection.isOpen)return ;try{connection = rc.connect();cf= ClientSideCaching.enable(new CaffeineCacheAccessor(lc),connection,TrackingArgs.Builder.enabled());connection.addListener(msg->{List<Object> content = msg.getContent(StringCodec.UTF8::decodeKey);//日志输出if(msg.getType().equalsIgnoreCase("invalidate")){List<String> keys = (List<String>)content.get(1);keys.forEach(k->lc.invalidate(k));}});}catch(){//略}}
}//本地缓存访问器
//代理 caffeine client,使之实现香菜连接池中 CacheAccessor 接口
public class CaffeineCacheAccessor implements CacheAccessor{private Cache lc;//本地缓存客户端,这里可以是 caffeine//示例方法,其他方法同样public Object get(Object key){return lc.getIfPresent(key);}
}//心跳检测
@Bean
public CommandLimeRunner init(CacheManager cm){return new CommandLineRunner(){public void run(String... args) throws Exception{while(true){cm.check();TimeUnit.SECONDS.sleep(5);}}}
}