├── .gitignore ├── 网络协议 ├── 快速下载.md ├── 两台机器不通,如何调试?.md ├── 揭秘RTMP流媒体协议.md ├── RARP协议的作用.md ├── 一个局域网里面有多个交换机,会出现什么问题.md ├── STP协议的缺点.md ├── TCP协议有心跳机制,为何应用层还要做心跳.md ├── UDP的特点及使用场景.md ├── TCP和UDP的区别.md └── HTTP状态码.md ├── 算法与数据结构 ├── 递归 │ └── 对递归的理解.md ├── 队列 │ └── 哪些场景中会用到队列的排队请求?.md ├── 排序 │ └── 基于链表存储,排序算法思考?.md ├── 栈 │ └── JVM中的"栈"和数据结构中的"栈"是一回事吗?.md ├── 树 │ ├── 散列表、二叉查找树对比.md │ └── 树的概念.md ├── 二分查找 │ └── 如何快速定位IP对应的省份地址.md ├── 跳表 │ └── 为什么Redis要用跳表来实现有序集合,而不是红黑树.md ├── 常见面试题 │ └── 判断是否为2的幂.md ├── 散列表 │ └── 如何设计一个工业级的散列表.md └── 哈希算法 │ └── 哈希算法的应用场景.md ├── MySQL ├── 重建索引.md ├── 1.md └── 2.md ├── 区块链 └── 比特币中PoW的优劣.md ├── 分布式系统 └── PoW,Paxos,Raft对比.md ├── Go语言 ├── string和[]byte和[]rune的区别.go └── 实现Interface时value与pointer的不同.go ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | -------------------------------------------------------------------------------- /网络协议/快速下载.md: -------------------------------------------------------------------------------- 1 | - 下载文件可以使用HTTP或FTP,中心化下载 2 | - P2P协议:一种是以来tracker,即元数据集中,文件数据分散;另一种基于分布式的哈希算法,元数据和文件数据全部分散 3 | -------------------------------------------------------------------------------- /网络协议/两台机器不通,如何调试?.md: -------------------------------------------------------------------------------- 1 | ### 问题描述 2 | 在一个比较大的网络中,如果两台机器不通,你知道应该用什么方式调试吗? 3 | 4 | ### 解答 5 | ping + 抓包工具,如 wireshark 6 | -------------------------------------------------------------------------------- /网络协议/揭秘RTMP流媒体协议.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### 基于RTMP的视频流传输的机制存在什么问题?如何进行优化? 4 | ``` 5 | 1. RTMP基于TCP协议,TCP保证有序,拥塞控制,流量控制,延迟很高,不适合做实时流传输 6 | 2. 改进:引进UDP协议 7 | ``` 8 | -------------------------------------------------------------------------------- /网络协议/RARP协议的作用.md: -------------------------------------------------------------------------------- 1 | ### 问题描述 2 | RARP协议,已知MAC求IP,可以用来做什么 3 | 4 | ### 解答 5 | RARP可以用于局域网管理员想指定机器IP(与机器绑定,不可变),又不想每台机器去设置静态IP 6 | 7 | 可以在RARP服务器上配置MAC和IP对应的ARP表 8 | -------------------------------------------------------------------------------- /算法与数据结构/递归/对递归的理解.md: -------------------------------------------------------------------------------- 1 | ##### 优缺点 2 | - 优点: 简洁高效 3 | - 缺点: 堆栈溢出、重复计算、函数调用耗时多、空间复杂度高 4 | 5 | 6 | ##### 平时调试代码喜欢使用IDE的单步跟踪功能,但规模比较大、递归层次很深的递归代码,几乎无法使用这种调试方式,有什么好的调试方法吗? 7 | - 打印日志发现递归值 8 | - 结合条件断点进行调试 9 | -------------------------------------------------------------------------------- /网络协议/一个局域网里面有多个交换机,会出现什么问题.md: -------------------------------------------------------------------------------- 1 | ### 问题描述 2 | 如果一个局域网里面有多个交换机,ARP广播的模式会出现什么问题呢? 3 | 4 | ### 解答 5 | ARP广播时,交换机会将一个端口收到的包转发到其它所有的端口上 6 | 7 | 比如数据包经过交换机A到达交换机B,交换机B又将包复制为多份广播出去。 8 | 9 | 如果整个局域网存在一个环路,使得数据包又重新回到了最开始的交换机A,这个包又会被A再次复制多份广播出去。 10 | 11 | 如此循环,数据包会不停得转发,而且越来越多,最终占满带宽,或者使解析协议的硬件过载,行成广播风暴。 12 | -------------------------------------------------------------------------------- /网络协议/STP协议的缺点.md: -------------------------------------------------------------------------------- 1 | ### 问题描述 2 | STP协议能够很好的解决环路问题,但是也有它的缺点,你能举几个例子吗? 3 | 4 | ### 解答 5 | > - 在数据结构中,有一个方法叫做**最小生成树**,有环的我们称为**图**,将图中的环破了,就生成了**树** 6 | > - 在计算机网络中,生成树的算法叫做**STP**,全称**Spanning Tree Protocol** 7 | > - STP协议通过交换机之间互相比武的方式,最终所有的交换机,环被打破,生成一棵树 8 | 9 | 缺点: 10 | 11 | 对于跨地域甚至跨国组织的网络支持,计算量很大 12 | -------------------------------------------------------------------------------- /网络协议/TCP协议有心跳机制,为何应用层还要做心跳.md: -------------------------------------------------------------------------------- 1 | 2 | ### TCP协议有心跳机制,为何应用层还要做心跳? 3 | - tcp连接建立以后,隔7200s(2小时)发送探针检测连接,失败后重试10次,每次超时时间75s,虽然可修改配置 4 | - TCP面向连接,是为了在客户端和服务端维护连接,而建立一定的数据结构来维护双方交互的状态,是虚拟的 5 | - 在某种情况下,服务器CPU负载100%了,此时应用服务器程序无法响应业务请求,但是TCP连接依然还在,此时需要客户端主动断开连接然后请求其它服务器 6 | - 类似的,客户端也可能突然进程挂掉,未通知服务器程序断开TCP连接,服务器程序认为客户端还活着,未能及时回收TCP连接,业务层做心跳,服务器程序能及时知道客户端状态 7 | -------------------------------------------------------------------------------- /算法与数据结构/队列/哪些场景中会用到队列的排队请求?.md: -------------------------------------------------------------------------------- 1 | - 高性能队列Disruptor、Linux环形缓存,使用了循环并发队列 2 | 3 | - Java concurrent并发包利用ArrayBlockingQueue来实现公平锁 4 | 5 | - 阻塞队列实现一个"生产者-消费者模型" 6 | 7 | - 基于数组实现有界队列(blounded queue),线程池中排队的请求超过队列大小,接下来的请求会被拒绝,用于对响应时间敏感的系统 8 | 9 | - 数据库连接池 10 | 11 | - 分布式消息队列 12 | 13 | - Redis的消息队列以及管道技术 14 | 15 | - 高并发请求时,请求放到队列中 16 | 17 | - 对象池 18 | -------------------------------------------------------------------------------- /算法与数据结构/排序/基于链表存储,排序算法思考?.md: -------------------------------------------------------------------------------- 1 | ##### 前提 2 | 应该有个前提,是否允许修改链表的节点value值,还是只能改变节点的位置。一般而言,考虑只能改变节点位置 3 | 4 | ##### 冒泡排序 5 | 冒泡排序相比于数组实现,比较次数一致,但交换时操作更复杂 6 | 7 | ##### 插入排序 8 | 插入排序,比较次数一致,不需要再有后移操作,找到位置后可以直接插入,但排序完毕后可能需要倒置链表 9 | 10 | ##### 选择排序 11 | 选择排序比较次数一致,交换操作同样比较麻烦 12 | 13 | ##### 总结 14 | 综上,时间复杂度和空间复杂度并无明显变化,若追求极致性能,冒泡排序的时间复杂度系数会变大,插入排序系数会减小,选择排序无明显变化。 15 | -------------------------------------------------------------------------------- /算法与数据结构/栈/JVM中的"栈"和数据结构中的"栈"是一回事吗?.md: -------------------------------------------------------------------------------- 1 | 2 | - 内存中的堆栈和数据结构堆栈不是一个概念,可以说内存中的堆栈是真实存在的物理区,数据结构中的堆栈是抽象的数据存储结构。 3 | - 内存空间在逻辑上分为三部分:代码区、静态数据区和动态数据区,动态数据区又分为栈区和堆区。 4 | - 代码区:存储方法体的二进制代码。高级调度(作业调度)、中级调度(内存调度)、低级调度(进程调度)控制代码区执行代码的切换。 5 | - 静态数据区:存储全局变量、静态变量、常量,常量包括final修饰的常量和String常量。系统自动分配和回收。 6 | - 栈区:存储运行方法的形参、局部变量、返回值。由系统自动分配和回收。 7 | - 堆区:new一个对象的引用或地址存储在栈区,指向该对象存储在堆区中的真实数据。 8 | -------------------------------------------------------------------------------- /MySQL/重建索引.md: -------------------------------------------------------------------------------- 1 | ### 为什么要重建索引 2 | - 索引可能因为删除,或者页分裂等原因,导致数据页有空洞,重建索引的过程会创建一个新的索引,把数据按顺序插入,这样页面的利用率最高,也就是索引更紧凑、更省空间。 3 | 4 | - 今天这个 alter table T engine=InnoDB 让我想到了我们线上的一个表, 记录日志用的, 会定期删除过早之前的数据. 最后这个表实际内容的大小才10G, 而他的索引却有30G. 在阿里云控制面板上看,就是占了40G空间. 这可花的是真金白银啊. 5 | 后来了解到是 InnoDB 这种引擎导致的,虽然删除了表的部分记录,但是它的索引还在, 并未释放. 6 | 只能是重新建表才能重建索引. 7 | 8 | - 不论是删除主键还是创建主键,都会将整个表重建。所以连着执行这两个语句的话,第一个语句就白做了。这两个语句,你可以用这个语句代替 : alter table T engine=InnoDB 9 | -------------------------------------------------------------------------------- /算法与数据结构/树/散列表、二叉查找树对比.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### 散列表、二叉查找树 对比 4 | 5 | - 散列表的插入、删除、查找,时间复杂度可以做到O(1) 6 | - 二叉查找树在比较平衡的情况下,插入、删除、查找操作时间复杂度才是O(logn) 7 | 8 | #### 为什么还要有二叉查找树? 9 | - 散列表的数据无序存储,先进行排序才能有序输出,二叉查找树只需要中序遍历就可有序输出,O(n)的时间复杂度 10 | - 散列表扩容耗时很多,散列冲突时性能不稳定;尽管二叉查找树在不平衡时,性能也不稳定,但在工程中,最常用的平衡二叉查找树的性能可以稳定在O(logn) 11 | - 散列表查找等操作时间复杂度是常量级,但是哈希冲突存在,常量不一定比logn小,加上哈希函数的耗时,也不一定比平衡二叉查找树的效率高 12 | - 散列表的构造比二叉查找树复杂,需要考虑 散列函数的设计、冲突解决办法、扩容、缩容等,而平衡二叉查找树只需要考虑平衡性一个问题,而且这个问题的解决方案比较成熟、稳定 13 | - 为了避免散列冲突,散列表装载因子不能太大,浪费内存空间 14 | -------------------------------------------------------------------------------- /算法与数据结构/二分查找/如何快速定位IP对应的省份地址.md: -------------------------------------------------------------------------------- 1 | ### 如何快速定位IP对应的省份地址? 2 | ``` 3 | [202.102.133.0, 202.102.133.255] 山东东营市 4 | [202.102.135.0, 202.102.136.255] 山东烟台 5 | [202.102.156.34, 202.102.157.255] 山东青岛 6 | [202.102.48.0, 202.102.48.255] 江苏宿迁 7 | [202.102.49.15, 202.102.51.251] 江苏泰州 8 | [202.102.56.0, 202.102.56.255] 江苏连云港 9 | ``` 10 | - 如果IP区间与归属地的对应关系不经常更新,可以先预处理这12万条数据,让其按照起始IP从小到大排序 11 | - IP地址可以转化为32位的整型数,从小到大排序 12 | - 问题转化为"在有序数组中,查找最后一个小于等于某个给定值的元素"了 13 | - 当我们查询某个IP时,可以先通过二分查找,找到最后一个起始IP小于等于这个IP的IP区间,然后检查这个IP是否在这个IP区间内,如果在,我们就取出对应的归属地显示;如果不在,返回未查找到 14 | -------------------------------------------------------------------------------- /区块链/比特币中PoW的优劣.md: -------------------------------------------------------------------------------- 1 | # 比特币中PoW的优劣 2 | 3 | ## 解决 4 | * **提高对数据篡改的成本**。让你修改数据需要付出大量的算力,而区块链的数据相互依赖,导致 " 一处改处处改 ",因此你要完全修改就需要付出大量的算力。 5 | 6 | * **提高网络中有不同声音的成本**。试想,如果一个网络有不同的人给出来了不同的账本,而且都合法,你会信谁的?所以,挖矿可以解决这个事。让你要做一个伪造账本的成本极其地大,而校验账本的成本很小。 7 | 8 | * **解决分歧**。当有不同声音的时候,即区块链出现分叉时,所有的矿工只能选择其中一个分支(因为没人有算力可以同时发出两个不同的声音)。于是,大多数人选择的那个分支就会成为事实,少数人选的那头就被遗忘了。**这让整个去中心化系统的一致性,不再以人数多认可的数据为准,而是以算力多的人认可的数据为准。** 9 | 10 | ## 存在的问题 11 | * **越来越中心化地记账。** 本来是要大众一起参与去中心化的事,现在因为算力的问题,因为 GPU 的出现,导致一般人几乎无法参与其中了。 12 | 13 | * **越来越跑不动。** 比特币今天的链越来越长,导致要验证数据是否正确的成本越来越高,一般人的电脑基本都快要跑不起来了。 14 | -------------------------------------------------------------------------------- /网络协议/UDP的特点及使用场景.md: -------------------------------------------------------------------------------- 1 | ### 三大特点 2 | - 沟通简单 3 | ``` 4 | 1. 不需要大量的数据结构、处理逻辑、包头字段,相信网络世界是美好的,容易送达,不容易被丢弃 5 | ``` 6 | - 轻信他人 7 | ``` 8 | 1. 不会建立连接,监听端口号,谁都可以给他传数据,也可以传给任何人数据,甚至可以同时给多个人传数据 9 | ``` 10 | - 愣头青,做事不懂权变 11 | ``` 12 | 1. 不知道何时坚持,何时退让,不会根据网络情况进行发包的拥塞控制,该怎么发还怎么发 13 | ``` 14 | ### 使用场景 15 | 1. 需要资源少,在网络情况好的内网,或者对丢包不敏感的应用 16 | ``` 17 | DHCP就是基于UDP协议,一般或者IP是内网请求,失败了没事 18 | 19 | PXE可以在启动时自动安装操作系统,下载镜像时使用的TFTP,也是基于UDP协议 20 | ``` 21 | 2. 不需要一对一沟通,建立连接,而是可以广播的应用 22 | 23 | 3. 需要处理速度快,延时低,可以容忍少数丢包,但是要求即使网络拥塞,也毫不退缩,一往无前 24 | ``` 25 | 直播应用,基于UDP实现自己的视频传输协议 26 | 27 | 实时游戏 28 | 29 | 物联网是嵌入式系统,维护TCP协议代价太大 30 | ``` 31 | -------------------------------------------------------------------------------- /算法与数据结构/跳表/为什么Redis要用跳表来实现有序集合,而不是红黑树.md: -------------------------------------------------------------------------------- 1 | ### 为什么Redis要用跳表来实现有序集合,而不是红黑树 2 | Redis 中的有序集合是通过跳表来实现的,严格点讲,其实还用到了散列表。不过散列表我们后面才会讲到,所以我们现在暂且忽略这部分。如果你去查看 Redis 的开发手册,就会发现,Redis 中的有序集合支持的核心操作主要有下面这几个: 3 | 4 | - 插入一个数据; 5 | - 删除一个数据; 6 | - 查找一个数据; 7 | - 按照区间查找数据(比如查找值在 [100, 356] 之间的数据); 8 | - 迭代输出有序序列。 9 | 10 | 其中,插入、删除、查找以及迭代输出有序序列这几个操作,红黑树也可以完成,时间复杂度跟跳表是一样的。但是,按照区间来查找数据这个操作,红黑树的效率没有跳表高。 11 | 12 | 对于按照区间查找数据这个操作,跳表可以做到 O(logn) 的时间复杂度定位区间的起点,然后在原始链表中顺序往后遍历就可以了。这样做非常高效。 13 | 14 | 当然,Redis 之所以用跳表来实现有序集合,还有其他原因,比如,跳表更容易代码实现。虽然跳表的实现也不简单,但比起红黑树来说还是好懂、好写多了,而简单就意味着可读性好,不容易出错。还有,跳表更加灵活,它可以通过改变索引构建策略,有效平衡执行效率和内存消耗。 15 | -------------------------------------------------------------------------------- /网络协议/TCP和UDP的区别.md: -------------------------------------------------------------------------------- 1 | 1. TCP面向连接(三次握手),UDP面向无连接 2 | ``` 3 | 所谓的面向连接,是为了在客户端和服务端维护连接,而建立一定的数据结构来维护双方交互的状态, 4 | 用这样的数据结构来保证所谓的面向连接的特性 5 | ``` 6 | 2. TCP提供可靠交付,UDP不可靠 7 | ``` 8 | - s通过TCP连接传输的数据,无差错、不丢失、不重复、并且按序到达 9 | - IP包没有任何可靠性保证 10 | - UDP继承了IP包的特性,不保证不丢失,不保证按顺序到达 11 | ``` 12 | 3. TCP是面向字节流的,UDP是面向数据报 13 | ``` 14 | - IP包是一个个的IP包,之所以变成流,是TCP自己的状态维护做的事情 15 | - UDP继承了IP的特点,基于数据报,一个一个地发,一个一个地收 16 | ``` 17 | 4. TCP是可以拥塞控制的,UDP无控制 18 | ``` 19 | - 当TCP意识到包丢弃了或者网络环境不好了,会根据情况调整自己的行为,调整发送的速度(流量控制、拥塞控制) 20 | - UDP不会,应用让我发,我就发,管它洪水滔天 21 | ``` 22 | 5. TCP其实是一个有状态服务,UDP无状态 23 | ``` 24 | - TCP是有脑子的,精确地记着发送了没有,接收到没有,发送到哪个了,应该接收哪个了 25 | - UDP是无脑子的,天真无邪,发出去就发出去了 26 | ``` 27 | -------------------------------------------------------------------------------- /算法与数据结构/常见面试题/判断是否为2的幂.md: -------------------------------------------------------------------------------- 1 | 2 | ### 递归 3 | 4 | ```Golang 5 | func isPowerOfTwo(n int) bool { 6 | if n == 0 { 7 | return false 8 | } 9 | //2的幂一直除以2,最后等于1 10 | if n == 1 { 11 | return true 12 | } 13 | //n必须为偶数 14 | if n % 2 != 0 { 15 | return false 16 | } 17 | return isPowerOfTwo(n / 2) 18 | } 19 | ``` 20 | 21 | ### 位运算 22 | 23 | ```Golang 24 | func isPowerOfTwo(n int) bool { 25 | if n <= 0 { 26 | return false 27 | } 28 | //n为2的幂,二进制表示时:一定为 某位是1,其它位都是0,例如4:00000100 29 | //n-1,二进制表示时,n的二进制为1的位右边全是1,例如3:00000011 30 | //所以 & 运算后,结果是 00000000,即0,false 31 | return !(n & (n-1)) 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /分布式系统/PoW,Paxos,Raft对比.md: -------------------------------------------------------------------------------- 1 | # 对比PoW,Paxos/Raft 2 | 3 | ### 不同点 4 | * 对于 Paxos/Raft,其需要 Leader 选举,而对于比特币或者以太坊这样的无中心化的方式是没有 leader 的 5 | * 对于 Paxos/Raft,加入其网络(集群)的结点前提假设都是受信的。然而,对于比特币 / 以太坊来说,其前提假设都是不受信的,它们只相信,超过一半的结点所同意的东西 6 | * 对于 Paxos/Raft,需要事先对整个集群中的结点数有定义,而无中心化的比特币和以太坊中的结点是想来就来,想走就走,来去自由。如果 Paxos/Raft 在这样的环境下,其会处于一个非常尴尬的境地——要能随时进行伸缩。而且,Paxos/Raft 并不适合在一个非常大的网络中玩(比如上百万的结点) 7 | 8 | ### 相同点 9 | * 它们都是一致性的算法 10 | * 对系统的修改总是需要一个人来干(区块链用 PoW 消耗资源,让提案变得困难,Paxos/Raft 用领导选举)。 11 | * 系统中暂时的不一致是可以被修正的(区块链会考虑最长链,牺牲了强一致性,保证了可用性,Paxos/Raft 如果没有超过半数的结点在线,会停止工作,牺牲了可用性,保证了强一性) 12 | 13 | ### 总结 14 | 总之,区块链所面对的无中心化的 P2P 网络要比 Paxos/Raft 所面对的相对中心式分布式网络要复杂多得多。所以,不太可能使用 Paxos/Raft 协议来替代 PoW 协议。除非,你想干一个相对中心化的区块链,然而这就成了区块链的一个悖论了 15 | -------------------------------------------------------------------------------- /算法与数据结构/散列表/如何设计一个工业级的散列表.md: -------------------------------------------------------------------------------- 1 | 2 | ### 工业级的散列表应该具有那些特性? 3 | - 快速的查询、插入、删除操作 4 | - 内存占用合理,不能浪费过多内存 5 | - 性能稳定,极端情况下,散列表的性能也不会退化到无法接受的情况 6 | 7 | ### 如何实现散列表? 8 | - 设计合适的散列函数 9 | - 定义装载因子阈值,并且设计动态扩容策略 10 | - 合适的散列冲突解决方法 11 | 12 | ### 工业级散列表举例分析 13 | Java中的HashMap 14 | 15 | 1. 初始大小 16 | 17 | 默认16,可以修改默认初始大小,减少动态扩容的次数,大大提高性能 18 | 19 | 2. 装载因子和动态扩容 20 | 21 | 默认0.75,当元素超过0.75容量使,自动扩容,每次扩容为原来的两倍 22 | 23 | 3. 散列冲突解决办法 24 | 25 | 底层采用链表,长度太长(默认8),转换为红黑树,少于6,转为链表 26 | 27 | 4. 散列函数 28 | 29 | 追求简单高效、分布均匀 30 | 31 | 32 | ### 如何避免低效的扩容? 33 | - 特殊情况下,当装载因子已经达到阈值,需要先扩容,再插入数据,此时,插入数据就会变的很慢,甚至无法接受 34 | - 一次性扩容机制不合适 35 | - 当装载因子达到阈值,我们只申请空间,并不把老数据搬到新散列表中 36 | - 当有新数据插入时,我们将新数据插入新散列表中,并且从老的散列表拿出一个数据搬到新散列表 37 | - 经过多次插入操作,老的散列表就全部搬到新散列表中,均摊的方法,任何情况下,插入数据的时间复杂度都是O(1) 38 | - 查询操作,为了兼容新、老散列表,先从新散列表查找,未找到再去老的散列表 39 | -------------------------------------------------------------------------------- /MySQL/1.md: -------------------------------------------------------------------------------- 1 | 2 | ### 问题描述 3 | MySQL/当备库用–single-transaction做逻辑备份的时候,如果从主库的binlog传来一个DDL语句会怎么样?.md 4 | 5 | ### 解答 6 | 假设这个 DDL 是针对表 t1 的, 这里我把备份过程中几个关键的语句列出来: 7 | ``` 8 | Q1:SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; 9 | Q2:START TRANSACTION WITH CONSISTENT SNAPSHOT; 10 | /* other tables */ 11 | Q3:SAVEPOINT sp; 12 | /* 时刻 1 */ 13 | Q4:show create table `t1`; 14 | /* 时刻 2 */ 15 | Q5:SELECT * FROM `t1`; 16 | /* 时刻 3 */ 17 | Q6:ROLLBACK TO SAVEPOINT sp; 18 | /* 时刻 4 */ 19 | /* other tables */ 20 | ``` 21 | 22 | 在备份开始的时候,为了确保 RR(可重复读)隔离级别,再设置一次 RR 隔离级别 (Q1); 23 | 24 | 1.如果在 Q4 语句执行之前到达,现象:没有影响,备份拿到的是 DDL 后的表结构。 25 | 26 | 2.如果在“时刻 2”到达,则表结构被改过,Q5 执行的时候,报 Table definition has changed, please retry transaction,现象:mysqldump 终止; 27 | 28 | 3.如果在“时刻 2”和“时刻 3”之间到达,mysqldump 占着 t1 的 MDL 读锁,binlog 被阻塞,现象:主从延迟,直到 Q6 执行完成。 29 | 30 | 4.从“时刻 4”开始,mysqldump 释放了 MDL 读锁,现象:没有影响,备份拿到的是 DDL 前的表结构。 31 | -------------------------------------------------------------------------------- /算法与数据结构/哈希算法/哈希算法的应用场景.md: -------------------------------------------------------------------------------- 1 | 2 | ### 哈希算法有哪些应用场景 3 | 4 | #### 安全加密 5 | 6 | #### 唯一标识 7 | 从图片的二进制码串,开头取100字节,中间100字节,最后100字节,对300个字节哈希算法得到一个哈希字符串,作为图片唯一标识 8 | 9 | #### 数据校验 10 | P2P协议时,验证文件块是否完整(每个文件块的哈希值存在种子中) 11 | 12 | #### 哈希函数 13 | 14 | #### 负载均衡 15 | 对IP地址或会话ID计算哈希值,对服务器列表取模,得到服务器编号,路由过去 16 | 17 | #### 数据分片 18 | ##### 如何统计"搜索关键词"出现的次数 19 | - 1T日志,依次读出关键词,计算哈希值取模,分配到机器上,相同关键词就被分到同一个机器上,每个机器分别计算关键词出现次数,最后合并结果 20 | - 这个处理过程,也是MapReduce的基本设计思想 21 | 22 | ##### 如何快速判断图片是否在图库中? 23 | - 有1亿张图片,每个图片取唯一标识,构建散列表 24 | - 多台机器,每台机器维护一部分散列表(哈希值取模) 25 | - 判断一个图片是否在图库中,先计算唯一标识,取模得到机器编号,取对应的机器上的散列表中查找 26 | 27 | 估算1亿张图片构建散列表大约需要多少台机器 28 | - 散列表每个数据单元包含 哈希值和图片路径,MD5哈希值长度为128bit,也就是16字节,文件路径上限是256字节,假设平均128字节,如果用链表法解决哈希冲突,需要存指针,指针占8个字节,所以每个数据单元占用152字节 29 | - 假设一台机器内存为2GB,散列表的装载因子为0.75,一台机器大约1000万(2GB*0.75/152)张图片构建散列表,大约需要十几台机器 30 | 31 | #### 分布式存储 32 | - 对数据哈希取值,对机器个数取模,决定缓存机器编号 33 | - 一致性哈希算法,构造虚拟的环和虚拟节点 34 | -------------------------------------------------------------------------------- /Go语言/string和[]byte和[]rune的区别.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func printStirng(s string) { 6 | fmt.Print("\nprintStirng:") 7 | for _, char := range s { 8 | fmt.Printf("%d,", char) 9 | } 10 | } 11 | 12 | func printBytes(s string) { 13 | fmt.Print("\nprintBytes:") 14 | bs := []byte(s) 15 | for _, b := range bs { 16 | fmt.Printf("%v,", b) 17 | } 18 | } 19 | 20 | func printRunes(s string) { 21 | fmt.Print("\nprintRunes:") 22 | rs := []rune(s) 23 | for _, r := range rs { 24 | fmt.Printf("%v,", r) 25 | } 26 | } 27 | 28 | func main() { 29 | s1 := "中文" 30 | printStirng(s1) //20013,25991 31 | printBytes(s1) //228,184,173,230,150,135, 32 | printRunes(s1) //20013,25991, 33 | 34 | s2 := "abc" 35 | printStirng(s2) //97,98,99, 36 | printBytes(s2) //97,98,99, 37 | printRunes(s2) //97,98,99, 38 | 39 | //遍历string相当于遍历[]int32,等同于rune(int32),int32相当于4字节的长度,中文英文字符都在长度内 40 | //处理中英文时不同,英文,一个字符即一个字节,中文的UTF-8是一个字符3个字节 41 | } 42 | -------------------------------------------------------------------------------- /Go语言/实现Interface时value与pointer的不同.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Animal interface { 8 | Speak() string 9 | } 10 | 11 | type Dog struct { 12 | } 13 | 14 | func (d Dog) Speak() string { 15 | return "Woof!" 16 | } 17 | 18 | type Cat struct { 19 | } 20 | 21 | func (c *Cat) Speak() string { 22 | return "Meow!" 23 | } 24 | 25 | type Llama struct { 26 | } 27 | 28 | func (l Llama) Speak() string { 29 | return "?????" 30 | } 31 | 32 | type JavaProgrammer struct { 33 | } 34 | 35 | func (j JavaProgrammer) Speak() string { 36 | return "Design patterns!" 37 | } 38 | 39 | func main() { 40 | // https://play.golang.org/p/TvR758rfre 41 | 42 | //为什么Cat{}不算实现了Animal interface? 43 | // &Llama{}算实现了interface? 44 | 45 | //go 会把指针进行隐式转换得到 value,但反过来则不行 46 | 47 | animals := []Animal{Dog{}, Cat{}, Llama{}, &Llama{}, JavaProgrammer{}} 48 | for _, animal := range animals { 49 | fmt.Println(animal.Speak()) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /算法与数据结构/树/树的概念.md: -------------------------------------------------------------------------------- 1 | ### 高度、深度、层数 2 | 3 | ![定义](https://static001.geekbang.org/resource/image/40/1e/4094a733986073fedb6b9d03f877d71e.jpg) 4 | 5 | ![定义](https://static001.geekbang.org/resource/image/50/b4/50f89510ad1f7570791dd12f4e9adeb4.jpg) 6 | 7 | ### 满二叉树 8 | 叶子结点全部在最底层,除了叶子结点之外,每个节点都有左右两个子节点 9 | 10 | ### 完全二叉树 11 | 叶子节点都在最底下两层,最后一层的叶子节点都靠左排列,并且除了最后一层,其他层的节点个数都要达到最大,这种二叉树叫作 12 | 13 | 满二叉树是一种特殊的完全二叉树 14 | 15 | ### 如何存储一颗二叉树 16 | 我们有两种方法,一种是基于指针或者引用的二叉链式存储法,一种是基于数组的顺序存储法。 17 | 18 | #### 链式存储法 19 | ![链式存储](https://static001.geekbang.org/resource/image/12/8e/12cd11b2432ed7c4dfc9a2053cb70b8e.jpg) 20 | 21 | #### 顺序存储法 22 | ![顺序存储](https://static001.geekbang.org/resource/image/14/30/14eaa820cb89a17a7303e8847a412330.jpg) 23 | 24 | ### 顺序存储时,不浪费内存的就是完全二叉树(数组中index=0不算做浪费内存) 25 | 26 | ### 二叉树遍历 27 | ![二叉树遍历](https://static001.geekbang.org/resource/image/ab/16/ab103822e75b5b15c615b68560cb2416.jpg) 28 | 29 | ### 平衡二叉查找树 30 | 31 | 发明平衡二叉查找树这类数据结构的初衷是,解决普通二叉查找树在频繁的插入、删除等动态更新的情况下,出现时间复杂度退化的问题。 32 | 33 | #### 平衡二叉树 34 | 二叉树中任意一个节点的左右子树的高度相差不能大于1 35 | 36 | #### 二叉查找树 37 | 任意一个节点,它的左节点比它小,右节点比它大 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 TomorrowWu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MySQL/2.md: -------------------------------------------------------------------------------- 1 | 2 | ### 问题描述 3 | 假设你的表里面已经有了 city_name(city, name) 这个联合索引,然后你要查杭州和苏州两个城 4 | 市中所有的市民的姓名,并且按名字排序,显示前 100 条记录。如果 SQL 查询语句是这么写的 5 | : 6 | ``` 7 | select * from t where city in ('杭州'," 苏州 ") order by name limit 100; 8 | ``` 9 | 那么,这个语句执行的时候会有排序过程吗,为什么? 10 | 11 | 如果业务端代码由你来开发,需要实现一个在数据库端不需要排序的方案,你会怎么实现呢? 12 | 13 | 进一步地,如果有分页需求,要显示第 101 页,也就是说语句最后要改成 “limit 14 | 10000,100”, 你的实现方法又会是什么呢? 15 | 16 | ### 解答 17 | 18 | 虽然有 (city,name) 联合索引,对于单个 city 内部,name 是递增的。但是由于这条 SQL 语句 19 | 不是要单独地查一个 city 的值,而是同时查了"杭州"和" 苏州 "两个城市,因此所有满足条件的 20 | name 就不是递增的了。也就是说,这条 SQL 语句需要排序 21 | 22 | 那怎么避免排序呢? 23 | 24 | 这里,我们要用到 (city,name) 联合索引的特性,把这一条语句拆成两条语句,执行流程如下: 25 | 1. 执行 select * from t where city=“杭州” order by name limit 100; 这个语句是不需要 26 | 排序的,客户端用一个长度为 100 的内存数组 A 保存结果。 27 | 2. 执行 select * from t where city=“苏州” order by name limit 100; 用相同的方法,假 28 | 设结果被存进了内存数组 B。 29 | 3. 现在 A 和 B 是两个有序数组,然后你可以用归并排序的思想,得到 name 最小的前 100 30 | 值,就是我们需要的结果了。 31 | 如果把这条 SQL 语句里“limit 100”改成“limit 10000,100”的话,处理方式其实也差不多, 32 | 即:要把上面的两条语句改成写: 33 | ``` 34 | select * from t where city=" 杭州 " order by name limit 10100; 35 | 36 | select * from t where city=" 苏州 " order by name limit 10100。 37 | ``` 38 | 这时候数据量较大,可以同时起两个连接一行行读结果,用归并排序算法拿到这两个结果集里, 39 | 按顺序取第 10001~10100 的 name 值,就是需要的结果了。 40 | 当然这个方案有一个明显的损失,就是从数据库返回给客户端的数据量变大了。 41 | 所以,如果数据的单行比较大的话,可以考虑把这两条 SQL 语句改成下面这种写法: 42 | ``` 43 | select id,name from t where city=" 杭州 " order by name limit 10100; 44 | 45 | select id,name from t where city=" 苏州 " order by name limit 10100。 46 | ``` 47 | 然后,再用归并排序的方法取得按 name 顺序第 10001~10100 的 name、id 的值,然后拿着 48 | 这 100 个 id 到数据库中去查出所有记录。 49 | 上面这些方法,需要你根据性能需求和开发的复杂度做出权衡。 50 | -------------------------------------------------------------------------------- /网络协议/HTTP状态码.md: -------------------------------------------------------------------------------- 1 | ### 1xx 2 | 代表请求已被接受,需要继续处理 3 | 4 | 状态码 | 含义 5 | ---|--- 6 | 100 | continue 7 | 101 | Switching Protocols 8 | 102 | Processing 9 | 10 | ### 2xx 11 | 代表请求已成功被服务器接收、理解、并接受 12 | 13 | 状态码 | 含义 14 | ---|--- 15 | 200 | OK:请求已成功 16 | 201 | Created:请求已经被实现,而且有一个新的资源已经依据请求的需要而建立,且其URI已经随Location头信息返回 17 | 202 | Accepted:服务器已接受请求,但尚未处理 18 | 203 | Non-Authoritative Information:服务器是一个转换代理服务器(transforming proxy,例如网络加速器),以200 OK状态码为起源,但回应了原始响应的修改版本 19 | 204 | No Content:服务器成功处理了请求,没有返回任何内容 20 | 205 | Reset Content:服务器成功处理了请求,但没有返回任何内容,要求请求者重置文档视图 21 | 206 | Partial Content:服务器已经成功处理了部分GET请求。类似于迅雷这类的HTTP 下载工具都是使用此类响应实现断点续传或者将一个大文档分解为多个下载段同时下载 22 | 23 | ### 3xx 24 | 代表需要客户端采取进一步的操作才能完成请求,通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明 25 | 26 | 状态码 | 含义 27 | ---|--- 28 | 300 | Multiple Choices:用户或浏览器能够自行选择一个首选的地址进行重定向 29 | 301 | Moved Permanently:被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一 30 | 302 | Found:临时重定向 31 | 303 | See Other:对应当前请求的响应可以在另一个URI上被找到 32 | 304 | Not Modified 33 | 34 | ### 4xx 35 | 客户端看起来可能发生了错误,妨碍了服务器的处理 36 | 37 | 38 | 状态码| 含义 39 | ---|--- 40 | 400 | Bad Request :客户端错误(例如,格式错误的请求语法,太大的大小,无效的请求消息或欺骗性路由请求) 41 | 401 | Unauthorized :该状态码表示当前请求需要用户验证 42 | 402 | Payment Required :最初的意图可能被用作某种形式的数字现金或在线支付方案的一部分,但几乎没有哪家服务商使用 43 | 403 | Forbidden :服务器已经理解请求,但是拒绝执行它 44 | 404 | Not Found : 请求失败,请求所希望得到的资源未被在服务器上发现,但允许用户的后续请求 45 | 405 | Method Not Allowed :请求方法不能被用于请求相应的资源。该响应必须返回一个Allow头信息用以表示出当前资源能够接受的请求方法的列表 46 | 408 | Request Timeout:请求超时。根据HTTP规范,客户端没有在服务器预备等待的时间内完成一个请求的发送,客户端可以随时再次提交这一请求而无需进行任何更改 47 | ### 5xx 48 | 服务器无法完成明显有效的请求 49 | 50 | 状态码 | 含义 51 | ---|--- 52 | 500 | Internal Server Error : 服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理 53 | 501 | Not Implemented :服务器不支持当前请求所需要的某个功能 54 | 502 | Bad Gateway : 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应 55 | 503 | Service Unavailable : 由于临时的服务器维护或者过载,服务器当前无法处理请求。这个状况是暂时的,并且将在一段时间以后恢复 56 | 504 | Gateway Timeout : 作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器收到响应 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # interview 2 | 3 | ## 算法与数据结构 4 | 5 | ### 常见面试题 6 | #### [拜托,面试别再问我TopK了!!!](https://mp.weixin.qq.com/s/FFsvWXiaZK96PtUg-mmtEw) 7 | #### [小米三面面试题](https://github.com/TomorrowWu/golang-algorithms/blob/master/algorithms/uncategorized/%E5%B0%8F%E7%B1%B3%E4%B8%89%E9%9D%A2%E9%9D%A2%E8%AF%95%E9%A2%98/README.md) 8 | #### [判断是否为2的幂](算法与数据结构/常见面试题/判断是否为2的幂.md) 9 | #### [大数乘法](https://github.com/TomorrowWu/golang-algorithms/blob/master/leetcode/0043.multiply-strings/src/multiply-strings.go) 10 | #### [三门问题](https://zh.wikipedia.org/wiki/%E8%92%99%E6%8F%90%E9%9C%8D%E7%88%BE%E5%95%8F%E9%A1%8C) 11 | 12 | ### 数组 13 | #### [实现Array](https://github.com/TomorrowWu/golang-algorithms/blob/master/data-structures/array/array.go) 14 | 15 | ### 链表 16 | #### [实现linked-list及相关操作,链表反转,判断循环链表,合并两个有序链表,删除倒数第n个节点](https://github.com/TomorrowWu/golang-algorithms/blob/master/data-structures/linked-list/singlelinkedlist.go) 17 | #### [单向链表判断是否回文](https://github.com/TomorrowWu/golang-algorithms/blob/master/data-structures/linked-list/palindrome.go) 18 | 19 | ### 栈 20 | #### [为什么函数调用要用“栈”来保存临时变量]() 21 | #### [JVM中的"栈"和数据结构中的"栈"是一回事吗?](算法与数据结构/栈/JVM中的"栈"和数据结构中的"栈"是一回事吗?.md) 22 | #### [栈在表达式求值中应用(带小括号)]() 23 | #### [基于数组实现栈数据结构]() 24 | #### [基于单链表实现栈数据结构]() 25 | #### [基于栈结构实现浏览器前进和后退功能]() 26 | 27 | ### 队列 28 | #### [哪些场景中会用到队列的排队请求?](算法与数据结构/队列/哪些场景中会用到队列的排队请求?.md) 29 | #### [实现无锁并发队列]() 30 | 31 | ### 跳表 32 | #### [为什么Redis要用跳表来实现有序集合,而不是红黑树](算法与数据结构/跳表/为什么Redis要用跳表来实现有序集合,而不是红黑树.md) 33 | 34 | ### 递归 35 | #### [对递归的理解](算法与数据结构/递归/对递归的理解.md) 36 | 37 | ### 排序 38 | #### [特定算法是依赖特定的数据结构的,排序算法一般都是基于数组实现的,如果数据存储在链表中,排序算法还能工作吗?如果能,那相应的时间复杂度、空间复杂度又是多少呢?](算法与数据结构/排序/基于链表存储,排序算法思考?.md) 39 | #### [10个接口访问日志文件,每个文件约300MB,每个文件的日志都是按照时间戳从小到大排序的,将10个文件合并为1个文件,仍按照时间戳从小到大排列,如果处理任务的机器内存只有1GB,有什么好的解决思路,能"快速"地将这10个文件合并?]() 40 | ``` 41 | 先构建十条io流,分别指向十个文件,每条io流读取对应文件的第一条数据, 42 | 然后比较时间戳,选择出时间戳最小的那条数据,将其写入一个新的文件, 43 | 然后指向该时间戳的io流读取下一行数据,然后继续刚才的操作,比较选出最小的时间戳数据,写入新文件,io流读取下一行数据, 44 | 以此类推,完成文件的合并, 45 | 这种处理方式,日志文件有n个,数据就要比较n次,每次比较选出一条数据来写入,时间复杂度是O(n),空间复杂度是O(1),几乎不占用内存, 46 | ``` 47 | #### [在O(n)内查找第K大元素,代码实现](https://github.com/TomorrowWu/golang-algorithms/blob/master/leetcode/0215.kth-largest-element-in-an-array/src/kth-largest-element-in-an-array.go) 48 | #### 根据年龄,给100万用户排序 49 | 计数排序 50 | #### [拜托,面试别再问我计数排序了!!!](https://mp.weixin.qq.com/s/KU-AUGOnLeRtE_hivl2uSA) 51 | #### [拜托,面试别再问我基数排序了!!!](https://mp.weixin.qq.com/s/Z8gU9QLpMnA-zoMc9ZeR2w) 52 | #### 如何在1000万个整数中快速查找某个整数?(内存限制是100MB,每个数据大小是8字节) 53 | ``` 54 | - 解决: 将数据存储在数组中,内存占用80MB,从小到大排序,再二分查找算法 55 | - 散列表和二叉树等支持快速查找的动态数据结构,大部分情况下,二分查找可以解决的问题,用上述两种数据结构都可以解决 56 | - 但是,上述两种结构需要比较多的额外的内存空间,100MB内存存不下 57 | - 二分查找底层依赖的是数组,除了数据本身以外,不需要额外存储其他信息,最省内存 58 | ``` 59 | 60 | ### 二分查找 61 | #### [如何快速定位IP对应的省份地址?](算法与数据结构/二分查找/如何快速定位IP对应的省份地址.md) 62 | 63 | ### 散列表(Hash表) 64 | #### [如何设计一个工业级的散列表](算法与数据结构/散列表/如何设计一个工业级的散列表.md) 65 | 66 | ### 树 67 | #### [说说树的概念](算法与数据结构/树/树的概念.md) 68 | #### [给定一组数据,比如 1,3,5,6,9,10,可以构建出多少种不同的二叉树?]() 69 | #### [如何实现按层遍历二叉树?]() 70 | #### [散列表如此高效,为什么还需要二叉树?](算法与数据结构/树/散列表、二叉查找树对比.md) 71 | #### 如何通过编程,求给定一棵二叉树的确切高度 72 | ``` 73 | - 第一种是深度优先思想的递归,分别求左右子树的高度。当前节点的高度就是左右子树中较大的那个+1 74 | - 第二种可以采用层次遍历的方式,每一层记录都记录下当前队列的长度,这个是队尾,每一层队头从0开始。 75 | 然后每遍历一个元素,队头下标+1。直到队头下标等于队尾下标。这个时候表示当前层遍历完成。 76 | 每一层刚开始遍历的时候,树的高度+1。最后队列为空,就能得到树的高度。 77 | ``` 78 | #### [二叉树搜索树的最近公共祖先](https://github.com/TomorrowWu/golang-algorithms/blob/master/leetcode/0235.lowest-common-ancestor-of-a-binary-search-tree/src/lowest-common-ancestor-of-a-binary-search-tree.go) 79 | 80 | ### 哈希算法 81 | #### [哈希算法有哪些应用场景](算法与数据结构/哈希算法/哈希算法的应用场景.md) 82 | 83 | ## 计算机网络 84 | #### [如果一个局域网里面有多个交换机,ARP广播的模式会出现什么问题呢?](网络协议/一个局域网里面有多个交换机,会出现什么问题.md) 85 | #### [ARP协议,已知IP地址求MAC;RARP协议,已知MAC求IP,可以用来做什么?](网络协议/RARP协议的作用.md) 86 | #### [STP协议能够很好的解决环路问题,但是也有它的缺点,你能举几个例子吗?](网络协议/STP协议的缺点.md) 87 | #### [在一个比较大的网络中,如果两台机器不通,你知道应该用什么方式调试吗?](网络协议/两台机器不通,如何调试?.md) 88 | #### [你觉得基于RTMP的视频流传输的机制存在什么问题?如何进行优化?](网络协议/揭秘RTMP流媒体协议.md) 89 | #### [把电影下载下来看,那么大,如何快速下载?](网络协议/快速下载.md) 90 | #### 负载均衡为什么要分地址和运营商呢? 91 | ``` 92 | 为了返回最优的IP,即离用户最近的IP,提高访问速度 93 | ``` 94 | 95 | ## MySQL 96 | ### [什么是数据库事务]() 97 | ``` 98 | 一次会话,多个命令要么都执行成功,要么都执行失败 99 | ``` 100 | ### [ACID 四大特性]() 101 | ### [SQL注入攻击](https://lovecoding.club/2018/12/12/web%E5%AE%89%E5%85%A8-sql%E6%B3%A8%E5%85%A5.html) 102 | ### [当备库用–single-transaction 做逻辑备份的时候,如果从主库的 binlog 传来一个 DDL 语句会怎么样?](MySQL/1.md) 103 | ### [重建索引](MySQL/重建索引.md) 104 | ### [假设你的表里面已经有了 city_name(city, name) 这个联合索引,然后你要查杭州和苏州两个城市中所有的市民的姓名,并且按名字排序,显示前 100 条记录。需要实现一个在数据库端不需要排序的方案,你会怎么实现呢?](MySQL/2.md) 105 | 106 | 107 | ## Redis 108 | ### [RDB与AOF两种持久化](http://redisdoc.com/topic/persistence.html) 109 | 110 | 111 | ## 网络协议 112 | #### [TCP和UDP的区别](网络协议/TCP和UDP的区别.md) 113 | #### [UDP的特点及使用场景](网络协议/UDP的特点及使用场景.md) 114 | #### [用websocket连接服务器时,为什么要自己做心跳机制,tcp不是有心跳机制?](网络协议/TCP和UDP的区别.md) 115 | #### [HTTP状态码](网络协议/HTTP状态码.md) 116 | 117 | 118 | ## 分布式系统 119 | #### [PoW和Paxos/Raft对比](分布式系统/PoW,Paxos,Raft对比.md) 120 | 121 | ## 区块链 122 | #### [比特币中PoW的优劣](区块链/比特币中PoW的优劣.md) 123 | #### Base58编码转换过程 124 | ``` 125 | 相当于将一个二进制数字,转换为58进制 126 | ``` 127 | 128 | ## 系统设计 129 | #### [基于Redis做IP限速](https://redis.io/commands/incr) 130 | ``` 131 | counter = current_time # for example 15:03 132 | count = INCR counter 133 | EXPIRE counter 60 # just to make sure redis doesn't store it forever 134 | 135 | if count > 5 136 | print "Exceeded the limit" 137 | ``` 138 | #### [秒杀](https://mp.weixin.qq.com/s?__biz=MzU2OTUyNzk1NQ==&mid=2247491172&idx=1&sn=1b3c5ca9b043bafd23687f9a55946492&source=41#wechat_redirect) 139 | 140 | ## 操作系统 141 | #### [面试必备之乐观锁与悲观锁](https://lovecoding.club/2018/11/20/%E4%B9%90%E8%A7%82%E9%94%81%E4%B8%8E%E6%82%B2%E8%A7%82%E9%94%81.html) 142 | #### [多版本并发控制(MVCC)在分布式系统中的应用](https://coolshell.cn/articles/6790.html) 143 | #### [进程、线程、协程区别]() 144 | ``` 145 | - 进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。 146 | - 线程是进程的一个实体,是CPU调度和分派的基本单位,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据 147 | - 协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈 148 | 149 | ``` 150 | 151 | ## Linux 152 | ### 你常用的5个Linux命令 153 | ``` 154 | 1. grep: 文本搜索 ps -ef|grep java:查找指定进程 155 | 2. cp: 复制文件 cp file1 file2 file3 dir :把文件file1、file2、file3复制到目录dir中 156 | 3. mv: 移动文件、目录或更名 mv file1 file2 file3 dir : 把文件file1、file2、file3移动到目录dir中 mv file1 file2 : 把文件file1重命名为file2 157 | 4. rm 158 | 5. ps: 列出系统中当前运行的进程 159 | 6. kill: 杀死进程 160 | 7. tar: 压缩,解压 161 | 8. chmod: 改变文件权限 162 | 9. tail: tail -f 20160921.logs :查看正在改变的日志文件 tail -3000 catalina.out:查看倒数前3000行的数据 tail -3000 catalina.out | grep 'AA':查看倒数前3000行包含字母'AA'的数据 163 | 10. lsof -i:8080:根据端口查看进程pid 164 | 11. ps -ef|grep ganache-cli | grep -v grep|sort -nrk2|head -n 1|awk '{print $1,$4}' 165 | -v : 屏蔽 166 | wc chap1: 显示文件中的行数,字数,和字节数 167 | sort -nrk2: r: 从大到小 k2:第几列 168 | head -n 1: 头部的 1行 169 | awk '{print $1,$4}' log.txt: 输出文本中的1、4项 170 | 12. top:查看当前系统的运行情况 171 | 13. tar: 解压 172 | 14. du -sh * | sort -n 173 | 查看当前目录大小,并按文件大小排序 174 | ``` 175 | ### 查看进程 176 | ``` 177 | 1,ps -ef|grep mysql 178 | 2. netstat -anp|grep 3306 179 | 3. lsof -i:3306 (list of file ) 180 | ``` 181 | ### Linux系统的/proc目录的作用 182 | ``` 183 | 在GUN/Linux操作系统中,/proc是一个位于内存中的伪文件系统(in-memory pseudo-file system)。 184 | 该目录下保存的不是真正的文件和目录,而是一些“运行时”信息,如系统内存、磁盘io、设备挂载信息和硬件配置信息等。 185 | proc目录是一个控制中心,用户可以通过更改其中某些文件来改变内核的运行状态。 186 | proc目录也是内核提供给我们的查询中心,我们可以通过这些文件查看有关系统硬件及当前正在运行进程的信息 187 | ``` 188 | 189 | ## 分布式 190 | ### 分布式系统、集群、负载均衡 191 | ``` 192 | 不同机器部署不同的服务,对外暴露一个系统 193 | 不同机器相同的服务,对外暴露一个服务 194 | 平衡的将任务分给集群中的每一个服务 195 | ``` 196 | 197 | ## 智力题 198 | ### [有9个球,其中一个的质量与其他的不同,有一个天平,通过最多几次可以找出那个质量不一样的球](https://www.nowcoder.com/questionTerminal/2b1ac592b56745b2969672c1c4e0d2c5?source=relative) 199 | ### 总共100个球,两个人分别拿,至少拿一个最多拿5个,你先拿怎么保证你能拿到第100个 200 | ``` 201 | 就是用逆向归纳的方法:如果最后你拿完剩1、2、3、4、5个球,那么则是对方拿到了第100个球。所以你的目标就是剩余6个球,这样无论对方怎么拿,你都能拿到100个球。由此类推,倒数第二次,你的目标就是剩余12个球,这样不管对方拿几个,你都可以将剩余球的个数变为6个,从而变为前面说的那种情况,而拿到第100个球。于是,不难归纳出,只要每次你的目标是剩余球的个数为6的倍数,那么你肯定最终拿到第100个球。 202 | 所以,如果最开始有100个球,那么只要你先拿4个,使剩余球的个数为96个(96=16×6),那么最后拿到第100个球的肯定是你 203 | ``` 204 | 205 | ## Go语言 206 | ### [string和[]byte和[]rune的区别](Go语言/string和[]byte和[]rune的区别.go) 207 | ### [实现Interface时value与pointer的不同](Go语言/实现Interface时value与pointer的不同.go) 208 | --------------------------------------------------------------------------------