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

Go语言分布式锁实战:dlock助力构建高并发稳定系统

在构建分布式系统时,一个常见且棘手的问题便是资源竞争和数据一致性问题。分布式锁作为一种常用的解决方案,在多个进程或节点之间协调访问共享资源时显得尤为重要。今天,我们将介绍一款分布式锁库——dlock,并通过详细的使用示例带您了解其工作原理和实际应用场景。

分布式锁的工作原理

分布式锁主要用于在分布式环境下实现对共享资源的互斥访问,确保同一时刻只有一个客户端可以操作共享资源,从而避免数据不一致或资源冲突问题。dlock 库基于两种成熟的技术实现锁机制:

  1. Redis 锁
    通过 Redis 提供的高性能缓存服务,dlock 利用 redsync 算法实现了分布式锁。该方式具有低延迟、高吞吐量的特点,非常适用于高并发场景。开发者只需要简单调用 dlock 提供的方法,就能轻松实现分布式锁控制。

  2. Etcd 锁
    Etcd 是一个高可靠、高可用的分布式键值存储系统,常用于服务发现和配置管理。dlock 利用 etcd 的一致性特性,构建了一个稳定的分布式锁解决方案。在一些对一致性要求较高的场景中,使用 etcd 锁可以确保锁状态在各个节点间实时同步,避免数据冲突。

这两种锁实现方式各有优劣,开发者可以根据项目的具体需求和部署环境选择合适的锁方案,从而提升系统的稳定性和扩展性。

使用示例:轻松实现分布式锁

接下来,我们将通过两个代码示例,展示如何分别使用 Redis 锁和 Etcd 锁来管理分布式锁。

Redis 锁示例

以下代码展示了如何通过 dlock 库实现 Redis 分布式锁。示例中,我们首先初始化一个 Redis 客户端,然后通过 dlock.NewRedisLock 创建一个锁对象。代码中包含两种加锁方式:一种是尝试获取锁(TryLock),另一种是阻塞等待锁(Lock)。

package mainimport ("context""fmt""time""github.com/go-dev-frame/sponge/pkg/goredis""github.com/go-dev-frame/sponge/pkg/dlock"
)func main() {// 初始化 Redis 客户端(此处为单机实例,注:不建议把分布式锁存放在Sentinel模式或redis集群)redisCli, err := goredis.Init("default:123456@192.168.3.37:6379")if err != nil {panic(err)}defer redisCli.Close()// 创建分布式锁实例,锁名为 "test_lock"locker, err := dlock.NewRedisLock(redisCli, "test_lock")if err != nil {panic(err)}ctx, _ := context.WithTimeout(context.Background(), time.Second*10)// 示例1:尝试获取锁,如果失败则不阻塞{ok, err := locker.TryLock(ctx)if err != nil {fmt.Println("failed to TryLock", err)return}if !ok {fmt.Println("failed to lock")return}defer func() {if err := locker.Unlock(ctx); err != nil {fmt.Println("failed to unlock", err)return}}()// 在此处执行需要加锁保护的业务逻辑// ......}// 示例2:阻塞式获取锁,等待锁释放或超时{if err := locker.Lock(ctx); err != nil {fmt.Println("failed to lock")return}defer func() {if err := locker.Unlock(ctx); err != nil {fmt.Println("failed to unlock", err)return}}()// 执行临界区代码// ......}
}

Etcd 锁示例

如果您的系统对一致性要求更高,或者已经部署了 etcd 集群,那么可以选择使用 etcd 锁。以下代码展示了如何初始化 etcd 客户端,并通过 dlock.NewEtcd 方法创建一个分布式锁实例。同样提供了两种加锁方式供开发者选择。

package mainimport ("context""fmt""time""github.com/go-dev-frame/sponge/pkg/etcdcli""github.com/go-dev-frame/sponge/pkg/dlock"
)func main() {// 设置 etcd 集群的连接地址和超时时间endpoints := []string{"192.168.3.37:2379"}cli, err := etcdcli.Init(endpoints, etcdcli.WithConnectTimeout(time.Second*5))if err != nil {panic(err)}defer cli.Close()// 创建 etcd 分布式锁实例,锁路径为 "sponge/dlock",租约时间为 10 秒locker, err := dlock.NewEtcd(cli, "sponge/dlock", 10)if err != nil {panic(err)}ctx, _ := context.WithTimeout(context.Background(), time.Second*10)// 示例1:尝试获取锁,非阻塞模式{ok, err := locker.TryLock(ctx)if err != nil {fmt.Println("failed to TryLock", err)return}if !ok {fmt.Println("failed to lock")return}defer func() {if err := locker.Unlock(ctx); err != nil {fmt.Println("failed to unlock", err)return}}()// 执行加锁后的操作// ......}// 示例2:阻塞获取锁,等待锁释放或遇到错误退出{if err := locker.Lock(ctx); err != nil {fmt.Println("failed to lock", err)return}defer func() {if err := locker.Unlock(ctx); err != nil {fmt.Println("failed to unlock", err)return}}()// 执行需要锁保护的业务逻辑// ......}
}

