当前位置: 首页 > news >正文

常见技术难点及方案

1. 分布式锁

1.1 难点

1.1.1 锁延期

同一时间内不允许多个客户端同时获得锁;

1.1.2 防止死锁

需要确保在任何故障场景下,都不会出现死锁;

1.2.3 可重入

特殊的锁机制,它允许同一个线程多次获取同一个锁而不会被阻塞。

1.2.4 高可用

同时,加锁、释放锁的过程性能开销应尽量低,并保证高可用,避免单点故障。

1.2 技术方案

1.2.1 基于Redis

  • 技术要点
原理Redis的SETNX指令:SETNX(set if not exist)指令用于插入一个键值对。如果键已经存在,则返回False,否则插入成功并返回True。
锁延期Redis 实现分布式锁时,为了确保锁的安全性,引入了 watchdog(看门狗)机制。watchdog 的主要作用是定期重置锁的过期时间,从而避免锁意外过期被其他客户端获取。(在客户端启动)
释放锁同时,可以利用EXPIRE指令为键值对设置过期时间,防止锁忘记释放。
可重入Redis分布式锁实现可重入意味着同一个线程或进程可以多次获取同一个锁而不会被阻塞。这通常是通过在客户端维护一个锁计数器来实现的,每次获取锁时计数器加1,每次释放锁时计数器减1,只有当计数器为0时才真正释放锁。
高可用Redis的RedLock算法:尝试从多个相互独立的Redis实例获取锁,只有当从大多数实例上获取了锁,并且获取锁的时间小于锁的过期时间时,才认为锁获取成功。
  • 技术实践

1.2.2 基于Zookeeper

  • 技术要点
原理

Zookeeper分布式锁:利用Zookeeper的顺序临时节点实现分布式锁和等待队列。

客户端尝试在ZooKeeper的一个特定路径下创建一个临时顺序节点。这个节点是临时的,意味着当客户端会话结束时,ZooKeeper会自动删除它。顺序节点则是ZooKeeper会为其分配一个唯一的、单调递增的序列号。

客户端检查它创建的节点是否是在特定路径下序号最小的节点。如果是,那么它获取到了锁。如果不是,它就需要等待,通常通过监视序号在它之前的节点的删除事件。

锁延期为了保持锁,客户端必须保持与ZooKeeper的会话活动。ZooKeeper的会话有一个超时时间,如果在这个时间内客户端没有与ZooKeeper进行任何交互(如心跳),会话将过期,导致所有与该会话关联的临时节点被删除。因此,为了延期锁,客户端需要定期与ZooKeeper交互以重置会话的超时计时器。
释放锁

当客户端完成其任务并准备释放锁时,它只需删除它之前创建的临时节点。由于该节点是临时的,它的删除不会触发其他客户端的监视事件,除非有其他客户端正在等待成为下一个锁持有者。

如果客户端在持有锁期间崩溃或遇到其他问题,ZooKeeper将自动删除其临时节点(因为会话已过期),从而释放锁。其他等待的客户端将能够获取锁。

可重入

本地锁计数器
客户端维护一个本地锁计数器。每次成功获取锁时,计数器递增;每次释放锁时,计数器递减。

重入逻辑
如果客户端已经持有锁(即本地锁计数器大于0),并且再次尝试获取锁,则只需递增本地锁计数器,而无需与ZooKeeper进行任何额外的交互。

高可用Zookeeper设计的初衷就是为了实现分布式锁服务。
  • 技术实践

Apache Curator是一个流行的ZooKeeper客户端库,它提供了高级的分布式锁实现,包括可重入锁。以下是一个使用Curator实现可重入锁的示例:

Curator is a keeper or custodian of a museum or other collection - A ZooKeeper Keeper.

Apache Curator is a Java/JVM client library for Apache ZooKeeper, a distributed coordination service. It includes a high level API framework and utilities to make using Apache ZooKeeper much easier and more reliable. It also includes recipes for common use cases and extensions such as service discovery and a Java 8 asynchronous DSL.

Welcome to Apache Curator | Apache Curator

