多级缓存架构当中每一层的意义
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、目录结构
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
3、利用docker-compose构建容器,最终结果如下图
4、配置文件以及lua脚本编写
搭建过程中遇到的问题以及解决方法:
[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那一行的值)。
最终浏览器访问结果如下: