负载均衡引发的两个常见问题

在单个实例下,可以用 lock 来达到某一时刻,只有一个线程调用,比如记录访问网站的次数,但是多实例负载的情况下,实例之间就变成了多进程, lock 已经不能满足我们的需求,需要用到分布式锁

redis 实现分布式锁注意点

  1. 锁需要过期时间

当某个实例拿到锁之后,如果系统崩溃了,那么锁永远不会释放,其它的实例也就不能正常运行了,所以可以这样子:

var success = redisClient.Set(lockKey, 1, expireSeconds: 5, exists: RedisExistence.Nx);
  1. 每次加锁必须设置 value 不一样

以第一点为基础,每次加锁 value 都设置为 1,如果此时有三个实例,A 实例拿到锁后但是程序运行超时了,锁被自动释放掉,此时 B 实例拿到锁,过一会后 A 程序运行结束,会释放 B 实例加的锁,造成程序乱套,所以可以这样子:

var id = Guid.NewGuid().ToString("N");
var success = redisClient.Set(lockKey, id, expireSeconds: 5, exists: RedisExistence.Nx);
  1. 释放锁最好是原子操作
var releaseLockScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";//释放锁的redis脚本
var id = Guid.NewGuid().ToString("N");
redisClient.Eval(releaseLockScript, lockKey, id);

参考链接:https://www.cnblogs.com/refuge/p/13774008.html

文件存储

在单个实例下,上传的文件可以放在程序运行的目录,能正常的上传下载,但是多个实例负载下,上传的文件会不确定是放在哪个实例下,而且在下载的时候,可能存在 A 实例的文件,B 实例接到下载文件的请求,程序要做进一步判断再请求到 A 实例拿文件,造成一系列麻烦的问题,所以在多实例负载的情况下,每个实例接受到文件上传,可以把文件上传到同一个地方,下载的时候可以到同一个地方下载,可以采用(Minio)搭建分布式存储。

posted @ 2021-06-02 14:00  东东东  阅读(310)  评论(0)    收藏  举报