分布式

分布式锁

Reids分布式锁

public class RedisTool {

    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";

    /**
     * 尝试获取分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @param expireTime 超期时间
     * @return 是否获取成功
     */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {

        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);

        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

    /**
     * 释放分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @return 是否释放成功
     */
    public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {

        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));

        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }
}    

为何需要requestId

  • 线程1执行逻辑为:加锁、执行逻辑、解锁
  • 若线程1执行逻辑时间,超过锁有效期,则解锁时有可能解除了别人的锁

缺点

  • Redis 主从复制是异步的,主挂掉切换主后,可能有部分数据丢失,导致锁丢失

数据库分布式锁

  • select for update
  • 唯一索引
  • 版本号

Zookeeper分布式锁

  • 创建临时有序节点来创建锁
  • 获取所有节点,判断序号是否最小来判断是否有锁
  • 监听上一节点来实现等待锁

缺点

  • 创建临时锁的目的,是防止程序挂掉无法释放锁
  • 也可能因为网络故障而错误释放锁

分布式事务

两阶段提交协议

商业数据库自带

过程:

三阶段提交

MQ事务

负载均衡

算法

  • 轮询
  • 加权轮询
  • 随机
  • 最少连接
  • 加权最小连接

实现

  • DNS 解析
  • 修改 Mac地址
  • 修改 IP 地址
  • Http 重定向
  • Nginx 反向代理

发布于 2020/08/23 浏览