- 开辟一块内存空间
在Nginx配置文件conf/nginx.conf中开启了一个内存大小为128M的内存空间,用来存储缓存数据;
- 定义内存字典业务实现lua脚本memory_shared_dic_java.lua(添加缓存,获取缓存)
---
--- 基于lua+Openresty实现内存字典,直接访问redis缓存
--- 引入Redis lua库文件
local red = require "resty.redis"
--- 调用new方法,获取redis对象
local redis = red:new()
--
local password = "123456";
-- 设置一下redis密码
redis:auth(password)
redis:select(0)
--- 1、实现缓存的添加操作
function set_to_cache(key,value,expr)
if not expr then
expr = 0
end
--- 获取本地内存字典对象
local ngx_cache = ngx.shared.ngx_cache
--- 向内存字典中添加缓存数据
local succ,err,forcible = ngx_cache:set(key,value,expr)
return succ
end
--- 2、从内存字典中获取缓存数据
function get_from_cache(key)
--- 获取本地内存字典对象
local ngx_cache = ngx.shared.ngx_cache
--- 从内存字典中获取数据缓存
local res = ngx_cache:get(key)
-- 如果内存字典缓存不存在
if not res then
-- 查询redis缓存数据
local rev,err = get_from_redis(key)
if not rev then
ngx.say("redis cache not exists",err)
return
end
-- 添加到本地内存字典
set_to_cache(key,rev,60)
end
return res
end
--- 向redis添加缓存数据
function set_to_redis(key,value)
-- 设置连接Redis的超时时间
redis:set_timeout(10000)
-- 连接redis服务器
local ok,err = redis:connect("172.17.61.90",6379)
-- 判断连接redis服务是否成功
if not ok then
ngx.say("failed to connect:",err)
return
end
-- 如果连接成功,向redis添加缓存数据
local succ,err = redis:set(key,value)
if not succ then
ngx.say("failed set redis:",err)
return
end
return succ
end
-- 从Redis中获取缓存数据
function get_from_redis(key)
-- 设置连接Redis的超时时间
redis:set_timeout(10000)
-- 连接redis服务器
local ok,err = redis:connect("172.17.61.90",6379)
-- 判断连接redis服务是否成功
if not ok then
ngx.say("failed to connect:",err)
return
end
-- 从Redis中获取缓存数据
local succ,err = redis:get(key)
if not succ then
ngx.say("failed get redis:",err)
return
end
ngx.say("get cache from redis......")
return succ
end
--- 3、内存字典缓存响应业务实现
--- 获取请求参数
local params = ngx.req.get_uri_args()
--- 获取参数属性值
local id = params.id
--- 从内存字典中获取数据缓存
local goods = get_from_cache("seckill_goods_"..id)
--- 判断内存字典中是否存在缓存数据,如果不存在,将会去查询后端服务数据
if goods == nil then
-- 从后端服务查询数据
local result = ngx.location.capture("/seckill/goods/detail/"..id)
goods = result.body
-- 向内存字典中添加缓存数据
set_to_cache("seckill_goods_"..id,goods,60)
end
-- 输出结果
ngx.say(goods)
这个lua脚本写好后,上传到Nginx/conf同级目录lua目录下,并且在nginx.conf文件中配置,然后sbin/nginx -s reload生效:
3. java中代码
添加guava依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
@Autowired
private SeckillGoodsMapper seckillGoodsMapper;
//注入redistemplate对象
@Autowired
private RedisTemplate redisTemplate;
//注入guva缓存对象
@Autowired
private Cache<String,Object> guavaCahce;
public TbSeckillGoods findOneByCache(Integer id){
//1、先从jvm堆缓存中读取数据,使用guva缓存
TbSeckillGoods seckillGoods = (TbSeckillGoods) guavaCahce.getIfPresent("seckill_goods_"+id);
//判断jvm堆内缓存是否存在
if(seckillGoods == null){
//2、从分布式缓存中查询
seckillGoods = (TbSeckillGoods) redisTemplate.opsForValue().get("seckill_goods_"+id);
//判断
if(seckillGoods == null){
//3、直接从数据库查询
seckillGoods = seckillGoodsMapper.selectByPrimaryKey(id);
if(seckillGoods != null && seckillGoods.getStatus() == 1){
//添加缓存
redisTemplate.opsForValue().set("seckill_goods_"+id,seckillGoods,1,TimeUnit.HOURS);
}
}
//添加guava缓存
guavaCahce.put("seckill_goods_"+id,seckillGoods);
}
//如果缓存存在,返回Redis缓存
return seckillGoods;
}