Openresty(lua+nginx)-Guava-Redis做多级缓存

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Openresty(lua+nginx)-Guava-Redis做多级缓存
  1. 开辟一块内存空间
    在Nginx配置文件conf/nginx.conf中开启了一个内存大小为128M的内存空间,用来存储缓存数据;
  2. 定义内存字典业务实现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;
            
      }
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
3月前
|
缓存 NoSQL 应用服务中间件
2.2.2 redis,memcached,nginx网络组件
2.2.2 redis,memcached,nginx网络组件
|
3月前
|
存储 NoSQL 应用服务中间件
4.网络设计与redis、memcached、nginx组件(一)
4.网络设计与redis、memcached、nginx组件(一)
76 0
|
3月前
|
NoSQL Java 应用服务中间件
4.网络设计与redis、memcached、nginx组件(二)
4.网络设计与redis、memcached、nginx组件(二)
28 0
|
5月前
|
负载均衡 NoSQL 应用服务中间件
redis、memcached、nginx网络组件
redis、memcached、nginx网络组件
109 0
|
3月前
|
NoSQL 网络协议 应用服务中间件
redis,memcached,nginx网路组件
redis,memcached,nginx网路组件
39 0
|
5月前
|
NoSQL Java 应用服务中间件
2.4 网络设计与redis、memcached、nginx组件
2.4 网络设计与redis、memcached、nginx组件
39 0
|
5月前
|
NoSQL 应用服务中间件 调度
2.2.2 redis、memcached、nginx 网络组件
网络编程关注的问题 连接建立 连接断开 消息到达
30 0
|
7月前
|
缓存 NoSQL 应用服务中间件
基于Redis和Nginx实现高并发缓存架构
基于Redis和Nginx实现高并发缓存架构
421 0
|
7月前
|
缓存 NoSQL 应用服务中间件
基于Nginx+Lua优化多级缓存架构
基于Nginx+Lua优化多级缓存架构
117 0
|
NoSQL PHP Redis
Redis(二)PHP7.2安装redis扩展及访问
服务器安装的是php7.2,就需要使用第一个命令php72w那个,具体使用什么命令,还需要按你自己的服务器PHP版本来看。安装后可用 which phpize 和 which php-config 查看安装的路径。
389 0
Redis(二)PHP7.2安装redis扩展及访问