多级缓存
安装OpenResty
OpenResty是一个基于 Nginx的高性能 Web 平台,用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用Web 服务和动态网关。具备下列特点:
- 具备Nginx的完整功能
- 基于Lua语言进行扩展,集成了大量精良的Lua库,第三方模块
- 允许使用Lua自定义业务逻辑,自定义库
官方地址:https://openresty.org/cn/
- 在linux下安装
- 安装OpenResty的依赖开发库
yum install -y pcre-devel openssl-devel gcc --skip-broken
- 在centos中添加openresty仓库
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
- 安装openResty
yum install -y yum-utils
- 安装opm工具,是一个openresty的管理工具,可以帮助我们安装一个第三方的lua模块
yum instally openrest -y -opm
默认情况下 openResty的安装目录是/usr/local/openresty
配置nginx环境变量
-
打开配置文件
vim /etc/profile
-
在最下面添加
export NGINX_HOME=/usr/local/openresty/nginx
export PATH=${NGINX_HOME}/sbin:$PATH
-
让配置生效
source /etc/profile
-
启动
nginx
java
# 启动nginx
nginx
# 重新加载配置
nginx -s reload
# 停止
nginx -s stop
OpenResty入门
这里由代理一个访问路径为例子:
在windows端的nginx中进行
-
在nginx.conf的http下面,添加对OpenResty的Lua模块的加载:
-
在nginx.conf的server下面,添加对
/api/item
这个路径的监听:
-
Linux中niginx目录下创建lua文件夹,新建item.lua文件
创建内容:
-
重新加载配置
nginx -s reload
OpenResty获取请求参数
OpenResty提供了各种API用来获取不同类型的参数:
OpenResty向tomcat服务器发送请求
nginx提供了内部API请求用以发送http请求:
返回的响应内容包括:
resp.status:响应状态码
resp.header:响应头,是一个table
resp.body:响应体,就是响应数据
注意:这里的path是路径,并不包含IP和端口,这个请求会被nginx内部的server监听并处理,可以使用反向代理
我们可以把http查询的请求封装到一个函数中,放到OpenResty函数库中,方便以后使用
- 创建文件
/usr/local/openresty/lualib/common.lua
- 在文件中封装请求http查询的函数
如何使用这个封装函数,返回向tomcat请求的数据,在item.lua文件中
注意:Openresty提供了一个cjson的模块用来处理JSON的序列化和反序列化
地址:https://github.com/openresty/lua-cjson/
如何使用:
- 引入json模块
local cjson=require "cjson"
- 序列化:
反序列化:
在nginx与tomcat端之间添加redis缓存
- 冷启动和缓存预热
冷启动:服务刚刚启动时,Redis中并没有缓存,如果所有商品数据都在第一次查询时添加缓存,可能会给数据库带来较大压力。
缓存预热:在实际开发中,我们可以利用大数据统计用户访问的热点数据,在项目启动时将这些热点数据提前查询并保存到Redis中。
OpenResty提供了操作Redis的模块,只需要引入就能够使用
封装函数,用来释放Redis连接,放入连接池
封装函数,从Redis中读取数据并返回
Redis本地缓存
OpenResty为nginx提供了shard dict的功能,可以在nginx的多个worker之间共享数据,实现缓存功能
- 开启共享词典,在nginx.conf的http下添加配置:
- 操作共享词典
缓存同步
缓存同步策略
设置有效期:
给缓存设置有效期,到期后自动删除。再次查询时更新
优势:简单、方便
缺点:时效性差,缓存过期之前可能不一致
场景:更新频率较低,时效性要求低的业务
同步双写:
在修改数据库的同时,直接修改缓存
优势:时效性强,缓存与数据库强一致
缺点:有代码侵入,耦合度高;
场景:对一致性、时效性要求较高的缓存数据
异步通知:
修改数据库时发送事件通知,相关服务监听到通知后修改缓存数据
优势:低耦合,可以同时通知多个缓存服务
缺点:时效性一般,可能存在中间不一致状态
场景:时效性要求一般,有多个服务需要同步
基于Canal的异步通知
安装Canal
Canal是阿里巴巴旗下的开源项目,基于java开发,基于数据库增量日志解析,提供增量数据订阅&消费
地址:https://github.com/alibaba/canal
Canal是基于MySQL的主从同步来实现的,MySQL主从同步的原理如下:
MySOL master将数据变更写入二进制日志( binarylog)其中记录的数据叫binary log events
MySQLslave 将master的 binary log events拷贝到它的中继日志(relay log)
MySQL slave 重放 relay log 中事件,将数据变更反映它自己的数据
Canal就是把自己伪装成MVSOL的一个slave节点,从而监听master的binarylog变化。再把得到的变化信息通知给Canal的客户端,进而完成对其它数据库的同步。
安装:
-
首先创建一个网络,将MySQL,Canal,MQ放在同一个Docker网络中:
docker network create hhh
让mysql加入这个网络
docker network connect hhh mysql
-
将Canal镜像上传到虚拟机中,通过命令导入;
docker load -i canal.tar
-
运行创建Canal容器
docker run p 11111:11111 --name canal
-e canal.destinations=hhh
-e canal.instance.master.address=mysql:3306
-e canal.instance.dbUsername=canal
-e canal.instance.dbPassword=canal
-e canal.instance.connectionCharset=UTF-8
-e canal.instance.tsdb.enable=true
-e canal.instance.gtidon=false
-e canal.instance.filter.regex=hhh\...*
--network hhh
-d canal/canal-server:v1.1.5
Canal客户端
Canal提供了各种语言的客户端,当Canal监听到binlog变化时,会通知Canal的客户端。
第三方开源的canal-starter:地址:https://github.com/NormanGyllenhaal/canal-client
- 引入依赖
- 编写配置
yml
canal:
destination: hhh #要跟canal运行时设置的destination一致
server: 192.168.75.135:11111 #canal地址
- 编写监听器,监听canal消息
java
//Item是指定表的实体类
@CanalTable("表名")
@Component
public class ItemHandler implements EntryHandler<Item>{
@Override
public void insert(Item item){
//新增数据到redis中
//新增数据到JVM缓存
}
@Override
public void update(Item before,Item after){
//更新redis数据
//更新本地缓存
//更新数据到JVM缓存
}
@Override
public void delete(Item item){
//删除redis数据
//清除本地缓存
//从JVM中删除缓存
}
}