数据库 redis 本地缓存 多级缓存架构图_redis


多级缓存架构当中每一层的意义


 


ngx_lua 属于 nginx 的一部分,它的执行指令都包含在 nginx 的 11 个步骤之中了,相应的处理阶段可以做插入式处理,即可插拔式架构,不过 ngx_lua 并不是所有阶段都会运行的;另外指令可以在 http 、 server 、 server if 、 location 、 location if 几个范围进行配置:


 


1、nginx本地缓存


nginx 本地缓存,抗的是热数据的高并发访问,根据场景设置缓存时间商品的购买总是有热点的,比如每天购买 iphone 、 nike 、海尔等知名品牌的东西的人,总是比较多的这些热数据,利用nginx 本地缓存,由于经常被访问,所以可以被锁定在 nginx 的本地缓存内大量的热数据的访问,就是经常会访问的那些数据,就会被保留在nginx本地缓存内,那么对这些热数据的大量访问,就直接走 nginx 就可以了,不需要走后续的各种网络开销了


 


2、redis分布式缓存


如果 nginx 本地缓存不命中,则 nginx 会访问 redis 集群服务, redis 集群服务,抗的是很高的离散访问,因为 redis 的性能问题,能够支撑海量的数据,高并发的访问,提供高可用的服务nginx本地内存有限,也就能 cache 住部分热数据,除了热点数据,其他相对不那么热的数据,可能流量会经常走到 redis 那里 利用 redis cluster 的多 master 写入,横向扩容,1T+ 以上海量数据支持,几十万的读写并发, 99.99% 高可用性,那么就可以抗住大量的离散访问请求


 


3、多级缓存架构设计需要解决的问题


这里列了一些,也就是结合我们所学的知识带大家解决生产环境当中要解决的问题


 


1 、数据库 + 缓存双写一致性解决方案


面临难题:高并发场景下,如何解决数据库与缓存双写的时候数据不一致的情况?



 



2 、缓存维度化拆分解决方案



面临难题:如何解决大 value 缓存的全量更新效率低下问题?



 



3 、缓存命中率提升解决方案



面临难题:如何将缓存命中率



 



4 、缓存并发重建冲突解决方案



面临难题:如何解决高并发场景下,缓存重建时的分布式并发重建的冲突问题?



 



5 、缓存预热解决方案



面临难题:如何解决高并发场景下,缓存冷启动导致 MySQL 负载过高,甚至瞬间被打死的问题?



 



6 、缓存雪崩解决方案



面临难题:如何解决恐怖的缓存雪崩问题?避免给公司带来巨大的经济损失?



 



7 、缓存穿透解决方案



面临难题:如何解决高并发场景下的缓存穿透问题?避免给 MySQL 带来过大的压力?



 



8 、缓存失效解决方案



面临难题:如何解决高并发场景下的缓存失效问题?避免给 redis 集群带来过大的压力?


集群划分


redis 集群


容器名称

容器IP地址 

映射端口号

服务器运行模式

redis-matser1

172.18.0.2

6380->6379  16380->16379

Master

redis-matser2

172.18.0.3

6381->6379  16381->16379

Master

redis-matser3

172.18.0.4

6382->6379  16382->16379

Master

redis-slave1

172.18.0.5

6383->6379  16383->16379

Slave

redis-slave2

172.18.0.6

6384->6379  16384->16379

Slave

redis-slave3

172.18.0.7

6385->6379  16385->16379

Slave

Ngnix集群

容器名称

容器IP地址 

映射端口号

服务器运行模式

Nginx

172.18.0.8

8001->80

Nginx分发层

Nginx-lua1

172.18.0.9

8002->80

Nginx分发层

Nginx-lua2

172.18.0.10

8003->80

Nginx分发层

PHP与mysql

容器名称

容器IP地址 

映射端口号

服务器运行模式

php-fpm

172.18.0.11

9002->9000

php应用层

mysql

172.18.0.12

3307->3306

mysql应用层

 具体操作步骤如下

1、目录结构

数据库 redis 本地缓存 多级缓存架构图_redis_02

 2、构建镜像

#构建nginx镜像
cd /docker/cache/docker/nginx

docker build -t nginx . --no-cache(如果以前有构建过则加上--no-cache)

#构建php镜像
cd /docker/cache/docker/php

docker build -t php-fpm . --no-cache

#构建redis镜像
cd /docker/cache/docker/redis

docker build -t redis . --no-cache

数据库 redis 本地缓存 多级缓存架构图_缓存_03


数据库 redis 本地缓存 多级缓存架构图_redis_04

 

数据库 redis 本地缓存 多级缓存架构图_nginx_05

3、利用docker-compose构建容器,最终结果如下图

数据库 redis 本地缓存 多级缓存架构图_缓存_06

4、配置文件以及lua脚本编写

数据库 redis 本地缓存 多级缓存架构图_redis_07

数据库 redis 本地缓存 多级缓存架构图_nginx_08

数据库 redis 本地缓存 多级缓存架构图_缓存_09

搭建过程中遇到的问题以及解决方法:

[error] 1507#0: *22 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 10.0.0.1, server: www.wordpress.com, request: "GET /info.p

问题:nginx能解析静态文件但是不能解析php动态文件,返回404文件未发现错误

原始nginx配置:(这里只给出抛给php程序的配置)

location ~ \.php$ {
      fastcgi_pass   127.0.0.1:9000;
	  fastcgi_index  index.php;
	  fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name; 
	  include        fastcgi_params;
}

解决方案:

location ~ \.php/?.*   {
            root           /var/www/html;#php-fpm容器中的路径,不是nginx路径
            fastcgi_pass   127.0.0.1:9002;#对应容器的端口,此处ip地址应写外网访问地址
            fastcgi_index  index.php;
            #为php-fpm指定的根目录
            fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name; #加了这一项
            #定义变量$path_info,存放pathinfo信息
            set $path_info "";
            if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
                #将文件地址赋值给变量 $real_script_name
                set $real_script_name $1;
                #将文件地址后的参数赋值给变量 $path_info
                set $path_info $2;
            }
            #配置fastcgi的一些参数
            fastcgi_param SCRIPT_NAME $real_script_name;
            fastcgi_param PATH_INFO $path_info;
            #fastcgi_params所在目录
            include       /usr/local/openresty/nginx/conf/fastcgi_params;
   }

 

原因:

在fastcgi_params文件(和nginx.conf文件在同一个目录下)里定义了许多与fastcgi程序相关的变量,当nginx通过fastcgi接口发送请求时它要去定义好的地方去解析相应的变量值,然后交给php去处理,很显然,如果fastcgi获取不了相应的值,那么他就无法把相应请求转发给php程序,自然无法解析。

这个问题的关键在于"Primary script unknown”主脚本未知,也就是fastcgi程序无法找到定义的要执行的脚本,默认的配置文件fastcgi_params定义的变量中并没有$fastcgi_script_name这个变量,但是在fastcgi.conf里定义了。所以我们要么包含这个fastcgi.conf文件,要么把fastcgi_params里的SCRIPT_FILENAME 构建成和fastcgi.conf里的值一样,加上$document_root参数(这个参数的值就代表站点目录root那一行的值)。

最终浏览器访问结果如下:

数据库 redis 本地缓存 多级缓存架构图_缓存_10