当前位置: 首页 > article >正文

Redis 多级缓存

亿级流量的缓存方案

传统缓存的问题

传统的缓存策略一般是请求到达 Tomcat 后,先查询 Redis ,如果未命中则查询数据库,存在以下问题:

在整个这个流程当中,请求始终是由 tomcat 发起的,但是我们知道,tomcat 的并发能力是远远不如 redis 的,所以 Tomcat 就成为了整个流程的一个性能瓶颈,第二就是 redis 的缓存是有过期的可能性的,所以当 Redis 的缓存失效时,tomcat 的请求就会直接抵达数据库这样会对数据库产生巨大的冲击。

多级缓存方案

多级缓存就是充分利用请求处理的每一个环节,分别添加缓存,减轻 Tomcat 的压力,提升服务的性能

例如这幅图:第一级缓存就会由浏览器去实现将一些静态资源缓存在本地,nginx 就是我们的二级缓存,我们的 nginx 就可以将一些动态的数据的请求缓存在本地,当下次请求到来时我们的 nginx 就可以现在本地找一找有没有资源,redis 这个时候就是我们的三级缓存,就是当我们的 nginx 本地也没有资源的情况下,nginx 就会去查询 redis 如果 redis 有也会直接返回,请求就不会抵达 tomcat,如果未命中我们才会抵达 tomcat ,这个时候 tomcat 就是我们的第四级缓存,逻辑与上述一致

综上所述,这个时候压力最大的其实就是我们的 nginx 服务器,那么此时此刻我们的 nginx 就不再是一个简单的反向代理了,而是一个正儿八经的 web 服务器,那么这个时候我们最好是给 nginx 做一个集群,然后准备一个单独的 nginx 来做反向代理

JVM 进程缓存

主要是在 Tomcat 中添加进程缓存

初识 Caffeine

Caffeine 是一个基于 java8 开发的,提供了近乎最佳命中率的高性能的本地缓存库。目前 Spring 内部的缓存的使用的就是 Caffeine。Github 地址:GitHub - ben-manes/caffeine: A high performance caching library for Java

Caffeine 提供了三种缓存驱逐策略

  • 基于容量:设置缓存的数据上限

  • 基于时间:设置缓存的有效时间

  • 基于引用:设置缓存为软引用或者弱鸡引用,利用 GC 来回收缓存数据。性能较差,不建议使用

在默认情况下,当一个缓存元素过期的时候,Caffeine 不会自动立即将其清理个驱逐。而是在一次读或者写操作之后,或者在空闲时间完成对失效数据的驱逐

本地进程缓存

缓存在日常开发中起到至关重要的作用,由于是存储在内存中,数据的读取速度非常快,能大量减少对数据库的访问量,减少数据库的压力,我们把缓存分为两类

  • 分布式缓存,例如 Redis

    • 优点:存储容量更大,可靠性更好,可以在集群中共享

    • 缺点:访问缓存有网络开销

    • 场景:缓存数据量大,可靠性要求较高,需要在集群之间共享

  • 进程本地缓存,例如 HashMap, GuavaCache

    • 优点:读取本地内存,没有网络开销,速度更快

    • 缺点:存储容量有限,可靠性低,无法共享

    • 场景:性能要求较高,缓存数据量小

lua 语法入门

Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放,其开发的目的就是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制的功能,因此 Lua 经常被使用在游戏开发当中,我们的 nginx 也是基于 C语言开发的,它里面也有一些可以自定义的组件,因此我们可以在 nginx 中嵌入 lua 这门语言实现定制功能,第一次学习 Lua 还是需要安装的,不过在我们的 Centos 系统里面是自带 Lua 这门语言的,此脚本语言以 .lua 后缀结尾。官网:The Programming Language Lua

-- 创建一个 lua 简单的实例
vim test.lua
print("Hello World!!!")
-- 运行 lua test.lua

变量和循环

数据类型描述
nil这个最简单,只有值 nil 属于该类,表示一个无效值
booleantrue false
number表示双精度浮点型
string字符串,双引号和单引号都行
function函数类型
tableLua 中的表,其实就是一个关联数组,数组的索引可以是数字,字符串或者其他类型,在 lua 中 table 的创建是通过“构造表达式”来完成的,最简单的表达方式就是 {},用来创建一个空的表

我们可以通过内置的 type 函数来判断数据的类型

print(type("Hello World!!!"))

直接在命令行使用 lua 命令还可以在线编辑,声明变量可以使用 local 不需要指定数据类型

-- 声明字符串
local str = 'hello'
-- 声明数字
local num = 21
-- 声明布尔值
local flag = true
-- 声明数组
local arr = {'a','b','c'}
-- 声明 table
local map = {name='a',age=21}

-- 访问数组,lua 数组的角标从 1 开始
print(arr[1])
-- 访问 table
print(map.name) / print(map['name'])

-- 遍历
for index,value in ipairs(arr) do
    print(index,value)
end

条件控制,函数

-- 函数的定义
function xxxx ()
    return
end

-- 条件判断
if ( not xxx [and/or] xxx )
then
else
end
初识 OpenRestry

OpenRestry 是一个基于 Ngix 的高性能 web 平台,用于方便地搭建能够处理超高并发,扩展性极高的动态 web 应用,web 服务和动态网关,其具备以下几个特点

具备 nginx 的完整功能

