Skip to content

Commit 53b5b18

Browse files
committed
thread
1 parent 3bbdc51 commit 53b5b18

3 files changed

Lines changed: 48 additions & 11 deletions

File tree

docs/interview/MySQL-FAQ.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,12 @@ B+ 树的特点:
535535

536536

537537

538+
#### 页分裂
539+
540+
http://www.uxys.com/html/MySQL/20190722/70361.html
541+
542+
543+
538544
### 哪些情况需要创建索引
539545

540546
1. 主键自动建立唯一索引
@@ -563,6 +569,8 @@ B+ 树的特点:
563569

564570
### MySQL高效索引
565571

572+
https://www.cnblogs.com/myseries/p/11265849.html
573+
566574
**覆盖索引**(Covering Index),或者叫索引覆盖, 也就是平时所说的不需要回表操作
567575

568576
- 就是 select 的数据列只用从索引中就能够取得,不必读取数据行,MySQL 可以利用索引返回 select 列表中的字段,而不必根据索引再次读取数据文件,换句话说**查询列要被所建的索引覆盖**
@@ -1001,8 +1009,9 @@ MyISAM 表的读操作与写操作之间,以及写操作之间是串行的。
10011009

10021010
InnoDB 实现了以下两种类型的**行锁**
10031011

1004-
- 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
1005-
- 排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
1012+
- 共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
1013+
1014+
- 排他锁又称为写锁,简称X锁,顾名思义,排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。
10061015

10071016
为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB 还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是**表锁**
10081017

@@ -1466,6 +1475,20 @@ long_query_time = 3
14661475
14671476
14681477
1478+
#### 建索引的几大原则
1479+
1480+
1. 最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
1481+
1482+
2. =和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。
1483+
1484+
3. 尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录。
1485+
1486+
4. 索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’)。
1487+
1488+
5. 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
1489+
1490+
1491+
14691492
**一般性建议**
14701493
14711494
- 对于单键索引,尽量选择针对当前query过滤性更好的索引

docs/interview/Network-FAQ.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
### 网络模型
3636

37-
随着技术的发展,计算机的应用越来越广泛,计算机之间的通信开始了百花齐放的状态,每个具有独立计算服务体系的信息技术公司都会建立自己的计算机通信规则,而这种情况会导致异构计算机之间无法通信,极大的阻碍了网络通信的发展,至此为了解决这个问题,国际标准化组织(ISO)制定了OSI模型,该模型定义了不同计算机互联的标准,OSI模型把网络通信的工作分为7层,分别是**物理层、数据链路层、网络层、传输层、会话层、表示层和应用层**
37+
随着技术的发展,计算机的应用越来越广泛,计算机之间的通信开始了百花齐放的状态,每个具有独立计算服务体系的信息技术公司都会建立自己的计算机通信规则,而这种情况会导致异构计算机之间无法通信,极大的阻碍了网络通信的发展,至此为了解决这个问题,国际标准化组织(ISO)制定了 OSI 模型,该模型定义了不同计算机互联的标准,OSI 模型把网络通信的工作分为 7 层,分别是**物理层、数据链路层、网络层、传输层、会话层、表示层和应用层**
3838

3939
这七层模型是设计层面的概念,每一层都有固定要完成的职责和功能,分层的好处在于清晰和功能独立性,但分层过多会使层次变的更加复杂,虽然不需要实现本层的功能,但是也需要构造本层的上下文,空耗系统资源,所以在落地实施网络通信模型的时候将这七层模型简化合并为四层模型分别是**应用层、传输层、网络层、网络接口层**(各层之间的模型、协议统称为:**TCP/IP协议簇**)。
4040

@@ -54,9 +54,9 @@
5454
| **数据链路层** | 定义数据的基本格式,如何传输,如何标识 | SLIP,CSLIP,PPP,ARP,RARP,MTU |
5555
| **物理层** |**二进制**数据形式在物理媒体上传输数据 | ISO2110,IEEE802 |
5656

57-
当我们某一个网站上不去的时候。通常会ping一下这个网站
57+
当我们某一个网站上不去的时候。通常会 ping 一下这个网站
5858

59-
`ping` 可以说是ICMP的最著名的应用,是TCP/IP协议的一部分。利用`ping`命令可以检查网络是否连通,可以很好地帮助我们分析和判定网络故障。
59+
`ping` 可以说是 ICMP 的最著名的应用,是 TCP/IP 协议的一部分。利用`ping`命令可以检查网络是否连通,可以很好地帮助我们分析和判定网络故障。
6060

6161

6262

@@ -165,7 +165,7 @@ TCP是一种面向连接的单播协议,在发送数据前,通信双方必
165165
166166
为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
167167

168-
具体例子:“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”
168+
具体例子:“已失效的连接请求报文段”的产生在这样一种情况下:client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 server。本来这是一个早已失效的报文段。但 server 收到此失效的连接请求报文段后,就误认为是 client 再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”
169169

170170

171171

@@ -764,9 +764,9 @@ session 是一种维持客户端与服务器端会话的机制。但是与 **coo
764764

765765
### 从输入网址到获得页面的过程
766766

767-
1. 浏览器查询 DNS,获取域名对应的IP地址:具体过程包括浏览器搜索自身的DNS缓存、搜索操作系统的DNS缓存、读取本地的Host文件和向本地DNS服务器进行查询等。对于向本地DNS服务器进行查询,如果要查询的域名包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析(此解析具有权威性);如果要查询的域名不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析(此解析不具有权威性)。如果本地域名服务器并未缓存该网址映射关系,那么将根据其设置发起递归查询或者迭代查询;
768-
2. 浏览器获得域名对应的IP地址以后,浏览器向服务器请求建立链接,发起三次握手;
769-
3. TCP/IP链接建立起来后,浏览器向服务器发送HTTP请求
767+
1. 浏览器查询 DNS,获取域名对应的 IP 地址:具体过程包括浏览器搜索自身的DNS缓存、搜索操作系统的DNS缓存、读取本地的Host文件和向本地DNS服务器进行查询等。对于向本地DNS服务器进行查询,如果要查询的域名包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析(此解析具有权威性);如果要查询的域名不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析(此解析不具有权威性)。如果本地域名服务器并未缓存该网址映射关系,那么将根据其设置发起递归查询或者迭代查询;
768+
2. 浏览器获得域名对应的 IP 地址以后,浏览器向服务器请求建立链接,发起三次握手;
769+
3. TCP/IP 链接建立起来后,浏览器向服务器发送 HTTP 请求
770770
4. 服务器接收到这个请求,并根据路径参数映射到特定的请求处理器进行处理,并将处理结果及相应的视图返回给浏览器;
771771
5. 浏览器解析并渲染视图,若遇到对js文件、css文件及图片等静态资源的引用,则重复上述步骤并向服务器请求这些资源;
772772
6. 浏览器根据其请求到的资源、数据渲染页面,最终向用户呈现一个完整的页面。

docs/interview/Redis-FAQ.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,20 @@ Redis并不能保证数据的强一致性,这意味这在实际中集群在特
825825

826826
Reids 采用的是 **惰性删除和定时删除** 的结合,一般来说可以借助最小堆来实现定时器,不过 Redis 的设计考虑到时间事件的有限种类和数量,使用了无序链表存储时间事件,这样如果在此基础上实现定时删除,就意味着 `O(N)` 遍历获取最近需要删除的数据。
827827

828+
实现过期键惰性删除策略的核心是 `db.c/expireIfNeeded` 函数 —— 所有命令在读取或写入数据库之前,程序都会调用 `expireIfNeeded` 对输入键进行检查, 并将过期键删除:
829+
830+
![digraph expire_check { node [style = filled, shape = plaintext]; edge [style = bold]; // node write_commands [label = "SET 、\n LPUSH 、\n SADD 、 \n 等等", fillcolor = "#FADCAD"]; read_commands [label = "GET 、\n LRANGE 、\n SMEMBERS 、 \n 等等", fillcolor = "#FADCAD"]; expire_if_needed [label = "调用 expire_if_needed() \n 删除过期键", shape = box, fillcolor = "#A8E270"]; process [label = "执行实际的命令流程"]; // edge write_commands -> expire_if_needed [label = "写请求"]; read_commands -> expire_if_needed [label = "读请求"]; expire_if_needed -> process; }](https://redisbook.readthedocs.io/en/latest/_images/graphviz-efb7f7ae1a793feea33285531dfe0023f3017b90.svg)
831+
832+
比如说, `GET` 命令的执行流程可以用下图来表示:
833+
834+
![digraph get_with_expire { node [style = filled, shape = plaintext]; edge [style = bold]; // node get [label = "GET key", fillcolor = "#FADCAD"]; expire_if_needed [label = "调用\n expire_if_needed() \n 如果键已经过期 \n 那么将它删除", shape = diamond, fillcolor = "#A8E270"]; expired_and_deleted [label = "key 不存在\n 向客户端返回 NIL"]; not_expired [label = "向客户端返回 key 的值"]; get -> expire_if_needed; expire_if_needed -> expired_and_deleted [label = "已过期"]; expire_if_needed -> not_expired [label = "未过期"]; }](https://redisbook.readthedocs.io/en/latest/_images/graphviz-acca43b0dd583eb92a1ce7193dc6b9bb14e9c0f9.svg)
835+
836+
`expireIfNeeded` 的作用是, 如果输入键已经过期的话, 那么将键、键的值、键保存在 `expires` 字典中的过期时间都删除掉。
837+
838+
839+
840+
对过期键的定期删除由 `redis.c/activeExpireCycle` 函执行: 每当 Redis 的例行处理程序 `serverCron` 执行时, `activeExpireCycle` 都会被调用 —— 这个函数在规定的时间限制内, 尽可能地遍历各个数据库的 `expires` 字典, 随机地检查一部分键的过期时间, 并删除其中的过期键。
841+
828842

829843

830844
### Redis 的淘汰策略有哪些?
@@ -874,7 +888,7 @@ Reids 采用的是 **惰性删除和定时删除** 的结合,一般来说可
874888

875889
串行化之后,就会导致系统的吞吐量会大幅度的降低,用比正常情况下多几倍的机器去支撑线上的一个请求。
876890

877-
操作缓存的时候我们都是采取**删除缓存**缓存策略的,原因如下:
891+
操作缓存的时候我们都是采取**删除缓存**策略的,原因如下:
878892

879893
1. 高并发环境下,无论是先操作数据库还是后操作数据库而言,如果加上更新缓存,那就**更加容易**导致数据库与缓存数据不一致问题。(删除缓存**直接和简单**很多)
880894
2. 如果每次更新了数据库,都要更新缓存【这里指的是频繁更新的场景,这会耗费一定的性能】,倒不如直接删除掉。等再次读取时,缓存里没有,那我到数据库找,在数据库找到再写到缓存里边(体现**懒加载**)
@@ -943,7 +957,7 @@ https://zhuanlan.zhihu.com/p/48334686
943957

944958
1. 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
945959

946-
2. 一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。
960+
2. 一般并发量不是特别多的时候,使用最多的解决方案是加锁排队(key上锁,其他线程不能访问,假设在高并发下,缓存重建期间key是锁着的,这是过来1000个请求999个都在阻塞的。同样会导致用户等待超时,这是个治标不治本的方法!)
947961

948962
3. 给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。
949963

0 commit comments

Comments
 (0)