算法笔记1
链表专题合并链表递归实现,比较两个链表的头节点,然后递归合并
合并k个升序链表用优先队列,每次取出最小的节点,然后将节点的next放入优先队列
环形链表快慢指针,如果要找到环的入口,可以用快慢指针找到相遇点,然后一个指针从头开始,一个指针从相遇点开始,再次相遇的地方就是环的入口
相交链表两个指针,一个指针遍历完自己的链表后,指向另一个链表的头节点,另一个指针遍历完自己的链表后,指向另一个链表的头节点,这样两个指针遍历的长度是一样的,如果相交,那么两个指针会在相交的地方相遇
删除链表的倒数第n个节点快慢指针,快指针先走n步,然后快慢指针一起走,当快指针走到尾部时,慢指针的下一个节点就是要删除的节点
反转链表反转整个链表递归实现
反转前n个节点basecase为1,记录一个后驱节点
反转mn区间的节点m==1,不为1则前进到触发m==1
k个一组反转链表递归实现,然后反转前n个节点
拆分链表注意虚拟头节点的应用,在使用的时候用next进行操作,返回dum.next
记住那几个图是关键
前缀和专题
设计模式——策略模式
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748package mainimport "fmt"// 策略接口type PaymentStrategy interface { Pay(amount float64)}// 具体策略:支付宝支付type AlipayStrategy struct{}func (s *AlipayStrategy) Pay(amount float64) { fmt.Printf("支付宝支付:¥%.2f\n", amount)}// 具体策略:微信支付type WeChatPayStrategy struct{}func (s *WeChatPayStrategy) Pay(amount float64) { fmt.Printf("微信支付:¥%.2f\n", amount) ...
数据库:说一说InnoDB刷脏页
为什么SQL语句正常时很快,有时很慢?也就是“抖”一下(本质就是问说一说InnoDB刷脏页)原因分析
可能是在刷脏页(flush)(脏页即当内存数据页跟磁盘数据页内容不一致的时候,称这个内存页为脏页。)
第一种情况是redo log写满了。这时候系统会停止所有更新操作,把checkpoint往前推进,并且刷脏页,redo log留出空间可以继续写。
第二种情况就是系统内存不足。这时候会要淘汰一些数据页,如果淘汰的是“脏页”,需要先将脏页写入磁盘。
InnoDB缓冲池中的内存页的三种状态
还没使用的
使用了的干净页
使用了的脏页
申请数据页
当要读入的数据页没有在内存的时候,就必须到缓冲池中申请一个数据页。这时候得把最久不使用的数据页从内存中淘汰掉。当淘汰的是脏页的时候就得先刷脏页,出现以下两种情况便会影响性能
一个查询要淘汰的脏页个数太多,导致这个查询的响应时间明显变长。
日志写满了,更新全堵住,写性能跌为0。
第三种情况是MySQL认为系统处于“空闲”状态,会进行刷脏页,但既然都是空闲了,不太可能影响性能
第四种情况是MySQL正常关闭的情况,也会刷脏页。正常关闭了, ...
计网-传输层八股(一)
3.10 简述 TCP 和 UDP 的区别,它们的头部结构是什么样的
1、有连接,无连接
2、按序到达,提供超时重传;U不保证按序到达,甚至不保证到达
3、T首部20B以上,U只需8B
4、TCP有流量控制和拥塞控制;U无,网络堵塞不影响发送的速率
5、T是一对一的;U反过来
6、T面向字节流,数据没有边界,会出现粘包拆包问题;U面向报文段,有消息边界
7、可靠,不可靠
8、速度快慢
9、应用场景,t适合对连接可靠性要求比较高,传输量大的场景,比如;u适合实时性高的场景,比如视频通话,游戏等
头部结构
源目序确首保标窗校紧
udp:源目长校
3.8 简述 TCP 三次握手和四次挥手的过程
sasa
fafa
3.9 说说 TCP 2次握手行不行?为什么要3次
tcp连接双方都维护了一个序列号,标识哪些是已经接收的包,三次握手是告知并确认序列起始值的毕竟步骤
若两次,最多只有c的序列号能被s确认,s不能确认c的
3.12 简述 TCP 连接 和 关闭的状态转移
closed-listen(s端监听端口)-syn_sent(第一次)-syn_rcvd(第二次)-establishe ...
gate io
大体上MySQL可以分为Server层和引擎层两个部分Server层
Server层包括连接器、查询缓存、分析器、优化器、执行器,涵盖MySQL的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
连接器
基本概念
当客户端连接到数据库上的时候,首先接待的便是连接器,连接器负责跟客户端建立连接,获取权限,维持和管理连接。
连接流程
连接的命令如下-h$ip -p$port -u$user -p 接着输入密码。完成TCP握手后连接器就会开始身份认证。如果用户或者密码不对就会报Access denied for user错误,客户端结束运行。如果认证通过,接下来连接器会到权限表里面获取当前用户的所有权限。之后该连接的所有权限判断都依据当前获取的权限,意味着即使权限被修改了,也需要重新连接才能使用新的权限。
完成连接后,如果没有操作该连接便会进入空闲状态,可在show processlist里面查看连接的状态。如果连接超过wait_timeout时间没有动作,默认是8小时,则会将连接断开,如果此时再 ...
数据库-索引
目的
索引的出现是为了提高数据查询的效率,就像书的目录一样。索引是一种特殊的文件,包含对数据表中所有记录的引用指针,通常使用B树及其变种B+树
索引的优缺点优点
可以加快查询速度
可以在查询中使用优化隐藏器,提高系统性能
缺点
创建和维护索引需要耗费时间,降低增删改的执行效率
需要占用物理空间。
索引的常见模型基本概念
实现索引的方式有很多,可用于提高读写效率的数据结构也很多,下面从使用的角度介绍三个比较常用、简单的数据结构的区别:哈希表、有序数组和搜索树。
哈希表是把key用哈希函数放到一个确定的位置,然后把value放在数组的这个位置,当多个key换算成同一个位置,则使用链表存储,查询的时候遍历链表即可。但是哈希表做区间查询速度慢,适用于只有等值查询的场景,比如Memcached以及其他一些NoSQL引擎。
有序数组在等值查询和范围查询中的性能都很优秀,递增的ID可通过二分法快速查询。但是在更新数据时的时间复杂度会是On,所以有序数组只适用于静态存储引擎,比如你要保存的是 2017 年某个城市的所有人口信息,这类不会再修改的数据。
二叉搜索树查询更新复杂度都是logn。虽然二 ...
数据库-普通索引和唯一索引怎么选择【索引】
针对这个问题,就涉及到了change buffer的相关概念change buffer基本概念
当需要更新一个数据页的时候,如果数据页在内存中就直接更新;而如果这个数据页没有在内存中,在不影响数据一致性的前提下,InnoDB会将这些更新操作缓存在change buffer中,在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行change buffer中与这个页有关的操作。将change buffer中的操作应用到原数据页的操作叫merge,除了访问该数据页会触发merge外,有后台线程会定期merge,数据库正常关闭的时候也会merge。
change buffer 用的是 buffer pool 里的内存,因此不能无限增大。change buffer 的大小,可以通过参数 innodb_change_buffer_max_size 来动态设置。这个参数设置为 50 的时候,表示 change buffer 的大小最多只能占用 buffer pool 的 50%。
什么条件下可以使用change buffer
对于唯一索引来说插入操作需要先判断是否唯一,就需要将数据页读入 ...
数据库-日志系统
更新语句的执行流程?
和查询流程不同的是,更新语句还要涉及两个重要的日志模块,分别是redo log(重做日志)和binlog(归档日志)。
redo log
问题提出
加入对于MySQL的每次更新操作都要写进磁盘,然后磁盘也得找到对应的那条记录,然后才能更新,整个过程的IO、查询成本太高。
解决方案(WAL)
基本概念(写日志,更新,跟新,固定,循环,crashsafe)
为了解决这个问题,MySQL使用到了WAL技术,全称Write-Ahead Logging。它的关键点是先写日志,再写磁盘。具体来说,当有一条记录需要更新时,InnoDB引擎会先把记录写到redo log里面,并且更新内存,这时候更新操作就算完成了。同时InnoDB会再实弹的时候将这个操作记录更新到磁盘里面。InnoDB的redo log是固定大小的,比如可以配置为一组4个文件,一个文件1GB,总共4GB,写入时,从头开始,写到末尾就回到开头,循环写。有了redo log,InnoDB就可以保证即使数据库发生异常重启,之前提交的记录也不会丢失,该能力称为crash-safe。redo log是InnoDB引擎 ...
gate.io
事务的基本概念
事务就是保证一组数据库操作,要么全部成功,要么全部失败。在MySQL中,事务支持实在引擎层实现的,其中MyISAM引擎不支持事务。
隔离性与隔离级别基本概念
事务有4大特性ACID,分别是原子性、一致性、隔离性、持久性,隔离性便是其中之一。
当数据库上有多个事务在同时执行时,可能出现脏读、不可重复读、幻读(TODO:解释这三个名词)的问题,为了解决这些问题,引出了“隔离级别”的概念。隔离得越严实,效率就会越低,因此需要在二者之间找到平衡。
SQL标准的事务隔离级别包括:读未提交、读提交、可重复读和串行化。
读未提交是指其他事务能够读到一个没有提交的事务的变更。
读提交是指其他事务能够读到一已提交的事务的变更。
可重复读是指一个事务执行过程中读到的数据总是和事务启动时读到的一致。
串行化是指对于同一行记录,写加写锁,读加读锁,多个写操作串行访问。
视图
在实现上,数据库里面会创建一个视图,访问的时候以视图的逻辑为准。在“可重复读”隔离级别下,这个视图是在事务启动的时候创建的,整个事务存在期间都用这个视图。在“读提交”隔离级别下,这个视图是在每个SQL语句开始执行时 ...
开发模板
molloc
molloc有两种实现方式,brk和mmap。当申请内存小于128kb时使用brk,大于则使用mmap。brk申请的空间在free释放时不会真的释放,而是会放回内存池;它的好处是可以一次分配更大内存,避免频繁申请内存带来的切换开销;但是会产生内存碎片
mmap申请的内存空间在free时会归还给系统。但是每次mmap申请的内存第一次访问都需要触发缺页中断;并且需要进入内核,要频繁的状态切换。mmap的原理时直接将虚拟地址与内核缓冲区地址进行映射,避免内核缓冲区到用户缓冲区的copy
零拷贝
零拷贝是说不需要CPU将数据拷贝到另一个区域。
首先是DMA代替CPU将数据从磁盘缓冲区调入内核缓冲区。
由于数据加工都是在内核空间完成的,因此也不需要将数据从内核缓冲区拷贝到用户缓冲区。这一步有两种方法
第一种是使用mmap+write。用mmap代替read,避免copy,此时仍然需要4次状态切换以及一次缓冲区到socket的拷贝
第二种是使用sendfile。用sendfile代替read和write,这样只需要两次状态切换。同时缓冲区直接通过SGDMA传到网卡,实现真正的零拷贝 ...