总结

分布式锁是保障分布式系统数据一致性和高并发场景下稳定运行的重要工具。dlock 库通过简单易用的接口封装了基于 Redis 和 Etcd 的锁实现方式,为开发者提供了灵活选择的方案。无论是使用 Redis 实现低延迟的锁控制,还是采用 Etcd 保证数据一致性,dlock 都能满足不同场景下的需求。希望本文能够帮助您更好地理解和应用分布式锁技术,为您的分布式系统构建稳固的并发控制机制。


Sponge 是一个强大的 Go 开发框架,其核心理念是通过解析 SQL、Protobuf、JSON 文件逆向生成模块化代码,这些代码可灵活组合成多种类型的完整后端服务。Sponge 提供一站式项目开发解决方案,涵盖代码生成、开发、测试、API 文档生成和部署等方面,显著提升开发效率,降低开发难度,实现以"低代码"方式构建高质量企业级项目。Sponge与内置的DeepSeek R1助手协同重构传统开发范式,打造极速开发体验。

Sponge Github 地址: https://github.com/go-dev-frame/sponge

相关文章:

Go语言分布式锁实战:dlock助力构建高并发稳定系统

在构建分布式系统时,一个常见且棘手的问题便是资源竞争和数据一致性问题。分布式锁作为一种常用的解决方案,在多个进程或节点之间协调访问共享资源时显得尤为重要。今天,我们将介绍一款分布式锁库——dlock,并通过详细的使用示例带…...

如何提高G口服务器的安全性?

G口服务器可以支持千兆网络传输速度,能够为企业提供更快的数据处理能力和传输能力,随着网络流量的不断增长以及复杂计算任务的普及,企业对于网络带宽的要求也在相应提高,而G口服务器则可以降低网络的延迟度,大幅度提高…...

为没有CMake配置的第三方库添加CMake配置

1 编写CMakeLists.txt cmake_minimum_required(VERSION 3.15) #如果你第三方库和自己的库没有xxxConfig.cmake #请修改项目名称和命名空间(一般不需要) project("pthreads" LANGUAGES C CXX) set(KC_NAMESPACE "") #set(K…...

Linux驱动编程 - seq_open、single_open使用方法

目录 前言: 一、seq_xxx 1、seq_xxx 函数介绍 1.1 seq_open 1.2 seq_read 1.3 seq_lseek 1.4 seq_release 1.5 格式化输出函数 2、seq_open 实例 二、single_xxx 函数 1、single_xxx 函数介绍 1.1 single_open 1.2 single_start 1.3 single_next 1.4 single_stop…...

N列股票收盘价为起点的马科维茨(Markowitz)均值—方差理论

1. 数据准备与收益率计算 输入数据: 假设你有一个矩阵,每一列代表一只股票的历史收盘价序列。每一行对应一个时间点的收盘价。 计算收益率: 马科维茨理论要求使用资产的收益率而非价格。常用的收益率计算方法有对数收益率或简单收益率。 2.…...

【嵌入式学习2】函数

目录 ## 函数 ## 函数分类 ## 函数定义 1、无参数无返回值 2、有参数无返回值 3、有参数有返回值 ## 函数声明 ## 局部变量和全局变量 ## 多文件编程 如何避免把同一个头文件 include 多次,或者头文件嵌套包含? 命令行编译文件 头文件包含的…...

模式搜索+扩散模型:FlowMo重构图像Token化的技术革命

图像Token化作为现代生成式AI系统的核心技术,长期面临对抗性训练不稳定、潜在空间冗余等挑战。斯坦福大学李飞飞与吴佳俊团队提出的FlowMo(Flow towards Modes)创新性地融合模式搜索与扩散模型,在多个关键维度突破传统方法局限&am…...

mac brew 安装的php@7.4 打开redis扩展

