首页
学习
活动
专区
工具
TVP
发布

思考与总结

专栏成员
15
文章
8859
阅读量
16
订阅数
Golang实现分布式唯一ID生成器
一:数据库主键生成:利用数据库的主键生成来获取唯一ID,但是这种方式依赖数据库组件,并且获取ID的效率也不高。
dddyge
2024-03-26
6090
Golang实现一个可存放重复元素的二叉搜索树,结合Morris算法
今天学习的时候看到一道题目是问在二叉搜索树如何存放重复值,借此机会顺便复习了一下二叉搜索树。二叉搜索树的中序遍历是有序的,它的左子树的所有节点的值都是小于它的,它的右子树的所有节点的值都是大于它的。在学习二叉树的遍历的时候,有一个大名鼎鼎的Morris算法,使用双指针就可以实现二叉树的前中后序遍历,并且时间复杂度是O(N),空间复杂度是O(1),于是我使用Golang实现一个可存放重复元素的二叉搜索树,并且结合Morris算法进行查找。
dddyge
2024-03-06
1740
Golang实现线程安全的懒汉式单例模式
今天学习设计模式的时候看到了Java方面的双检式单例模式,由于JVM的指令重排序的问题,又在双检式的情况增添了更多的复杂性,于是我就去看看在Golang中是如何实现单例模式的。其实Golang中实现线程安全,同时又能够支持并发访问的方法也是双检法,他的复杂度封装在了sync包中的Once类中,也是通过采用Check -> Lock -> Check的方式来实现的,具体的代码如下
dddyge
2023-02-09
5820
记一次由于DDL语句导致的mysql满CPU线上事故
事情是这样子的,由于公司要推行降本增效,尽量使得服务器能满负载的去工作,我负责的项目由于对数据库的使用比较轻度,所以就降低配置去使用。而一个新的需求,需要稍微复杂一点的业务逻辑,所以需要对数据库增加一个字段,且增加一个索引,也就是做一点DDL语句的操作,但是由于表的数据量也不小(最大的一张表差不多800多万行,最少也有几百万条数据),所以在此之前,对大表加字段,加索引做了一个比较深入的学习。
dddyge
2022-12-29
5710
Golang模拟实现任务调度状态检测
有时候我们会需要去管理一些后台任务或者定时任务的执行状态或者生命周期等等,又或者后台任务执行超时后如何退出,或者异常情况下应该如何管理。本文通过系统中断简单模拟异常中断。 Runner包的代码如下:package runnerimport ("errors""os""os/signal""time")// runner包用于展示如何通过通道监视程序的执行时间, 如果程序运行时间太长// 也可以用runner包来终止程序。当开发需要调度后台处理任务的程序时,这种模式会很有用。// 这个程序可能会作为
dddyge
2022-12-18
3700
Golang实现协程池
通过无缓冲的通道实现Worker池,无缓冲的通道好处是:1. 任务不会丢失,所有投递的任务都一定会被处理,如果协程池里的协程都在忙碌中的话,那么会阻塞在往通道投递任务的那一行代码。2. 调用者可以及时的知道协程池是否处于忙碌的状态中。 以下是Work包中的代码:package workimport "sync"// work包的目的是展示如何使用无缓冲的通道来创建一个goroutine池, 这些goroutine执行并控制一组工作// 让其并发工作。在这种情况下, 使用无缓冲的通道要比随意指定一个缓冲
dddyge
2022-12-18
6920
Golang模拟实现连接池
池化技术是一种非常有效的节省资源提高效率的办法。本文写一个简单的demo实现数据库连接池,使用了有缓冲的通道来存放资源,从中细细体会资源池的思想。 pool包的代码如下:package poolimport ("errors""io""log""sync")// 本包是pool包, 用于展示如何使用有缓冲的通道实现资源池, 来管理可以在任意数量的goroutine之间共享// 及独立使用的资源。这种模式在需要共享一组静态资源的情况(如共享数据库连接或者内存缓冲区)// 下非常有用。如果goroutin
dddyge
2022-12-18
5960
快速选择算法Golang实现
类似求TopK问题中最常用的算法中,从时间复杂度最高到中等再到最优分别有不同的做法。在之前的学习中只学到了使用堆来优化TopK问题,但是这样的时间复杂度只能做到O(Nlogk)的大小,其中k是堆的大小。有一种更好的办法是基于快速排序的思想去优化的算法,叫做快速选择算法,它的时间复杂度能够做到O(N)的时间复杂度。这里的思路是:每次通过随机取得一个分区键,假设题目要求数组按照从大到小排序,那么通过将分区键移动到头部start,然后从头部的下一个元素开始遍历数组,遇到比分区键大的元素就交换到分区键后的已排序的下标的下一个位置,该指针假设就叫做index。最后遍历结束后将index的值与start的值交换,此时分区键就被移动到了index指针所指的位置,那么index左边的元素都是比分区键要大的,此时再通过对比index - start 与k的大小关系就可以判断下一次递归要从哪个区间开始,从而减少遍历的次数。
dddyge
2022-11-20
3850
高效判断回文子串技巧
今天学习到一个新的技巧来快速判断回文子串:该方法是通过中心扩展来高效判断是否是回文字符串。回文字符串分为奇回文和偶回文,其中奇回文的中心只有一个,偶回文的中心有两个,所以通过遍历中心来左右扩展判断回文字符串。假设字符串的长度为n,那么如果是奇回文,中心个数就是n个;如果是偶回文,中心个数就是n - 1个,那么总共需要遍历的中心个数就是2n - 1个。其中每次遍历中心的left,right分别是i / 2,i / 2 + i mod 2,如果是回文字符串就left--, right++的往左右两边扩散。此方法的时间复杂度是O(N²),因为枚举每个中心需要O(N)的复杂度,每个中心扩展又需要O(N)的复杂度,所以总的时间复杂度是O(N²)
dddyge
2022-11-19
4350
拓扑排序Golang实现
以前一直不太懂拓扑排序的实现,今天在知乎上面看到一篇文章讲拓扑排序,讲的特别清楚,一下子明朗了。链接如下:https://zhuanlan.zhihu.com/p/135094687。
dddyge
2022-10-19
6930
堆的Golang实现
在Leetcode刷题的时候,有些题目需要自己实现一个堆的结构,在此记录一下。例如Leetcode-23:合并k个升序链表。
dddyge
2022-09-07
7860
简单并查集Golang实现
网上看到的并查集都是一个新的结构体,并且有优化的手段,比如在结构体中携带秩,这样能起到路径压缩的作用。但是在Leetcode刷题时一般可以做一个简单版的并查集来ac,这里记录一下。
dddyge
2022-07-27
6020
记一次协程环境下类成员变量污染的问题
我维护的项目采用的技术框架是php中基于swoole的一个web框架叫做swoft。该框架是协程环境,并且是模仿springboot的一个注解式的php框架。我做的一个需求,发生了协程环境下的类成员变量污染的问题。事故是这样的:发起一次rpc请求,返回的结果存在一个类的成员变量,但是发现请求的参数跟结果对不上,我先是排查了错误日志,没发现异常,然后排查请求执行日志,发现日志数量丢失了。于是我仔细看了代码,我通过职责链模式将结果传递到了每一个类的成员变量中,而BeanFactory::getBean这个方法默认是获取单例的类,于是类的成员变量在没有保护的情况下被其他协程污染了。知道这个问题后,我通过修改注解,将职责链的每一个类都修改成多例模式。在本地使用Jmeter压测时结果是正确的,但是又发现了一个新的问题就是执行日志丢失的问题。后面仔细查看了swoft中log包的实现,发现框架开发组也犯了一个跟我一样的错误。他这里的思路是:将日志存放在类的成员变量messages中,这是一个数组,当这个数组中元素大于刷盘数量时,将该数组中的日志记录刷入文件中。但是却没有线程同步的代码块保护,于是在并发的情况下就可以复现日志被覆盖导致缺失的问题了。我在想框架的开发组不应该会犯这样的错误。于是翻了一下github的swoft框架的issue,发现在20年的时候就已经有人提出过这个问题,但是一直没有得到修复。后面我翻看了一下源码,发现他的log这个bean是单例模式,所以才有messages成员变量被污染的问题,我通过创建一个新的newLogger类并将其设置在框架启动时的日志处理类,该并发污染的问题就被解决了。
dddyge
2022-06-21
5540
记一次pgsql数据库cpu较高的事故
接了一个小需求,是将一些用户操作记录入到我们的数据库中。观察到入库的接口平均响应时间比较差大概在几秒左右,当时没多想,就觉得是先查询是否存在,再插入这个过程中查询是否存在比较耗时(因为操作记录表比较大),但是后面发现有10%,20%的入库接口响应时间甚至达到了十秒,并且pgsql数据库cpu变高了很多,波段性的高峰存在。老样子,先查询是否存在慢sql,耗时3秒以上的sql查询load出来后发现原来是查询是否存在的这个过程出了问题。我是通过一个联合索引来查询是否存在的,他们分别是(公司id,店铺id,xxid),通过explain该sql语句发现并没有走这个联合索引,而是走了(公司id,店铺id)这个索引。而这个索引扫出来的结果并没有区分度,因为一个公司的某一个店铺可以有很多的操作记录。让我们来思考一下联合索引的定义,它满足最左前缀匹配原则,mysql的查询优化器会自动将你代码中乱序的查询条件组装成联合索引去查询,进而通过联合索引来计算查询成本。但是最左前缀匹配原则是要求越有区分度的字段应该放在左边,我误以为sql的查询优化会自动帮我把联合索引的区分度字段往左边移动。这次事故的原因主要是因为我对最左前缀匹配原则理解的不深刻,下次应该尽可能的将具有区分度的字段放在联合索引的左边。
dddyge
2022-06-16
6470
记一次mysql数据库cpu暴涨100%事故
在公司监控大盘上看到了我负责的项目的数据库服务器CPU达到100%了, 于是紧急排查问题。仔细的看了一下监控大盘,发现时间从下午3点47分起就开始迅速上升到满cpu的情况,并且持续了23分钟,之后又断断续续的满cpu,每次持续时间大概在几分钟到10分钟左右。第一反应是想到是不是服务器有什么错误日志没输出,检查了elk中的错误,没有错误异常。第二个排查的地方是检查从3点47分起开始的访问量看看是不是并发比较高,发现访问量也是正常的,qps大概在60左右。于是下去找运维要一份数据库的慢sql,但是运维还没看到有慢sql(这点不清楚运维的慢sql是怎么记录日志的,按道理是应该有慢sql)。于是通过show processlist查询到了大概4,5条正在执行的查询。发现用户是我们yearning的用户,而不是应用的用户,并且query_start的起始时间距离现在也差不多在7,8分钟左右。将该sql展开发现是一个在yearning上面执行的inner join,我们是有分表的措施的,将数据按照不同企业维度分摊到10个表。平均一张表大概在10万左右的数据量,同事执行的inner join查询通过explain关键词分析发现该语句笛卡尔积之后的扫描行数足足有6亿行,最后筛选出了89行符合要求的数据。跟同事沟通了一下才发现是他执行的复杂查询。让运维帮忙kill掉查询语句后,数据库cpu恢复正常。
dddyge
2022-06-13
1.2K0
没有更多了
社区活动
【纪录片】中国数据库前世今生
穿越半个世纪,探寻中国数据库50年的发展历程
Python精品学习库
代码在线跑,知识轻松学
博客搬家 | 分享价值百万资源包
自行/邀约他人一键搬运博客,速成社区影响力并领取好礼
技术创作特训营·精选知识专栏
往期视频·千货材料·成员作品 最新动态
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档