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

相关文章

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Go语言如何判断两张图片的相似度

《Go语言如何判断两张图片的相似度》这篇文章主要为大家详细介绍了Go语言如何中实现判断两张图片的相似度的两种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 在介绍技术细节前,我们先来看看图片对比在哪些场景下可以用得到:图片去重:自动删除重复图片,为存储空间"瘦身"。想象你是一个

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中

如何搭建并配置HTTPD文件服务及访问权限控制

《如何搭建并配置HTTPD文件服务及访问权限控制》:本文主要介绍如何搭建并配置HTTPD文件服务及访问权限控制的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、安装HTTPD服务二、HTTPD服务目录结构三、配置修改四、服务启动五、基于用户访问权限控制六、

Go语言中使用JWT进行身份验证的几种方式

《Go语言中使用JWT进行身份验证的几种方式》本文主要介绍了Go语言中使用JWT进行身份验证的几种方式,包括dgrijalva/jwt-go、golang-jwt/jwt、lestrrat-go/jw... 目录简介1. github.com/dgrijalva/jwt-go安装:使用示例:解释:2. gi

go rate 原生标准限速库的使用

《gorate原生标准限速库的使用》本文主要介绍了Go标准库golang.org/x/time/rate实现限流,采用令牌桶算法控制请求速率,提供Allow/Reserve/Wait方法,具有一定... 目录介绍安装API介绍rate.NewLimiter:创建限流器limiter.Allow():请求是否

Go 语言中的 Struct Tag 的用法详解

《Go语言中的StructTag的用法详解》在Go语言中,结构体字段标签(StructTag)是一种用于给字段添加元信息(metadata)的机制,常用于序列化(如JSON、XML)、ORM映... 目录一、结构体标签的基本语法二、json:"token"的具体含义三、常见的标签格式变体四、使用示例五、使用

SpringCloud整合MQ实现消息总线服务方式

《SpringCloud整合MQ实现消息总线服务方式》:本文主要介绍SpringCloud整合MQ实现消息总线服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、背景介绍二、方案实践三、升级版总结一、背景介绍每当修改配置文件内容,如果需要客户端也同步更新,