Go微服务: 悲观锁

2024-06-12 02:20
文章标签 服务 go 悲观

本文主要是介绍Go微服务: 悲观锁,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

悲观锁概述

  • 悲观锁,作为并发控制领域的重要概念,广泛应用于数据库管理系统、多线程编程以及其他需要协调资源访问的场景中
  • 悲观锁(Pessimistic Lock),顾名思义,基于一种“悲观”的假设,即认为在数据处理过程中,很可能会发生并发冲突
  • 因此提前对数据加锁,以防止其他事务或线程的并发修改
  • 这种机制牺牲了一定的并发性能,以换取数据的一致性和安全性
  • 悲观锁的核心思想在于“先获取锁,再操作”
  • 在获取锁的过程中,如果资源已被其他进程锁定,则当前进程必须等待锁释放
  • 具体实现时,数据库系统或并发编程框架会提供相应的API来实现锁的获取与释放
  • 一旦获得锁,持有锁的进程便可以独占访问资源,直到显式释放锁或事务结束

锁的粒度, 类型, 应用场景


1 ) 粒度

  • 悲观锁的粒度可粗可细,从表级锁到行级锁不等,其中:
    • 表级锁:锁定整个表,适用于并发访问较少的场景,但会导致严重的性能瓶颈
    • 行级锁:锁定数据表中的某一行或几行数据,大大提高了并发处理能力,是大多数数据库系统推荐的锁策略

2 )类型

  • 常见的悲观锁类型包括:
    • 共享锁(Shared Locks)
      • 允许多个事务读取同一资源,但任何事务都不能修改
    • 排他锁(Exclusive Locks)
      • 独占资源,不允许其他事务读取或修改,常用于写操作

3 )应用场景

  • 写密集型操作:当系统中有大量写操作,且写操作间冲突频繁时,悲观锁能够有效避免并发写导致的数据不一致
  • 重要数据保护:对于一些敏感或关键数据,优先保证数据的完整性和一致性比追求高并发更为重要

悲观锁在mysql中的应用

  • 实际上默认每次运行 sql 都会 自动 commit,我们来看下
    • $ select @@autocommit; 这里得到的结果默认是 1
    • $ set autocommit=0; 现在设置为 0 不让自动提交
  • 现在比如有一个 stock 的表
    • $ select * from stock; 假设正常来说查询到一条记录
  • mysql 使用 for update 来实现悲观锁
  • 现在开2个mysql的客户端

1 )客户端1

  • 现在查询一条数据
  • $ select * from stock where id=1 where id = 1 for update;
  • 可见能够正常查询出来,这里用到了 for update

2 )客户端2

  • 在客户端2中进行查询
  • $ select * from stock where id=1 where id = 1 for update;
  • 这时候迟迟不返回,阻塞了
  • 现在回到 客户端1 执行 $ commit;
  • 可以看到,客户端2 从阻塞的状态立即拿到结果了
  • 还有需要注意的是:
    • 如果客户端1一直不提交,mysql有个超时机制
    • 超时之后,也不会再阻塞
    • 一般不考虑这种情况

3 ) 所以

  • 这个mysql中的for update 就类似 go语言 里的排他锁
  • mysql 的这个 for update 锁,没有锁住其他 id 的记录
  • 也就是说 上面示例中的 for update 是一个行级锁,只锁定了一条记录
  • 但是,要满足一些条件的时候才是行级锁,只有查询的是索引字段才是行级锁
  • 如果没有索引,那么它会把行级锁变成表锁,这个事情就严重了
  • 这个性能就是非常可怕,断崖式下跌,比如现在查询 num, 这里num是非索引
    • 在客户端1, $ select * from stock where num=1 for update;
    • 在客户端2,$ select * from stock where num=10 for update;
    • 这里如果是行级锁就不会阻塞,但是这里阻塞了, 也就是说这里变成了表锁
  • 所以,非索引 for update 是一个非常恐怖的事情,性能断崖式下跌
  • 悲观锁,在行级锁的情况下,在某些非高并发的场景下,其实还是可以接受的

悲观锁在GORM中的应用

  • 文档
    • https://gorm.io/zh_CN/docs/advanced_query.html#锁
    • https://www.kancloud.cn/sliver_horn/gorm/1861159

总结

  • 悲观锁是一种重要的并发控制手段,它通过预先锁定资源,有效避免了并发修改引发的数据不一致性问题
  • 尽管悲观锁在高并发环境下可能会影响性能,但在处理敏感数据或写密集型操作时,其提供的严格数据保护机制显得尤为关键
  • 开发者在选择使用悲观锁时,应充分评估系统的并发需求、数据敏感度以及性能指标,合理权衡悲观锁与乐观锁的应用场景,以达到最佳的并发控制效果

这篇关于Go微服务: 悲观锁的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1052927

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Go路由注册方法详解

《Go路由注册方法详解》Go语言中,http.NewServeMux()和http.HandleFunc()是两种不同的路由注册方式,前者创建独立的ServeMux实例,适合模块化和分层路由,灵活性高... 目录Go路由注册方法1. 路由注册的方式2. 路由器的独立性3. 灵活性4. 启动服务器的方式5.

TP-Link PDDNS服将于务6月30日正式停运:用户需转向第三方DDNS服务

《TP-LinkPDDNS服将于务6月30日正式停运:用户需转向第三方DDNS服务》近期,路由器制造巨头普联(TP-Link)在用户群体中引发了一系列重要变动,上个月,公司发出了一则通知,明确要求所... 路由器厂商普联(TP-Link)上个月发布公告要求所有用户必须完成实名认证后才能继续使用普联提供的 D

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

Go Mongox轻松实现MongoDB的时间字段自动填充

《GoMongox轻松实现MongoDB的时间字段自动填充》这篇文章主要为大家详细介绍了Go语言如何使用mongox库,在插入和更新数据时自动填充时间字段,从而提升开发效率并减少重复代码,需要的可以... 目录前言时间字段填充规则Mongox 的安装使用 Mongox 进行插入操作使用 Mongox 进行更

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

微服务架构之使用RabbitMQ进行异步处理方式

《微服务架构之使用RabbitMQ进行异步处理方式》本文介绍了RabbitMQ的基本概念、异步调用处理逻辑、RabbitMQ的基本使用方法以及在SpringBoot项目中使用RabbitMQ解决高并发... 目录一.什么是RabbitMQ?二.异步调用处理逻辑:三.RabbitMQ的基本使用1.安装2.架构

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

基于Go语言实现一个压测工具

《基于Go语言实现一个压测工具》这篇文章主要为大家详细介绍了基于Go语言实现一个简单的压测工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录整体架构通用数据处理模块Http请求响应数据处理Curl参数解析处理客户端模块Http客户端处理Grpc客户端处理Websocket客户端

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操