1. 找到php7.4的pecl目录 一般在这个位置 cd /usr/local/Cellar/php7.4/7.4.33_8/pecl/20190902 ls 一下 有个 redis.so 于是 直接去php.ini编辑了 php.ini的路径 vim /usr/local/etc/php/7.4/php.ini 把938行添加进去 然后重启一下 php7.4 brew services restart ph…...

OSPF多区域通信

作业要求: 1、多区域0SPF area 0、area10、are20 2、AR5、AR6作为stub区&#xff0c;使用环回接口与Pc1进行通信 第一步&#xff1a;为各端口配置IP地址 AR1: <Huawei>sys [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 5.5.5.1 24 [Huawei-GigabitEther…...

C++模板编程与元编程面试题及参考答案(精选100道题)

目录 解释 C++ 模板的实例化过程,显式实例化与隐式实例化的区别 模板函数在不同翻译单元中的 ODR(单一定义规则)问题 模板参数推导失败的可能场景及解决方法 模板函数中 auto 返回类型的推导规则 如何限制模板函数仅接受特定类型的参数?(非 C++20 概念场景) 函数模板…...

括弧匹配检验(信息学奥赛一本通-1354)

【题目描述】 假设表达式中允许包含两种括号&#xff1a;圆括号和方括号&#xff0c;其嵌套的顺序随意&#xff0c;如&#xff08;&#xff3b; &#xff3d;&#xff08;&#xff09;&#xff09;或&#xff3b;&#xff08;&#xff3b; &#xff3d;&#xff3b; &#xff3…...

三、重学C++—C语言内存管理

上一章节&#xff1a; 二、重学C—C语言核心-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/146191640?spm1001.2014.3001.5502 本章节代码&#xff1a; cPart2 CuiQingCheng/cppstudy - 码云 - 开源中国https://gitee.com/cuiqingcheng/cppstudy/tree/…...

算法题(105):小猫爬山

审题&#xff1a; 本题需要我们找出将n个小猫放在有限重的缆车上运下山所需的最小缆车数 时间复杂度分析&#xff1a;本题的数据量小于等于18&#xff0c;所以我们在做好剪枝的前提下可以使用深度优先搜索解题 思路&#xff1a; 方法一&#xff1a;dfs 搜索策略&#xff1a;将小…...

C语言-适配器模式详解与实践

文章目录 C语言适配器模式详解与实践1. 什么是适配器模式&#xff1f;2. 为什么需要适配器模式&#xff1f;3. 实际应用场景4. 代码实现4.1 UML 关系图4.2 头文件 (sensor_adapter.h)4.3 实现文件 (sensor_adapter.c)4.4 使用示例 (main.c) 5. 代码分析5.1 关键设计点5.2 实现特…...

线程的pthread_create、pthread_join、pthread_exit、pthread_detach函数

线程的创建&#xff08;pthread_create&#xff09; pthread_t tid;//本质是unsigned long类型&#xff0c;打印时得到的是该线程的虚拟地址int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void*), void *arg ); pthread_t *thre…...

测试专项4:AI算法测试在测试行业中,该如何定位自己自述

这岗位到底干啥的&#xff1f; 打个比方&#xff1a; 你就像AI模型的“质检员产品经理风险顾问”三合一。 质检员&#xff1a; 别人造了个AI模型&#xff08;比如人脸识别系统&#xff09;&#xff0c;你不能光看它实验室成绩好&#xff0c;得把它丢到现实里折腾&#xff1a;…...

QT-LINUX-Bluetooth蓝牙开发

BlueToothAPI QT-BlueToothApi Qt Bluetooth 6.8.2 官方提供的蓝牙API不支持linux。 D-Bus的API实现蓝牙 确保系统中安装了 BlueZ(版本需≥5.56),并且 Qt 已正确安装并配置了 D-Bus 支持。 默默看了下自己的版本.....D-BUS的API也不支持。 在 D-Bus 中,org 目录是 D-Bus…...

【经验总结】AUTOSAR架构下NvMBlock无效问题分析

