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

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
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
目录
相关文章
|
4月前
|
缓存 应用服务中间件 nginx
成功解决 Nginx更新静态资源无效 ,Nginx静态资源更新不及时,Nginx清除缓存
这篇文章讨论了在使用Nginx进行动静分离时遇到的静态资源更新不及时的问题。问题描述了在服务器上更新静态资源后,访问页面时页面没有显示更新的情况。文章提供了解决这个问题的方法,即清除浏览器缓存,并提供了相关参考文章链接。此外,还展示了问题复现的步骤和正常情况的预期结果。
成功解决 Nginx更新静态资源无效 ,Nginx静态资源更新不及时,Nginx清除缓存
|
2月前
|
存储 缓存 监控
|
2月前
|
存储 缓存 负载均衡
Nginx代理缓存机制
【10月更文挑战第2天】
107 4
|
2月前
|
存储 缓存 NoSQL
Nginx缓存
Nginx缓存
34 2
|
3月前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
2月前
|
NoSQL 网络协议 应用服务中间件
redis,memcached,nginx网络组件
redis,memcached,nginx网络组件
23 0
|
4月前
|
应用服务中间件 nginx
[nginx]编译安装openresty
[nginx]编译安装openresty
|
4月前
|
缓存 应用服务中间件 nginx
[nginx]proxy_cache缓存系统
[nginx]proxy_cache缓存系统
107 4
|
5月前
|
存储 缓存 前端开发
(三)Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...想要的这都有!
早期的业务都是基于单体节点部署,由于前期访问流量不大,因此单体结构也可满足需求,但随着业务增长,流量也越来越大,那么最终单台服务器受到的访问压力也会逐步增高。时间一长,单台服务器性能无法跟上业务增长,就会造成线上频繁宕机的现象发生,最终导致系统瘫痪无法继续处理用户的请求。
180 1
|
4月前
|
NoSQL Java 应用服务中间件
使用Redis和Nginx分别实现限制接口请求频率
这篇文章介绍了如何使用Redis和Nginx分别实现限制接口请求频率的方法,包括具体的命令使用、代码实现和配置步骤。
80 0