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

相关文章

Go信号处理如何优雅地关闭你的应用

《Go信号处理如何优雅地关闭你的应用》Go中的优雅关闭机制使得在应用程序接收到终止信号时,能够进行平滑的资源清理,通过使用context来管理goroutine的生命周期,结合signal... 目录1. 什么是信号处理?2. 如何优雅地关闭 Go 应用?3. 代码实现3.1 基本的信号捕获和优雅关闭3.2

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

go基础知识归纳总结

无缓冲的 channel 和有缓冲的 channel 的区别? 在 Go 语言中,channel 是用来在 goroutines 之间传递数据的主要机制。它们有两种类型:无缓冲的 channel 和有缓冲的 channel。 无缓冲的 channel 行为:无缓冲的 channel 是一种同步的通信方式,发送和接收必须同时发生。如果一个 goroutine 试图通过无缓冲 channel

如何确定 Go 语言中 HTTP 连接池的最佳参数?

确定 Go 语言中 HTTP 连接池的最佳参数可以通过以下几种方式: 一、分析应用场景和需求 并发请求量: 确定应用程序在特定时间段内可能同时发起的 HTTP 请求数量。如果并发请求量很高,需要设置较大的连接池参数以满足需求。例如,对于一个高并发的 Web 服务,可能同时有数百个请求在处理,此时需要较大的连接池大小。可以通过压力测试工具模拟高并发场景,观察系统在不同并发请求下的性能表现,从而

【Go】go连接clickhouse使用TCP协议

离开你是傻是对是错 是看破是软弱 这结果是爱是恨或者是什么 如果是种解脱 怎么会还有眷恋在我心窝 那么爱你为什么                      🎵 黄品源/莫文蔚《那么爱你为什么》 package mainimport ("context""fmt""log""time""github.com/ClickHouse/clickhouse-go/v2")func main(

基于SpringBoot的宠物服务系统+uniapp小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统+原生微信小程序+LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统+LW参考示例 3.基于SpringBoot+Vue的企业人事管理系统+LW参考示例 4.基于SSM的高校实验室管理系统+LW参考示例 5.基于SpringBoot的二手数码回收系统+原生微信小程序+LW参考示例 6.基于SSM的民宿预订管理系统+LW参考示例 7.基于

Go Select的实现

select语法总结 select对应的每个case如果有已经准备好的case 则进行chan读写操作;若没有则执行defualt语句;若都没有则阻塞当前goroutine,直到某个chan准备好可读或可写,完成对应的case后退出。 Select的内存布局 了解chanel的实现后对select的语法有个疑问,select如何实现多路复用的,为什么没有在第一个channel操作时阻塞 从而导

Go Channel的实现

channel作为goroutine间通信和同步的重要途径,是Go runtime层实现CSP并发模型重要的成员。在不理解底层实现时,经常在使用中对channe相关语法的表现感到疑惑,尤其是select case的行为。因此在了解channel的应用前先看一眼channel的实现。 Channel内存布局 channel是go的内置类型,它可以被存储到变量中,可以作为函数的参数或返回值,它在r