基于 Lua 语言进行扩展,集成了大量精良的 Lua 库,第三方模块

允许使用 Lua 自定义业务逻辑,自定义库

官方网站:https://openrestry.org/cn/

数据缓存同步策略

缓存同步策略有以下三种常见的方式

  • 设置有效期

    • 优势:简单,方便

    • 缺点:时效性差,缓存过期之前可能不一致

    • 场景:更新频率低,时效要求低的情况

  • 同步双写

    • 优势:时效性强,缓存与数据库强一致

    • 缺点:有代码入侵,耦合性高;

    • 场景:对一致性,时效性要求较高的缓存数据

  • 异步通知

    • 优势:低耦合,可以同时通知多个缓存服务

    • 缺点:时效性一般,可能存在中间不一致状态

    • 场景:时效性要求一般,有多个服务需要同步

初识 Canal

译为水道,管道等,是阿里巴巴旗下的一款开源项目,基于 JAVA 发开的。基于数据库增量日志解析,提供增量数据的订阅以及消费,GitHub地址 GitHub - alibaba/canal: 阿里巴巴 MySQL binlog 增量订阅&消费组件

它基于 mysql 的主从同步来实现的:

  • mysql master 将数据变更写入到二进制文件(binary log), 其中记录的数据叫 binary log events

  • mysql slave 将 master 的 binary log events 拷贝到它的中继日志 (relay log)

  • mysql slave 重放 relay log 中事件,将数据变更反映它自己的数据

Canal 就是把自己伪装成 mysql 的一个 slave 节点,从而监听 master 的 binary log 变化。再把得到的变化信息通知给 Canal 的客户端,进而完成对其他数据库的同步

搭建 Canal

# 开启 mysql 的 binlog 日志
vim /mysql/conf/my.cnf
# 添加内容
log-bin=/var/lib/mysql/mysql-bin  # 设置 binary log 文件的存放地址和文件名,叫做 mysql-bin
binlog-do-db=heima #  指定对那个库进行监控
# 然后重启 mysql
# 此时此刻我们还需要为从库设置权限
create user canal@'%' identified by '123456';
grant select , replication slave ,replication client ,super on *.* to 'canal'@'%' identified by 'canal';
flush privileges;
# 再次重启 mysql
# 查看主从状态
show master status;
# 我们需要创建一个网络,使得 mysql canal mq 都在同一个网络当中
docker network create heima
# 让 mysql 也加入这个网络
docker network connect heima mysql
# 接下来就是安装 canal 我们可以自行去网上下载 tar 包或者直接通过 wget 下载
# 这里假设我们已经下载到了 canal 的包
docker run -p 11111:11111 --name canal \
-e canal.destinations=heima \
-e canal.instance.master.address=mysql:3306 \
-e canal.instance.dbUsername=canal \
-e canal.instance.dbPassword=123456 \
-e canal.instance.connectionCharset=UTF-8 \
-e canal.instance.tsdb.enable=true \
-e canal.instance.gtidon=false \
-e canal.instance.filter.regex=heima\\..*\
--network heima \
-d canal/canal-server:v1.1.5
# 或者编写一个 docker-compose。yml 文件
version: '3.8'
services:
  canal:
    image: canal/canal-server:v1.1.5
    container_name: canal
    ports:
      - "11111:11111"
    environment:
      canal.destinations: heima
      canal.instance.master.address: mysql:3306
      canal.instance.dbUsername: canal
      canal.instance.dbPassword: 123456
      canal.instance.connectionCharset: UTF-8
      canal.instance.tsdb.enable: "true"
      canal.instance.gtidon: "false"
      canal.instance.filter.regex: heima\\..*
    networks:
      - heima

networks:
  heima:
    external: true
    


http://www.kler.cn/news/318835.html

相关文章:

  • 可以把台式电脑做成服务器吗
  • 状态模式原理剖析
  • OpenCV normalize() 函数详解及用法示例
  • 钰泰-ETA6964A 锂电池充电器IC
  • 基于STM32F103C8T6单片机的农业环境监测系统设计
  • 3D模型在UI设计中应用越来越多,给UI带来了什么?
  • API代理是什么?解读其原理与作用
  • golang context管理channel
  • 【数据库】sqlite
  • 【C++】托管类和托管函数
  • 大模型备案和互联网算法备案的区别?
  • Linux软件包管理器、Linux开发工具、vim的配置等的介绍
  • RabbitMQ简介
  • AI产品经理必知的133个专业术语
  • 高阶函数(Higher-Order Function)
  • 高侧电流检测电路设计
  • [新闻]Tom Sawyer Software宣布发布SysML v2 Viewer
  • GLM-4-9B 是智谱 AI 推出的预训练模型 GLM-4 系列中的开源版本
  • Pytest-allure如何在测试完成后自动生成完整报告?
  • 占领矩阵-第15届蓝桥省赛Scratch中级组真题第5题
  • 桥梁轻量化结构监测系统解决方案
  • [OPEN SQL] SELECT语句
  • Android JNI 调用流程
  • 深入理解主键回显:提升数据操作效率与准确性
  • 目标检测系列(一)什么是目标检测
  • OpenMV与STM32通信
  • 稳了,搭建Docker国内源图文教程
  • Mysql梳理10——使用SQL99实现7中JOIN操作
  • C++ 面试模拟02
  • 2024 年最新 Protobuf 结构化数据序列化和反序列化详细教程