目录 前言 正文 1.问题描述 2.问题原因 3.深入分析 3.1NvM_InvalidateNvBlock分析 3.2NvBlock无效后NvM_ReadBlock行为分析 3.3NvBlock无效后NvM_WriteBlock行为分析 4.总结 前言 最近在做所有NvMBlock测试的时候,发现一个NvMBlock始终无法测试成功(写入Block值 --&…...

STM32 的tf卡驱动

基于STM32的TF卡驱动的基本实现步骤和相关代码示例,主要使用SPI接口来与TF卡进行通信。 硬件连接 将TF卡的SPI接口与STM32的SPI引脚连接,通常需要连接SCK(时钟)、MOSI(主出从入)、MISO(主入从出)和CS(片选)引脚。 软件实现 初始化SPI 配置SPI的工作模式、时钟频率…...

stress-ng命令详解

stress-ng 是一款功能强大的 Linux 系统压力测试工具&#xff0c;能够模拟多种复杂负载场景&#xff0c;覆盖 CPU、内存、磁盘 I/O、进程调度等核心资源&#xff0c;帮助开发者验证系统在高负载下的稳定性与性能表现。以下是其核心功能、参数解析及实战案例。 一、工具简介与安…...

【C语言系列】数据在内存中存储

数据在内存中存储 一、整数在内存中的存储二、大小端字节序和字节序判断2.1什么是大小端&#xff1f;2.2练习2.2.1练习12.2.2练习22.2.3练习32.2.4练习42.2.5练习52.2.6练习6 三、浮点数在内存中的存储3.1练习3.2浮点数的存储3.2.1 浮点数存的过程3.2.2 浮点数取的过程 3.3题目…...

【中文翻译】第12章-The Algorithmic Foundations of Differential Privacy

由于GitHub项目仅翻译到前5章&#xff0c;我们从第6章开始通过大语言模型翻译&#xff0c;并导出markdown格式。 大模型难免存在错漏&#xff0c;请读者指正。 教材原文地址&#xff1a;https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf 12 其他模型 到目前为止&…...

图解模糊推理过程(超详细步骤)

我们前面已经讨论了三角形、梯形、高斯型、S型、Z型、Π型6种隶属函数&#xff0c;下一步进入模糊推理阶段。 有关六种隶属函数的特点在“Pi型隶属函数&#xff08;Π-shaped Membership Function&#xff09;的详细介绍及python示例”都有详细讲解&#xff1a;https://lzm07.b…...

datawhale组队学习-大语言模型-task5:主流模型架构及新型架构

目录 5.3 主流架构 5.3.1 编码器-解码器架构 5.3.2 因果解码器架构 5.3.3 前缀解码器架构 5.4 长上下文模型 5.4.1 扩展位置编码 5.4.2 调整上下文窗口 5.4.3 长文本数据 5.5 新型模型架构 5.5.1 参数化状态空间模型 5.5.2 状态空间模型变种 5.3 主流架构 在预训…...

为什么后端路由需要携带 /api 作为前缀?前端如何设置基础路径 /api?

一、为什么后端路由需要携带 /api 作为前缀&#xff1f; 1. 区分 API 端点与其他路由 在 Web 应用程序中&#xff0c;后端不仅需要处理 API 请求&#xff0c;还可能需要处理静态资源&#xff08;如 HTML、CSS、JS 文件&#xff09;或其他服务&#xff08;如 WebSocket&#x…...

C++ 关系运算符重载和算术运算符重载的例子,运算符重载必须以operator开头

在C中&#xff0c;运算符重载允许为用户定义的类型&#xff08;类或结构体&#xff09;赋予某些内置运算符的功能。下面是一个关于关系运算符重载&#xff08;&#xff09;和算术运算符重载&#xff08;&#xff09;的简单例子。 示例&#xff1a;复数类的运算符重载 将创建一…...

建造者模式 (Builder Pattern)

建造者模式 (Builder Pattern) 是一种创建型设计模式,它将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。 一、基础 1.1 意图 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。 1.2 适用场景 当创建复杂对象的算法应该…...

MCU vs SoC

MCU&#xff08;Microcontroller Unit&#xff0c;单片机&#xff09;和SoC&#xff08;System on Chip&#xff0c;片上系统&#xff09;是两种不同的芯片类型&#xff0c;尽管它们都实现了高度集成&#xff0c;但在设计目标、功能复杂性和应用场景上存在显著差异。以下是两者…...

RAG 架构地基工程-Retrieval 模块的系统设计分享

目录 一、知识注入的关键前奏——RAG 系统中的检索综述 &#xff08;一&#xff09;模块定位&#xff1a;连接语言模型与知识世界的桥梁 &#xff08;二&#xff09;核心任务&#xff1a;四大关键问题的协调解法 &#xff08;三&#xff09;系统特征&#xff1a;性能、精度…...

(C语言)习题练习 sizeof 和 strlen

sizeof 上习题&#xff0c;不知道大家发现与上一张的习题在哪里不一样嘛&#xff1f; int main() {char arr[] "abcdef";printf("%zd\n", sizeof(arr));printf("%zd\n", sizeof(arr 0));printf("%zd\n", sizeof(*arr));printf(&…...