Nginx 负载均衡配置
Nginx 负载均衡配置
多台服务器分流,提高网站并发能力,Nginx 负载均衡很常用。
1. 什么是负载均衡
- 多台服务器做同样的服务
- Nginx 把请求分发给不同服务器
- 提高并发能力,一台挂了其他还能用
2. 基础配置
upstream myserver {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass http://myserver;
}
}
3. 常用分发策略
1)轮询(默认)
- 一个接一个轮流分
upstream myserver { server 127.0.0.1:8080; server 127.0.0.1:8081; }
2)加权轮询
- 性能好的服务器多分点
upstream myserver { server 127.0.0.1:8080 weight=3; server 127.0.0.1:8081 weight=1; }
3)ip_hash
- 同一个IP固定访问同一台
upstream myserver { ip_hash; server 127.0.0.1:8080; server 127.0.0.1:8081; }
4. 健康检查
upstream myserver {
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
}
- max_fails:失败几次标记为挂掉
- fail_timeout:多久后重试
5. 常用参数
upstream myserver {
# 备用服务器,其他都挂了才用
server 127.0.0.1:8080 backup;
# 不参与负载均衡
server 127.0.0.1:8081 down;
}
6. 注意事项
- 多台服务器数据要同步(Session、数据库)
- Session 共享用 Redis
- 文件上传用共享存储
总结
Nginx 负载均衡要点:
- upstream 定义服务器组
- proxy_pass 转发到组
- 轮询、加权、ip_hash 策略
- 健康检查自动剔除挂掉的服务
- 注意 Session 共享
做大并发网站,负载均衡是必备的。
Redis 缓存穿透解决
Redis 缓存穿透解决
缓存穿透是指查询不存在的数据,请求都打到数据库,可能被攻击。
1. 什么是缓存穿透
- 缓存里没有这个数据
- 数据库里也没有
- 每次请求都查数据库
- 有人恶意攻击数据库就挂了
2. 和其他问题的区别
- 穿透: 查不存在的数据
- 击穿: 热点key过期
- 雪崩: 大量key同时过期
3. 解决方案
方案一:缓存空值
function getUser($id) {
global $redis, $db;
$key = "user:".$id;
$user = $redis->get($key);
if ($user !== false) {
return json_decode($user, true);
}
// 查数据库
$user = $db->query("SELECT * FROM users WHERE id=$id");
if ($user) {
// 存正常数据
$redis->setex($key, 3600, json_encode($user));
} else {
// 存空值,短时间过期
$redis->setex($key, 60, "null");
}
return $user;
}
方案二:布隆过滤器
- 所有存在的数据存在布隆过滤器里
- 查询前先过布隆过滤器
- 不存在直接返回,不查数据库
方案三:接口校验
- 前端做参数校验
- 比如id必须大于0
- 不合法的直接拒绝
4. 代码示例
// 简单防穿透
if ($id <= 0) {
return null;
}
// 先查缓存
$user = $redis->get("user:".$id);
if ($user === "null") {
return null;
}
if ($user) {
return json_decode($user, true);
}
// 查数据库
$user = $db->query("SELECT * FROM users WHERE id=$id");
// 存缓存
if ($user) {
$redis->setex("user:".$id, 3600, json_encode($user));
} else {
$redis->setex("user:".$id, 60, "null");
}
return $user;
5. 最佳实践
- 空值缓存,短时间过期
- 重要接口加布隆过滤器
- 前端做参数校验
- 数据库做限流保护
总结
缓存穿透解决要点:
- 查不到也存空值
- 空值过期时间短
- 用布隆过滤器
- 做好接口校验
高并发系统,缓存穿透一定要防。
Redis 缓存雪崩解决
Redis 缓存雪崩解决
缓存雪崩是指大量缓存同时失效,请求全部打到数据库,数据库直接挂掉。
1. 什么是缓存雪崩
原理:
- 大量 key 同时过期
- 请求都查数据库
- 数据库压力瞬间暴增
- 数据库扛不住挂掉
和缓存穿透的区别:
- 穿透:查询不存在的数据
- 雪崩:大量缓存同时失效
2. 产生原因
1)缓存大面积过期:
- 大量数据设置了相同过期时间
- 到时间一起失效
2)Redis 宕机:
- Redis 服务挂了
- 所有请求都走数据库
3. 解决方案
方案一:过期时间加随机值
// 不要设置相同过期时间
$expire = 3600 + rand(0, 600);
$redis->setex("key", $expire, $value);
加随机值,让 key 分散过期,不会同时失效。
方案二:缓存永不过期
- 热点数据不设置过期时间
- 更新数据时主动更新缓存
- 异步更新缓存
方案三:Redis 高可用
- 搭建 Redis 集群
- 主从复制
- 哨兵模式
- 一台挂了还有其他的
方案四:熔断降级
- 请求量太大时直接返回默认值
- 不让请求打到数据库
- 保护数据库
4. 代码示例
function getData($id) {
global $redis, $db;
$key = "data:".$id;
$data = $redis->get($key);
if ($data) {
return json_decode($data, true);
}
// 查数据库
$data = $db->query("SELECT * FROM table WHERE id=$id");
// 缓存,过期时间加随机值
$expire = 3600 + rand(0, 600);
$redis->setex($key, $expire, json_encode($data));
return $data;
}
5. 最佳实践
- 过期时间加随机值
- 搭建 Redis 集群
- 热点数据永不过期
- 加熔断降级机制
- 数据库做限流
总结
缓存雪崩解决要点:
- 过期时间加随机值,不要同时失效
- Redis 做主从高可用
- 热点数据不设置过期
- 做好降级兜底
做高并发系统,缓存雪崩一定要防。