@@ -754,6 +754,8 @@ new capacity : 00100000
|
||||
- 为 0,那么 hash%00010000 = hash%00100000,桶位置和原来一致;
|
||||
- 为 1,hash%00100000 = hash%00010000 + 16,桶位置是原位置 + 16。
|
||||
|
||||
<div align="center"> <img src="pics/hashmap-resize.png" width="560px"/> </div><br>
|
||||
|
||||
#### 7. 计算数组容量
|
||||
|
||||
HashMap 构造函数允许用户传入的容量不是 2 的 n 次方,因为它可以自动地将传入的容量转换为 2 的 n 次方。
|
||||
|
||||
@@ -234,6 +234,8 @@ epoll_ctl() 用于向内核注册新的描述符或者是改变某个文件描
|
||||
|
||||
从上面的描述可以看出,epoll 只需要将描述符从进程缓冲区向内核缓冲区拷贝一次,并且进程不需要通过轮询来获得事件完成的描述符。
|
||||
|
||||
<div align="center"> <img src="pics/epoll.png" width="600px"/> </div><br>
|
||||
|
||||
epoll 仅适用于 Linux OS。
|
||||
|
||||
epoll 比 select 和 poll 更加灵活而且没有描述符数量限制。
|
||||
|
||||
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 57 KiB |
@@ -210,6 +210,8 @@ TCC(Try-Confirm-Cancel)是在业务层面实现的两阶段提交,每个
|
||||
|
||||
Saga 将一个分布式事务拆分为多个本地事务,每个本地事务直接提交,并且都有一个对应的补偿操作。依次执行各个本地事务,如果某一个失败,就逆序执行前面已经提交的本地事务的补偿操作。
|
||||
|
||||
<div align="center"> <img src="pics/saga.png" width="540px"/> </div><br>
|
||||
|
||||
Saga 没有预留资源的 Try 阶段,中间状态对其它事务可见,因此没有隔离性。它适合流程长、无法长时间锁定资源的业务,正向操作和补偿操作同样需要实现幂等。
|
||||
|
||||
### 本地消息表
|
||||
@@ -226,6 +228,8 @@ Saga 没有预留资源的 Try 阶段,中间状态对其它事务可见,因
|
||||
|
||||
RocketMQ 的事务消息把本地消息表的工作交给了消息队列:生产者先发送一条对消费者不可见的半消息,再执行本地事务,然后根据执行结果通知 Broker 提交或者回滚这条消息。如果 Broker 长时间没有收到通知,会主动回查生产者的本地事务状态。
|
||||
|
||||
<div align="center"> <img src="pics/rocketmq-transaction.png" width="540px"/> </div><br>
|
||||
|
||||
## 三、CAP
|
||||
|
||||
分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容忍性(P:Partition Tolerance)。常见的“三选二”说法有误导性,因为网络分区是无法避免的故障,不是可以选择的选项。
|
||||
|
||||
@@ -122,6 +122,8 @@ http://www.examplebank.com/withdraw?account=AccountName&amount=1000&for=PayeeNam
|
||||
|
||||
如果有账户名为 Alice 的用户访问了恶意站点,而之前刚访问过银行不久,登录信息尚未过期,那么就会损失 1000 美元。
|
||||
|
||||
<div align="center"> <img src="pics/csrf.png" width="540px"/> </div><br>
|
||||
|
||||
这种恶意的网址可以有很多种形式,藏身于网页中的许多地方。此外,攻击者也不需要控制放置恶意网址的网站。例如他可以将这种地址藏在论坛,博客等任何用户生成内容的网站中。这意味着如果服务器端没有合适的防御措施的话,用户即使访问熟悉的可信网站也有受攻击的危险。改为 POST 请求也不能解决问题,攻击者可以使用自动提交的表单。
|
||||
|
||||
通过例子能够看出,攻击者并不能通过 CSRF 攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户浏览器,让其以用户的名义执行操作。
|
||||
|
||||
@@ -362,6 +362,8 @@ SELECT c FROM t WHERE c BETWEEN 10 and 20 FOR UPDATE;
|
||||
(20, +∞)
|
||||
```
|
||||
|
||||
<div align="center"> <img src="pics/next-key-locks.png" width="560px"/> </div><br>
|
||||
|
||||
## 七、关系数据库设计理论
|
||||
|
||||
### 函数依赖
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
Kafka、RocketMQ 等通过消费者组把两种模型结合起来:一条消息会发送给每个订阅它的消费者组,但在一个消费者组内只会被一个消费者消费。
|
||||
|
||||
<div align="center"> <img src="pics/consumer-group.png" width="560px"/> </div><br>
|
||||
|
||||
发布与订阅模式和观察者模式有以下不同:
|
||||
|
||||
- 观察者模式中,观察者和主题都知道对方的存在;而在发布与订阅模式中,生产者与消费者不知道对方的存在,它们之间通过频道进行通信。
|
||||
|
||||
@@ -111,6 +111,10 @@
|
||||
- 降级:主动关闭部分非核心功能,从而保证核心功能可用;
|
||||
- 熔断:某个依赖的服务持续出错时,暂时不再调用它而是直接返回默认结果,避免故障沿着调用链扩散。
|
||||
|
||||
漏桶以固定速率处理请求,桶满时丢弃新的请求;令牌桶以固定速率放入令牌,请求拿到令牌才能被处理,桶中积累的令牌允许一定的突发流量。
|
||||
|
||||
<div align="center"> <img src="pics/rate-limit.png" width="580px"/> </div><br>
|
||||
|
||||
熔断器有关闭、打开和半开三种状态:失败率超过阈值时打开;打开一段时间后进入半开状态,放行少量请求试探,成功则关闭,失败则重新打开。
|
||||
|
||||
<div align="center"> <img src="pics/circuit-breaker.png" width="500px"/> </div><br>
|
||||
|
||||
@@ -97,6 +97,10 @@ CDN 主要有以下优点:
|
||||
- 对这些不存在的数据缓存一个空数据,并设置较短的过期时间;
|
||||
- 使用布隆过滤器保存所有存在的 Key,对不存在的 Key 的请求直接拒绝。
|
||||
|
||||
布隆过滤器用多个哈希函数把 Key 映射到位数组的多个位置并置为 1。查询时只要有一个位置为 0,Key 就一定不存在;全部为 1 时 Key 可能存在,存在一定的误判率。
|
||||
|
||||
<div align="center"> <img src="pics/bloom-filter.png" width="560px"/> </div><br>
|
||||
|
||||
### 缓存击穿
|
||||
|
||||
指的是某个热点数据的缓存过期时,大量对它的请求同时到达数据库。
|
||||
@@ -200,6 +204,8 @@ Redis Cluster 使用的不是一致性哈希,而是把 Key 映射到固定的
|
||||
- 访问某个节点时,将其从原来的位置删除,并重新插入到链表头部。这样就能保证链表尾部存储的就是最近最久未使用的节点,当节点数量大于缓存最大空间时就淘汰链表尾部的节点。
|
||||
- 为了使删除操作时间复杂度为 O(1),就不能采用遍历的方式找到某个节点。HashMap 存储着 Key 到节点的映射,通过 Key 就能以 O(1) 的时间得到节点,然后再以 O(1) 的时间将其从双向队列中删除。
|
||||
|
||||
<div align="center"> <img src="pics/lru.png" width="560px"/> </div><br>
|
||||
|
||||
Java 的 LinkedHashMap 内部就是这种结构,把 accessOrder 设为 true 并重写 removeEldestEntry 方法,就可以直接得到一个 LRU 缓存。
|
||||
|
||||
```java
|
||||
|
||||