import org.apache.curator.framework.CuratorFramework;  
import org.apache.curator.framework.recipes.locks.InterProcessReentrantLock;  public class ZooKeeperReentrantLockExample {  private final CuratorFramework client;  private final InterProcessReentrantLock lock;  public ZooKeeperReentrantLockExample(CuratorFramework client, String lockPath) {  this.client = client;  this.lock = new InterProcessReentrantLock(client, lockPath);  }  public void acquireLock() throws Exception {  lock.acquire(); // 如果当前线程已经持有锁,则重入  }  public boolean tryAcquireLock(long time, TimeUnit unit) throws Exception {  return lock.tryLock(time, unit); // 尝试获取锁,支持重入  }  public void releaseLock() throws Exception {  lock.release(); // 释放锁,如果本地锁计数器减至0,则删除ZooKeeper中的节点  }  
}

2. 限流

2.1 难点

2.1.1 突发流量

在实际应用中,流量往往是不稳定的,存在高峰期和低谷期。如何根据流量的变化动态地调整限流策略,是限流算法需要解决的问题。此外,还需要考虑突发流量的情况,如突然出现的大量请求可能导致系统过载。

2.1.2 平滑

计数器限流算法是一种直观的限流方法,它通过累加在特定时间窗口内的请求数量,并在达到设定的阈值时执行限流操作。然而,这种方法存在一个显著的问题,那就是在时间窗口的末期,如果计数器接近或达到限流阈值,那么新到来的请求很可能会触发限流,即使这些请求在实际上并不会对系统造成过载

观察请求量曲线图,计数器这种限流器会容易呈现出锯齿状而不是平滑的曲线。

2.2 方法

2.2.1 计数器

原理计数器算法通过记录时间窗口内的请求数量来进行限流。当请求数量超过设定的阈值时,新的请求将被拒绝。
优点简单直观,易于实现。
缺点无法应对突发流量,因为一旦达到阈值,后续请求无论多少都会被拒绝。此外,随着流量增长,精度可能下降。

2.2.2 基于滑动窗口的计数器

原理将时间窗口划分为多个小的时间段(格子),每个格子内有一个计数器。随着时间推移,窗口会滑动,抛弃最老的时间段并纳入新的时间段。限流基于整个窗口内的请求总数。
优点相比于固定窗口计数器算法,滑动窗口能更好地应对突发流量,因为每个时间段都有独立的计数器。
缺点

实现相对复杂,需要维护多个计数器和时间窗口的状态。

2.2.3 令牌桶

原理令牌桶中存放着一定数量的令牌,每个令牌代表一个请求权限。请求到达时,如果桶中有令牌则取走令牌并允许请求通过;否则请求被拒绝或等待。
优点能够应对突发流量,因为桶中的令牌可以累积并在需要时快速发放。适用于需要灵活调整限流速率的场景。
缺点如果令牌发放过快,可能导致系统过载;如果发放过慢,则可能浪费系统资源。

2.2.4 漏斗算法

原理想象一个固定容量的桶,请求作为水流进入桶中。如果桶已满,新的请求(水流)会被丢弃或等待直到桶中有空间。
优点能够平滑突发流量,确保系统的稳定性。对于下游系统来说,流量是恒定的,有助于处理请求。
缺点可能导致延迟,因为即使系统有能力处理更多请求,漏桶也会限制流量的速率。

比较两者的特点,漏桶算法更侧重于强制限制数据的传输速率,确保系统接收的请求速率稳定。而令牌桶算法则在限制平均传输速率的同时,允许一定程度的突发传输,以适应流量变化的实际情况。

在适用场景上,漏斗算法更多地用于保护系统,防止因流量过大而崩溃。而令牌桶算法则更适用于那些需要应对突发流量的场景,比如在秒杀活动中,用户的请求速率不固定,令牌桶算法可以确保系统既能处理稳定的请求流,又能应对突发的请求高峰

2.3 方案

2.3.1 单机限流

2.3.1.1 Guava限流
  • Guava RateLimiter———-限制时间窗口内的凭据速率
    • 平滑突发限流(SmoothBurst)
    • 平滑预热限流(SmoothWarningUp)
    • 主要方法:RateLimiter.create()和limiter.acquire()

2.3.2 分布式限流

2.3.2.1 Ngnix+Lua
2.3.2.2 Redis+Lua

​思路上就很粗暴!比如当前限流为10000QPS/s,直接将当前秒作为key,每一个请求到达的时候都将这个key自增,当一个请求将其自增到10000后,就拒绝访问!具体的实现见张开涛的《亿级流量网络架构核心技术》p75—-“分布式限流”。

3. 负载均衡

4. 分布式事务

4.1 难点

4.2 技术方案

5. 幂等

5.1 CAS

5.2 数据库Unique Key

6. 分库分表

相关文章:

常见技术难点及方案

1. 分布式锁 1.1 难点 1.1.1 锁延期 同一时间内不允许多个客户端同时获得锁; 1.1.2 防止死锁 需要确保在任何故障场景下,都不会出现死锁; 1.2.3 可重入 特殊的锁机制,它允许同一个线程多次获取同一个锁而不会被阻塞。 1.2…...

c#关键字 static

static 修饰符可用于声明 static 类。 在类、接口和结构中,可以将 static 修饰符添加到字段、方法、属性、运算符、事件和构造函数。 static 修饰符不能用于索引器或终结器 尽管类的实例包含该类的所有实例字段的单独副本,但每个 static 字段只有一个副…...

redis 如何保证数据同步(数据变化时)

redis 如何保证数据同步(数据变化时) 思路 1.新增、删除和修改都先对数据库进行操作,这时数据库的数据将域缓存中数据不同。 2.数据库进行变动后,返回结果,根据返回的结果判断数据库操作是否成功。 3.如果数据库操…...

Ubuntu18.04桌面版设置静态IP地址

引用: Ubuntu配置静态IP_ubuntu配置静态ip地址-CSDN博客 正文 默认Unbuntu 18.04 Desktop桌面版使用 netplan 管理网卡网络地址。使用Unbuntu 18.04 桌面版配置,可以通过桌面上的设置图标配置网卡的静态IP地址。 点击桌面右上角下拉框,点击“设置”按…...

Aztec的客户端证明

1. 引言 隐私保护 zk-rollup 的证明生成与通用 zk-rollup 的证明生成有很大不同。原因是给定交易中存在特定数据(由私有函数处理),我们希望保持完全私有。在本文中,我们探讨了用于证明私有函数正确执行的客户端证明生成&#xff…...

面试官:小伙子知道synchronized的优化过程吗?我:嘚吧嘚吧嘚,面试官:出去!

写在开头 面试官:小伙子,多线程中锁用过吗? 我:那是自然! 面试官:那你知道synchronized的优化吗? 我:synchronized作为重锁,开销大,在早期不被推荐使用&…...

100天精通风控建模(原理+Python实现)——第23天:风控建模中的贝叶斯优化是什么?怎么实现?

在当今风险多变的环境下,风控建模已经成为金融机构、企业等组织的核心工作之一。在各大银行和公司都实际运用于业务,用于营销和风险控制等。本文以视频的形式阐述风控建模中的召回率是什么,怎么实现。并提供风控建模原理和Python实现文章清单。    之前已经阐述了100天精通…...

Http 超文本传输协议基本概念学习摘录

目录 HTTP协议 超文本传输协议 HyperText超文本 HTML超文本标记语言 HTTP协议原理 请求发送 服务器处理 响应发送 连接关闭或保持 HTTP协议版本 HTTP/0.9 HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/3 HTTP请求方法 GET POST PUT DELETE HEAD OPTIONS HTTP请求头字…...

模拟-算法

文章目录 替换所有的问号提莫攻击Z字形变换外观数列数青蛙 替换所有的问号 算法思路: 从前往后遍历整个字符串,找到问号之后,就遍历 a ~ z 去尝试替换即可。 class Solution {public String modifyString(String s) {char[] ss s.toCharA…...

深入了解鸿鹄工程项目管理系统源码:功能清单与项目模块的深度解析

工程项目管理软件是现代项目管理中不可或缺的工具,它能够帮助项目团队更高效地组织和协调工作。本文将介绍一款功能强大的工程项目管理软件,该软件采用先进的Vue、Uniapp、Layui等技术框架,涵盖了项目策划决策、规划设计、施工建设到竣工交付…...

Unbuntu20.04 git push和pull相关问题

文章目录 Unbuntu20.04 git push和pull使用1.下载[Git工具包](https://git-scm.com/downloads)2.建立本地仓库3.将本地仓库与github远程仓库关联4.将本地仓库文件上传到github远程仓…...

hive SQL 移位、运算符、REGEXP正则等常用函数

orderflag & shiftleft(1,14) shiftleft(1,14) SQL中使用的运算符号详解_sql中各种符号-CSDN博客 Hive函数_hive shift-CSDN博客 (内建函数(类型排序)_云原生大数据计算服务 MaxCompute(MaxCompute)-阿里云帮助中心)...

33-Java服务定位器模式 (Service Locator Pattern)

Java服务定位器模式 实现范例 服务定位器模式(Service Locator Pattern)用于想使用 JNDI 查询定位各种服务的时候考虑到为某个服务查找 JNDI 的代价很高,服务定位器模式充分利用了缓存技术在首次请求某个服务时,服务定位器在 JNDI…...

前端小卡片:vue3路由是什么,有什么作用,该如何配置?

在 Vue 3 中,路由的处理使用了 Vue Router,它是官方提供的路由管理器。Vue Router 用于实现单页应用中的路由功能,通过将不同的 URL 映射到对应的组件,实现页面之间的切换和导航。 Vue Router 的作用包括: 实现页面之…...

Jackson 2.x 系列【2】生成器 JsonGenerator

有道无术,术尚可求,有术无道,止于术。 本系列Jackson 版本 2.17.0 源码地址:https://gitee.com/pearl-organization/study-seata-demo 文章目录 1. 前言2. 案例演示2.1 创建 JsonFactory2.2 创建 JsonGenerator2.3 写入操作2.4 查…...

说说webpack中常见的Loader?解决了什么问题?

文章目录 一、是什么配置方式 二、特性三、常见的loadercss-loaderstyle-loaderless-loaderraw-loaderfile-loaderurl-loader 参考文献 一、是什么 loader 用于对模块的"源代码"进行转换,在 import 或"加载"模块时预处理文件 webpack做的事情…...

Django 铺垫

【一】基础知识点 【1】web框架的本质 Web框架本质上可以看成是一个功能强大的socket服务端用户的浏览器可以看成是拥有可视化界面的socket客服端两种通过网络请求实现数据交互 【2】浏览器发送请求 (1)HTTP协议 HTTP协议是超文本传输协议&#xff…...

浅谈C++的继承与多态(静态绑定、动态绑定和虚函数等)

今天我们来谈谈C的继承与多态😊😊😊,本篇的关键内容如下: 继承的本质及其原理派生类的构造和析构过程重载、隐藏和覆盖类的向下或向上转型静态绑定与动态绑定虚函数对类的影响虚析构函数 下面,我们将对这…...

【无人机综合考试题】

1.请选择出哪一个功能选项,在手动遥控飞行时,可以改变各通道的操作灵敏度? 行程比例在手动遥控飞行时,可以改变各通道的操作灵敏度 用于起降的遥控器中 THR、ELE 通道分别控制多旋翼无人机的什么运动? AIL(左、右移动)RUD(左、右水平旋转…...

JS精度计算的几种解决方法,1、转换成整数计算后再转换成小数,2、toFixed,3、math.js,4、bignumber.js,5、big.js

提示:学习express,搭建管理系统 文章目录 前言一、转换成整数计算后再转换成小数二、toFixed三、math.js四、bignumber.js五、big.js总结 前言 原始计算 let aNum 6.6 0.3;let bNum 6.6 - 0.2;let cNum 6.6 * 0.3;let dNum 6.6 / 0.2;console.log(…...

【单片机期末】单片机系统设计

主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

中科院1区顶刊|IF14+:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点

中科院1区顶刊|IF14:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点 当下,免疫与代谢性疾病的关联研究已成为生命科学领域的前沿热点。随着研究的深入,我们愈发清晰地认识到免疫系统与代谢系统之间存在着极为复…...

ABAP设计模式之---“Tell, Don’t Ask原则”

“Tell, Don’t Ask”是一种重要的面向对象编程设计原则,它强调的是对象之间如何有效地交流和协作。 1. 什么是 Tell, Don’t Ask 原则? 这个原则的核心思想是: “告诉一个对象该做什么,而不是询问一个对象的状态再对它作出决策。…...

day51 python CBAM注意力

目录 一、CBAM 模块简介 二、CBAM 模块的实现 (一)通道注意力模块 (二)空间注意力模块 (三)CBAM 模块的组合 三、CBAM 模块的特性 四、CBAM 模块在 CNN 中的应用 一、CBAM 模块简介 在之前的探索中…...

边缘计算设备全解析:边缘盒子在各大行业的落地应用场景

随着工业物联网、AI、5G的发展,数据量呈爆炸式增长。但你有没有想过,我们生成的数据,真的都要发回云端处理吗?其实不一定。特别是在一些对响应时间、网络带宽、数据隐私要求高的行业里,边缘计算开始“火”了起来&#…...

【自然语言处理】大模型时代的数据标注(主动学习)

文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构D 实验设计E 个人总结 A 论文出处 论文题目:FreeAL: Towards Human-Free Active Learning in the Era of Large Language Models发表情况:2023-EMNLP作者单位:浙江大…...

Nginx 事件驱动理解

在做埋点采集服务的过程中,主要依靠openresty加lua脚本来实现采集。高并发还是主要依靠nginx来实现。而其核心就是事件驱动/多路io复用(epoll机制),不同的linux服务器都有对应的实现方式。 而epoll机制就是,应用启动的…...