mirror of
https://github.com/doocs/advanced-java.git
synced 2025-04-25 14:30:23 +08:00
fix: update documents about Redis and ElasticSearch
更新 Redis 和 ElasticSearch 文档说明
This commit is contained in:
parent
ce7011855a
commit
1bb316e1ed
@ -11,7 +11,7 @@
|
||||
* [说一下 Dubbo 的工作原理?注册中心挂了可以继续通信吗?](/docs/distributed-system/dubbo-operating-principle.md)
|
||||
* [Dubbo 支持哪些序列化协议?说一下 Hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的?](/docs/distributed-system/dubbo-serialization-protocol.md)
|
||||
* [Dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?](/docs/distributed-system/dubbo-load-balancing.md)
|
||||
* [Dubbo 的 spi 思想是什么?](/docs/distributed-system/dubbo-spi.md)
|
||||
* [Dubbo 的 SPI 思想是什么?](/docs/distributed-system/dubbo-spi.md)
|
||||
* [如何基于 Dubbo 进行服务治理、服务降级、失败重试以及超时重试?](/docs/distributed-system/dubbo-service-management.md)
|
||||
* [分布式服务接口的幂等性如何设计(比如不能重复扣款)?](/docs/distributed-system/distributed-system-idempotency.md)
|
||||
* [分布式服务接口请求的顺序性如何保证?](/docs/distributed-system/distributed-system-request-sequence.md)
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 面试题
|
||||
一般实现分布式锁都有哪些方式?使用 redis 如何设计分布式锁?使用 zk 来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
|
||||
一般实现分布式锁都有哪些方式?使用 Redis 如何设计分布式锁?使用 zk 来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
|
||||
|
||||
## 面试官心理分析
|
||||
|
||||
@ -7,19 +7,19 @@
|
||||
|
||||
## 面试题剖析
|
||||
|
||||
### redis 分布式锁
|
||||
### Redis 分布式锁
|
||||
|
||||
官方叫做 `RedLock` 算法,是 redis 官方支持的分布式锁算法。
|
||||
官方叫做 `RedLock` 算法,是 Redis 官方支持的分布式锁算法。
|
||||
|
||||
这个分布式锁有 3 个重要的考量点:
|
||||
|
||||
* 互斥(只能有一个客户端获取锁)
|
||||
* 不能死锁
|
||||
* 容错(只要大部分 redis 节点创建了这把锁就可以)
|
||||
* 容错(只要大部分 Redis 节点创建了这把锁就可以)
|
||||
|
||||
#### redis 最普通的分布式锁
|
||||
#### Redis 最普通的分布式锁
|
||||
|
||||
第一个最普通的实现方式,就是在 redis 里使用 `SET key value [EX seconds] [PX milliseconds] NX` 创建一个 key,这样就算加锁。其中:
|
||||
第一个最普通的实现方式,就是在 Redis 里使用 `SET key value [EX seconds] [PX milliseconds] NX` 创建一个 key,这样就算加锁。其中:
|
||||
|
||||
- `NX`:表示只有 `key` 不存在的时候才会设置成功,如果此时 redis 中存在这个 `key`,那么设置失败,返回 `nil`。
|
||||
- `EX seconds`:设置 `key` 的过期时间,精确到秒级。意思是 `seconds` 秒后锁自动释放,别人创建的时候如果发现已经有了就不能加锁了。
|
||||
@ -44,11 +44,11 @@ end
|
||||
|
||||
为啥要用 `random_value` 随机值呢?因为如果某个客户端获取到了锁,但是阻塞了很长时间才执行完,比如说超过了 30s,此时可能已经自动释放锁了,此时可能别的客户端已经获取到了这个锁,要是你这个时候直接删除 key 的话会有问题,所以得用随机值加上面的 `lua` 脚本来释放锁。
|
||||
|
||||
但是这样是肯定不行的。因为如果是普通的 redis 单实例,那就是单点故障。或者是 redis 普通主从,那 redis 主从异步复制,如果主节点挂了(key 就没有了),key 还没同步到从节点,此时从节点切换为主节点,别人就可以 set key,从而拿到锁。
|
||||
但是这样是肯定不行的。因为如果是普通的 Redis 单实例,那就是单点故障。或者是 Redis 普通主从,那 Redis 主从异步复制,如果主节点挂了(key 就没有了),key 还没同步到从节点,此时从节点切换为主节点,别人就可以 set key,从而拿到锁。
|
||||
|
||||
#### RedLock 算法
|
||||
|
||||
这个场景是假设有一个 redis cluster,有 5 个 redis master 实例。然后执行如下步骤获取一把锁:
|
||||
这个场景是假设有一个 Redis cluster,有 5 个 Redis master 实例。然后执行如下步骤获取一把锁:
|
||||
|
||||
1. 获取当前时间戳,单位是毫秒;
|
||||
2. 跟上面类似,轮流尝试在每个 master 节点上创建锁,过期时间较短,一般就几十毫秒;
|
||||
@ -196,7 +196,7 @@ public class ZooKeeperSession {
|
||||
|
||||
也可以采用另一种方式,创建临时顺序节点:
|
||||
|
||||
如果有一把锁,被多个人给竞争,此时多个人会排队,第一个拿到锁的人会执行,然后释放锁;后面的每个人都会去监听**排在自己前面**的那个人创建的 node 上,一旦某个人释放了锁,排在自己后面的人就会被 zookeeper 给通知,一旦被通知了之后,就 ok 了,自己就获取到了锁,就可以执行代码了。
|
||||
如果有一把锁,被多个人给竞争,此时多个人会排队,第一个拿到锁的人会执行,然后释放锁;后面的每个人都会去监听**排在自己前面**的那个人创建的 node 上,一旦某个人释放了锁,排在自己后面的人就会被 ZooKeeper 给通知,一旦被通知了之后,就 ok 了,自己就获取到了锁,就可以执行代码了。
|
||||
|
||||
``` java
|
||||
public class ZooKeeperDistributedLock implements Watcher {
|
||||
@ -330,8 +330,8 @@ public class ZooKeeperDistributedLock implements Watcher {
|
||||
* redis 分布式锁,其实**需要自己不断去尝试获取锁**,比较消耗性能。
|
||||
* zk 分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小。
|
||||
|
||||
另外一点就是,如果是 redis 获取锁的那个客户端 出现 bug 挂了,那么只能等待超时时间之后才能释放锁;而 zk 的话,因为创建的是临时 znode,只要客户端挂了,znode 就没了,此时就自动释放锁。
|
||||
另外一点就是,如果是 Redis 获取锁的那个客户端 出现 bug 挂了,那么只能等待超时时间之后才能释放锁;而 zk 的话,因为创建的是临时 znode,只要客户端挂了,znode 就没了,此时就自动释放锁。
|
||||
|
||||
redis 分布式锁大家没发现好麻烦吗?遍历上锁,计算时间等等......zk 的分布式锁语义清晰实现简单。
|
||||
Redis 分布式锁大家没发现好麻烦吗?遍历上锁,计算时间等等......zk 的分布式锁语义清晰实现简单。
|
||||
|
||||
所以先不分析太多的东西,就说这两点,我个人实践认为 zk 的分布式锁比 redis 的分布式锁牢靠、而且模型简单易用。
|
||||
所以先不分析太多的东西,就说这两点,我个人实践认为 zk 的分布式锁比 Redis 的分布式锁牢靠、而且模型简单易用。
|
||||
|
@ -1,33 +1,33 @@
|
||||
## 面试题
|
||||
集群部署时的分布式 session 如何实现?
|
||||
集群部署时的分布式 Session 如何实现?
|
||||
|
||||
## 面试官心理分析
|
||||
|
||||
面试官问了你一堆 dubbo 是怎么玩儿的,你会玩儿 dubbo 就可以把单块系统弄成分布式系统,然后分布式之后接踵而来的就是一堆问题,最大的问题就是**分布式事务**、**接口幂等性**、**分布式锁**,还有最后一个就是**分布式 session**。
|
||||
面试官问了你一堆 Dubbo 是怎么玩儿的,你会玩儿 Dubbo 就可以把单块系统弄成分布式系统,然后分布式之后接踵而来的就是一堆问题,最大的问题就是**分布式事务**、**接口幂等性**、**分布式锁**,还有最后一个就是**分布式 Session**。
|
||||
|
||||
当然了,分布式系统中的问题何止这么一点,非常之多,复杂度很高,这里只是说一下常见的几个问题,也是面试的时候常问的几个。
|
||||
|
||||
## 面试题剖析
|
||||
|
||||
session 是啥?浏览器有个 cookie,在一段时间内这个 cookie 都存在,然后每次发请求过来都带上一个特殊的 `jsessionid cookie` ,就根据这个东西,在服务端可以维护一个对应的 session 域,里面可以放点数据。
|
||||
Session 是啥?浏览器有个 Cookie,在一段时间内这个 Cookie 都存在,然后每次发请求过来都带上一个特殊的 `jsessionid cookie` ,就根据这个东西,在服务端可以维护一个对应的 Session 域,里面可以放点数据。
|
||||
|
||||
一般的话只要你没关掉浏览器,cookie 还在,那么对应的那个 session 就在,但是如果 cookie 没了,session 也就没了。常见于什么购物车之类的东西,还有登录状态保存之类的。
|
||||
一般的话只要你没关掉浏览器,Cookie 还在,那么对应的那个 Session 就在,但是如果 Cookie 没了,Session 也就没了。常见于什么购物车之类的东西,还有登录状态保存之类的。
|
||||
|
||||
这个不多说了,懂 Java 的都该知道这个。
|
||||
|
||||
单块系统的时候这么玩儿 session 没问题,但是你要是分布式系统呢,那么多的服务,session 状态在哪儿维护啊?
|
||||
单块系统的时候这么玩儿 Session 没问题,但是你要是分布式系统呢,那么多的服务,Session 状态在哪儿维护啊?
|
||||
|
||||
其实方法很多,但是常见常用的是以下几种:
|
||||
|
||||
### 完全不用 session
|
||||
### 完全不用 Session
|
||||
|
||||
使用 JWT Token 储存用户身份,然后再从数据库或者 cache 中获取其他的信息。这样无论请求分配到哪个服务器都无所谓。
|
||||
|
||||
### tomcat + redis
|
||||
### Tomcat + Redis
|
||||
|
||||
这个其实还挺方便的,就是使用 session 的代码,跟以前一样,还是基于 tomcat 原生的 session 支持即可,然后就是用一个叫做 `Tomcat RedisSessionManager` 的东西,让所有我们部署的 tomcat 都将 session 数据存储到 redis 即可。
|
||||
这个其实还挺方便的,就是使用 Session 的代码,跟以前一样,还是基于 Tomcat 原生的 Session 支持即可,然后就是用一个叫做 `Tomcat RedisSessionManager` 的东西,让所有我们部署的 Tomcat 都将 Session 数据存储到 Redis 即可。
|
||||
|
||||
在 tomcat 的配置文件中配置:
|
||||
在 Tomcat 的配置文件中配置:
|
||||
|
||||
``` xml
|
||||
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
|
||||
@ -39,7 +39,7 @@ session 是啥?浏览器有个 cookie,在一段时间内这个 cookie 都存
|
||||
maxInactiveInterval="60"/>
|
||||
```
|
||||
|
||||
然后指定 redis 的 host 和 port 就 ok 了。
|
||||
然后指定 Redis 的 host 和 port 就 ok 了。
|
||||
|
||||
```xml
|
||||
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
|
||||
@ -49,15 +49,15 @@ session 是啥?浏览器有个 cookie,在一段时间内这个 cookie 都存
|
||||
maxInactiveInterval="60"/>
|
||||
```
|
||||
|
||||
还可以用上面这种方式基于 redis 哨兵支持的 redis 高可用集群来保存 session 数据,都是 ok 的。
|
||||
还可以用上面这种方式基于 Redis 哨兵支持的 Redis 高可用集群来保存 Session 数据,都是 ok 的。
|
||||
|
||||
### spring session + redis
|
||||
### Spring Session + Redis
|
||||
|
||||
上面所说的第二种方式会与 tomcat 容器重耦合,如果我要将 web 容器迁移成 jetty,难道还要重新把 jetty 都配置一遍?
|
||||
上面所说的第二种方式会与 Tomcat 容器重耦合,如果我要将 Web 容器迁移成 Jetty,难道还要重新把 Jetty 都配置一遍?
|
||||
|
||||
因为上面那种 tomcat + redis 的方式好用,但是会**严重依赖于web容器**,不好将代码移植到其他 web 容器上去,尤其是你要是换了技术栈咋整?比如换成了 spring cloud 或者是 spring boot 之类的呢?
|
||||
因为上面那种 Tomcat + Redis 的方式好用,但是会**严重依赖于 Web 容器**,不好将代码移植到其他 Web 容器上去,尤其是你要是换了技术栈咋整?比如换成了 Spring Cloud 或者是 Spring Boot 之类的呢?
|
||||
|
||||
所以现在比较好的还是基于 Java 一站式解决方案,也就是 spring。人家 spring 基本上承包了大部分我们需要使用的框架,spirng cloud 做微服务,spring boot 做脚手架,所以用 sping session 是一个很好的选择。
|
||||
所以现在比较好的还是基于 Java 一站式解决方案,也就是 Spring。人家 Spring 基本上承包了大部分我们需要使用的框架,Spirng Cloud 做微服务,Spring Boot 做脚手架,所以用 Spring Session 是一个很好的选择。
|
||||
|
||||
在 pom.xml 中配置:
|
||||
|
||||
@ -74,7 +74,7 @@ session 是啥?浏览器有个 cookie,在一段时间内这个 cookie 都存
|
||||
</dependency>
|
||||
```
|
||||
|
||||
在 spring 配置文件中配置:
|
||||
在 Spring 配置文件中配置:
|
||||
|
||||
``` xml
|
||||
<bean id="redisHttpSessionConfiguration"
|
||||
@ -132,6 +132,6 @@ public class TestController {
|
||||
}
|
||||
```
|
||||
|
||||
上面的代码就是 ok 的,给 sping session 配置基于 redis 来存储 session 数据,然后配置了一个 spring session 的过滤器,这样的话,session 相关操作都会交给 spring session 来管了。接着在代码中,就用原生的 session 操作,就是直接基于 spring sesion 从 redis 中获取数据了。
|
||||
上面的代码就是 ok 的,给 Spring Session 配置基于 Redis 来存储 Session 数据,然后配置了一个 Spring Session 的过滤器,这样的话,Session 相关操作都会交给 Spring Session 来管了。接着在代码中,就用原生的 Session 操作,就是直接基于 Spring Session 从 Redis 中获取数据了。
|
||||
|
||||
实现分布式的会话有很多种方式,我说的只不过是比较常见的几种方式,tomcat + redis 早期比较常用,但是会重耦合到 tomcat 中;近些年,通过 spring session 来实现。
|
||||
实现分布式的会话有很多种方式,我说的只不过是比较常见的几种方式,Tomcat + Redis 早期比较常用,但是会重耦合到 Tomcat 中;近些年,通过 Spring Session 来实现。
|
||||
|
@ -25,6 +25,6 @@
|
||||
* 每次处理完请求之后,必须有一个记录标识这个请求处理过了。常见的方案是在 mysql 中记录个状态啥的,比如支付之前记录一条这个订单的支付流水。
|
||||
* 每次接收请求需要进行判断,判断之前是否处理过。比如说,如果有一个订单已经支付了,就已经有了一条支付流水,那么如果重复发送这个请求,则此时先插入支付流水,orderId 已经存在了,唯一键约束生效,报错插入不进去的。然后你就不用再扣款了。
|
||||
|
||||
实际运作过程中,你要结合自己的业务来,比如说利用 redis,用 orderId 作为唯一键。只有成功插入这个支付流水,才可以执行实际的支付扣款。
|
||||
实际运作过程中,你要结合自己的业务来,比如说利用 Redis,用 orderId 作为唯一键。只有成功插入这个支付流水,才可以执行实际的支付扣款。
|
||||
|
||||
要求是支付一个订单,必须插入一条支付流水,order_id 建一个唯一键 `unique key` 。你在支付一个订单之前,先插入一条支付流水,order_id 就已经进去了。你就可以写一个标识到 redis 里面去, `set order_id payed` ,下一次重复请求过来了,先查 redis 的 order_id 对应的 value,如果是 `payed` 就说明已经支付过了,你就别重复支付了。
|
||||
要求是支付一个订单,必须插入一条支付流水,order_id 建一个唯一键 `unique key` 。你在支付一个订单之前,先插入一条支付流水,order_id 就已经进去了。你就可以写一个标识到 Redis 里面去, `set order_id payed` ,下一次重复请求过来了,先查 Redis 的 order_id 对应的 value,如果是 `payed` 就说明已经支付过了,你就别重复支付了。
|
||||
|
@ -1,32 +1,32 @@
|
||||
## 分布式系统面试连环炮
|
||||
有一些同学,之前呢主要是做传统行业,或者外包项目,一直是在那种小的公司,技术一直都搞的比较简单。他们有共同的一个问题,就是都没怎么搞过分布式系统,现在互联网公司,一般都是做分布式的系统,大家都不是做底层的分布式系统、分布式存储系统 hadoop hdfs、分布式计算系统 hadoop mapreduce / spark、分布式流式计算系统 storm。
|
||||
有一些同学,之前呢主要是做传统行业,或者外包项目,一直是在那种小的公司,技术一直都搞的比较简单。他们有共同的一个问题,就是都没怎么搞过分布式系统,现在互联网公司,一般都是做分布式的系统,大家都不是做底层的分布式系统、分布式存储系统 Hadoop HDFS、分布式计算系统 Hadoop MapReduce / Spark、分布式流式计算系统 Storm。
|
||||
|
||||
分布式业务系统,就是把原来用 Java 开发的一个大块系统,给拆分成**多个子系统**,多个子系统之间互相调用,形成一个大系统的整体。假设原来你做了一个 OA 系统,里面包含了权限模块、员工模块、请假模块、财务模块,一个工程,里面包含了一堆模块,模块与模块之间会互相去调用,1 台机器部署。现在如果你把这个系统给拆开,权限系统、员工系统、请假系统、财务系统 4 个系统,4 个工程,分别在 4 台机器上部署。一个请求过来,完成这个请求,这个员工系统,调用权限系统,调用请假系统,调用财务系统,4 个系统分别完成了一部分的事情,最后 4 个系统都干完了以后,才认为是这个请求已经完成了。
|
||||
|
||||

|
||||
|
||||
> 近几年开始兴起和流行 Spring Cloud,刚流行,还没开始普及,目前普及的是 dubbo,因此这里也主要讲 dubbo。
|
||||
> 近几年开始兴起和流行 Spring Cloud,刚流行,还没开始普及,目前普及的是 Dubbo,因此这里也主要讲 Dubbo。
|
||||
|
||||
面试官可能会问你以下问题。
|
||||
|
||||
### 为什么要进行系统拆分?
|
||||
|
||||
* 为什么要进行系统拆分?如何进行系统拆分?拆分后不用dubbo可以吗?dubbo和thrift有什么区别呢?
|
||||
* 为什么要进行系统拆分?如何进行系统拆分?拆分后不用 Dubbo 可以吗?Dubbo 和 thrift 有什么区别呢?
|
||||
|
||||
### 分布式服务框架
|
||||
|
||||
* 说一下的 dubbo 的工作原理?注册中心挂了可以继续通信吗?
|
||||
* dubbo 支持哪些序列化协议?说一下 hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的?
|
||||
* dubbo 负载均衡策略和高可用策略都有哪些?动态代理策略呢?
|
||||
* dubbo 的 spi 思想是什么?
|
||||
* 如何基于 dubbo 进行服务治理、服务降级、失败重试以及超时重试?
|
||||
* 说一下的 Dubbo 的工作原理?注册中心挂了可以继续通信吗?
|
||||
* Dubbo 支持哪些序列化协议?说一下 Hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的?
|
||||
* Dubbo 负载均衡策略和高可用策略都有哪些?动态代理策略呢?
|
||||
* Dubbo 的 SPI 思想是什么?
|
||||
* 如何基于 Dubbo 进行服务治理、服务降级、失败重试以及超时重试?
|
||||
* 分布式服务接口的幂等性如何设计(比如不能重复扣款)?
|
||||
* 分布式服务接口请求的顺序性如何保证?
|
||||
* 如何自己设计一个类似 dubbo 的 rpc 框架?
|
||||
* 如何自己设计一个类似 Dubbo 的 RPC 框架?
|
||||
|
||||
### 分布式锁
|
||||
|
||||
* 使用 redis 如何设计分布式锁?使用 zk 来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
|
||||
* 使用 Redis 如何设计分布式锁?使用 zk 来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
|
||||
|
||||
### 分布式事务
|
||||
|
||||
@ -34,4 +34,4 @@
|
||||
|
||||
### 分布式会话
|
||||
|
||||
* 集群部署时的分布式 session 如何实现?
|
||||
* 集群部署时的分布式 Session 如何实现?
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
首先,一般来说,个人建议是,你们从业务逻辑上设计的这个系统最好是不需要这种顺序性的保证,因为一旦引入顺序性保障,比如使用**分布式锁**,会**导致系统复杂度上升**,而且会带来**效率低下**,热点数据压力过大等问题。
|
||||
|
||||
下面我给个我们用过的方案吧,简单来说,首先你得用 dubbo 的一致性 hash 负载均衡策略,将比如某一个订单 id 对应的请求都给分发到某个机器上去,接着就是在那个机器上,因为可能还是多线程并发执行的,你可能得立即将某个订单 id 对应的请求扔一个**内存队列**里去,强制排队,这样来确保他们的顺序性。
|
||||
下面我给个我们用过的方案吧,简单来说,首先你得用 Dubbo 的一致性 hash 负载均衡策略,将比如某一个订单 id 对应的请求都给分发到某个机器上去,接着就是在那个机器上,因为可能还是多线程并发执行的,你可能得立即将某个订单 id 对应的请求扔一个**内存队列**里去,强制排队,这样来确保他们的顺序性。
|
||||
|
||||

|
||||
|
||||
|
@ -52,11 +52,11 @@
|
||||
| 352 | 0 | 11 |
|
||||
| 4593 | 17 | 15 |
|
||||
|
||||
刚开始的时候,这个库可能就是逻辑库,建在一个数据库上的,就是一个 mysql 服务器可能建了 n 个库,比如 32 个库。后面如果要拆分,就是不断在库和 mysql 服务器之间做迁移就可以了。然后系统配合改一下配置即可。
|
||||
刚开始的时候,这个库可能就是逻辑库,建在一个数据库上的,就是一个 MySQL 服务器可能建了 n 个库,比如 32 个库。后面如果要拆分,就是不断在库和 MySQL 服务器之间做迁移就可以了。然后系统配合改一下配置即可。
|
||||
|
||||
比如说最多可以扩展到 32 个数据库服务器,每个数据库服务器是一个库。如果还是不够?最多可以扩展到 1024 个数据库服务器,每个数据库服务器上面一个库一个表。因为最多是 1024 个表。
|
||||
|
||||
这么搞,是不用自己写代码做数据迁移的,都交给 dba 来搞好了,但是 dba 确实是需要做一些库表迁移的工作,但是总比你自己写代码,然后抽数据导数据来的效率高得多吧。
|
||||
这么搞,是不用自己写代码做数据迁移的,都交给 DBA 来搞好了,但是 DBA 确实是需要做一些库表迁移的工作,但是总比你自己写代码,然后抽数据导数据来的效率高得多吧。
|
||||
|
||||
哪怕是要减少库的数量,也很简单,其实说白了就是按倍数缩容就可以了,然后修改一下路由规则。
|
||||
|
||||
@ -64,7 +64,7 @@
|
||||
|
||||
1. 设定好几台数据库服务器,每台服务器上几个库,每个库多少个表,推荐是 32 库 * 32 表,对于大部分公司来说,可能几年都够了。
|
||||
2. 路由的规则,orderId 模 32 = 库,orderId / 32 模 32 = 表
|
||||
3. 扩容的时候,申请增加更多的数据库服务器,装好 mysql,呈倍数扩容,4 台服务器,扩到 8 台服务器,再到 16 台服务器。
|
||||
4. 由 dba 负责将原先数据库服务器的库,迁移到新的数据库服务器上去,库迁移是有一些便捷的工具的。
|
||||
3. 扩容的时候,申请增加更多的数据库服务器,装好 MySQL,呈倍数扩容,4 台服务器,扩到 8 台服务器,再到 16 台服务器。
|
||||
4. 由 DBA 负责将原先数据库服务器的库,迁移到新的数据库服务器上去,库迁移是有一些便捷的工具的。
|
||||
5. 我们这边就是修改一下配置,调整迁移的库所在数据库服务器的地址。
|
||||
6. 重新发布系统,上线,原先的路由规则变都不用变,直接可以基于 n 倍的数据库服务器的资源,继续进行线上系统的提供服务。
|
||||
|
@ -45,12 +45,12 @@ UUID.randomUUID().toString().replace("-", "") -> sfsdf23423rr234sfdaf
|
||||
|
||||
### snowflake 算法
|
||||
|
||||
snowflake 算法是 twitter 开源的分布式 id 生成算法,采用 Scala 语言实现,是把一个 64 位的 long 型的 id,1 个 bit 是不用的,用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号。
|
||||
snowflake 算法是 twitter 开源的分布式 id 生成算法,采用 Scala 语言实现,是把一个 64 位的 long 型的 id,1 个 bit 是不用的,用其中的 41 bits 作为毫秒数,用 10 bits 作为工作机器 id,12 bits 作为序列号。
|
||||
|
||||
* 1 bit:不用,为啥呢?因为二进制里第一个 bit 为如果是 1,那么都是负数,但是我们生成的 id 都是正数,所以第一个 bit 统一都是 0。
|
||||
* 41 bit:表示的是时间戳,单位是毫秒。41 bit 可以表示的数字多达 `2^41 - 1` ,也就是可以标识 `2^41 - 1` 个毫秒值,换算成年就是表示69年的时间。
|
||||
* 10 bit:记录工作机器 id,代表的是这个服务最多可以部署在 2^10台机器上哪,也就是1024台机器。但是 10 bit 里 5 个 bit 代表机房 id,5 个 bit 代表机器 id。意思就是最多代表 `2^5` 个机房(32个机房),每个机房里可以代表 `2^5` 个机器(32台机器)。
|
||||
* 12 bit:这个是用来记录同一个毫秒内产生的不同 id,12 bit 可以代表的最大正整数是 `2^12 - 1 = 4096` ,也就是说可以用这个 12 bit 代表的数字来区分**同一个毫秒内**的 4096 个不同的 id。
|
||||
* 41 bits:表示的是时间戳,单位是毫秒。41 bits 可以表示的数字多达 `2^41 - 1` ,也就是可以标识 `2^41 - 1` 个毫秒值,换算成年就是表示69年的时间。
|
||||
* 10 bits:记录工作机器 id,代表的是这个服务最多可以部署在 2^10 台机器上,也就是 1024 台机器。但是 10 bits 里 5 个 bits 代表机房 id,5 个 bits 代表机器 id。意思就是最多代表 `2^5` 个机房(32 个机房),每个机房里可以代表 `2^5` 个机器(32台机器)。
|
||||
* 12 bits:这个是用来记录同一个毫秒内产生的不同 id,12 bits 可以代表的最大正整数是 `2^12 - 1 = 4096` ,也就是说可以用这个 12 bits 代表的数字来区分**同一个毫秒内**的 4096 个不同的 id。
|
||||
|
||||
```
|
||||
0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000000
|
||||
|
@ -1,21 +1,21 @@
|
||||
## 面试题
|
||||
es 的分布式架构原理能说一下么(es 是如何实现分布式的啊)?
|
||||
ES 的分布式架构原理能说一下么(ES 是如何实现分布式的啊)?
|
||||
|
||||
## 面试官心理分析
|
||||
|
||||
在搜索这块,lucene 是最流行的搜索库。几年前业内一般都问,你了解 lucene 吗?你知道倒排索引的原理吗?现在早已经 out 了,因为现在很多项目都是直接用基于 lucene 的分布式搜索引擎—— ElasticSearch,简称为 es。
|
||||
在搜索这块,lucene 是最流行的搜索库。几年前业内一般都问,你了解 lucene 吗?你知道倒排索引的原理吗?现在早已经 out 了,因为现在很多项目都是直接用基于 lucene 的分布式搜索引擎—— ElasticSearch,简称为 ES。
|
||||
|
||||
而现在分布式搜索基本已经成为大部分互联网行业的 Java 系统的标配,其中尤为流行的就是 es,前几年 es 没火的时候,大家一般用 solr。但是这两年基本大部分企业和项目都开始转向 es 了。
|
||||
而现在分布式搜索基本已经成为大部分互联网行业的 Java 系统的标配,其中尤为流行的就是 ES,前几年 ES 没火的时候,大家一般用 solr。但是这两年基本大部分企业和项目都开始转向 ES 了。
|
||||
|
||||
所以互联网面试,肯定会跟你聊聊分布式搜索引擎,也就一定会聊聊 es,如果你确实不知道,那你真的就 out 了。
|
||||
所以互联网面试,肯定会跟你聊聊分布式搜索引擎,也就一定会聊聊 ES,如果你确实不知道,那你真的就 out 了。
|
||||
|
||||
如果面试官问你第一个问题,确实一般都会问你 es 的分布式架构设计能介绍一下么?就看看你对分布式搜索引擎架构的一个基本理解。
|
||||
如果面试官问你第一个问题,确实一般都会问你 ES 的分布式架构设计能介绍一下么?就看看你对分布式搜索引擎架构的一个基本理解。
|
||||
|
||||
## 面试题剖析
|
||||
|
||||
ElasticSearch 设计的理念就是分布式搜索引擎,底层其实还是基于 lucene 的。核心思想就是在多台机器上启动多个 es 进程实例,组成了一个 es 集群。
|
||||
ElasticSearch 设计的理念就是分布式搜索引擎,底层其实还是基于 lucene 的。核心思想就是在多台机器上启动多个 ES 进程实例,组成了一个 ES 集群。
|
||||
|
||||
es 中存储数据的**基本单位是索引**,比如说你现在要在 es 中存储一些订单数据,你就应该在 es 中创建一个索引 `order_idx` ,所有的订单数据就都写到这个索引里面去,一个索引差不多就是相当于是 mysql 里的一张表。
|
||||
ES 中存储数据的**基本单位是索引**,比如说你现在要在 ES 中存储一些订单数据,你就应该在 ES 中创建一个索引 `order_idx` ,所有的订单数据就都写到这个索引里面去,一个索引差不多就是相当于是 mysql 里的一张表。
|
||||
|
||||
```
|
||||
index -> type -> mapping -> document -> field。
|
||||
@ -39,7 +39,7 @@ index 相当于 mysql 里的一张表。而 type 没法跟 mysql 里去对比,
|
||||
|
||||
通过这个 replica 的方案,每个 shard 的数据都有多个备份,如果某个机器宕机了,没关系啊,还有别的数据副本在别的机器上呢。高可用了吧。
|
||||
|
||||
es 集群多个节点,会自动选举一个节点为 master 节点,这个 master 节点其实就是干一些管理的工作的,比如维护索引元数据、负责切换 primary shard 和 replica shard 身份等。要是 master 节点宕机了,那么会重新选举一个节点为 master 节点。
|
||||
ES 集群多个节点,会自动选举一个节点为 master 节点,这个 master 节点其实就是干一些管理的工作的,比如维护索引元数据、负责切换 primary shard 和 replica shard 身份等。要是 master 节点宕机了,那么会重新选举一个节点为 master 节点。
|
||||
|
||||
如果是非 master节点宕机了,那么会由 master 节点,让那个宕机节点上的 primary shard 的身份转移到其他机器上的 replica shard。接着你要是修复了那个宕机机器,重启了之后,master 节点会控制将缺失的 replica shard 分配过去,同步后续修改的数据之类的,让集群恢复正常。
|
||||
|
||||
|
@ -1,19 +1,19 @@
|
||||
## lucene 和 es 的前世今生
|
||||
lucene 是最先进、功能最强大的搜索库。如果直接基于 lucene 开发,非常复杂,即便写一些简单的功能,也要写大量的 Java 代码,需要深入理解原理。
|
||||
## Lucene 和 ES 的前世今生
|
||||
Lucene 是最先进、功能最强大的搜索库。如果直接基于 Lucene 开发,非常复杂,即便写一些简单的功能,也要写大量的 Java 代码,需要深入理解原理。
|
||||
|
||||
elasticsearch 基于 lucene,隐藏了 lucene 的复杂性,提供了简单易用的 restful api / Java api 接口(另外还有其他语言的 api 接口)。
|
||||
ElasticSearch 基于 Lucene,隐藏了 lucene 的复杂性,提供了简单易用的 RESTful api / Java api 接口(另外还有其他语言的 api 接口)。
|
||||
|
||||
* 分布式的文档存储引擎
|
||||
* 分布式的搜索引擎和分析引擎
|
||||
* 分布式,支持 PB 级数据
|
||||
|
||||
## es 的核心概念
|
||||
## ES 的核心概念
|
||||
|
||||
### Near Realtime
|
||||
近实时,有两层意思:
|
||||
|
||||
* 从写入数据到数据可以被搜索到有一个小延迟(大概是 1s)
|
||||
* 基于 es 执行搜索和分析可以达到秒级
|
||||
* 基于 ES 执行搜索和分析可以达到秒级
|
||||
|
||||
### Cluster 集群
|
||||
|
||||
@ -25,7 +25,7 @@ Node 是集群中的一个节点,节点也有一个名称,默认是随机分
|
||||
|
||||
### Document & field
|
||||
|
||||
文档是 es 中最小的数据单元,一个 document 可以是一条客户数据、一条商品分类数据、一条订单数据,通常用 json 数据结构来表示。每个 index 下的 type,都可以存储多条 document。一个 document 里面有多个 field,每个 field 就是一个数据字段。
|
||||
文档是 ES 中最小的数据单元,一个 document 可以是一条客户数据、一条商品分类数据、一条订单数据,通常用 json 数据结构来表示。每个 index 下的 type,都可以存储多条 document。一个 document 里面有多个 field,每个 field 就是一个数据字段。
|
||||
|
||||
``` json
|
||||
{
|
||||
@ -47,7 +47,7 @@ Node 是集群中的一个节点,节点也有一个名称,默认是随机分
|
||||
|
||||
### shard
|
||||
|
||||
单台机器无法存储大量数据,es 可以将一个索引中的数据切分为多个 shard,分布在多台服务器上存储。有了 shard 就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。每个 shard 都是一个 lucene index。
|
||||
单台机器无法存储大量数据,ES 可以将一个索引中的数据切分为多个 shard,分布在多台服务器上存储。有了 shard 就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。每个 shard 都是一个 lucene index。
|
||||
|
||||
### replica
|
||||
|
||||
@ -57,9 +57,9 @@ Node 是集群中的一个节点,节点也有一个名称,默认是随机分
|
||||
|
||||

|
||||
|
||||
## es 核心概念 vs. db 核心概念
|
||||
## ES 核心概念 vs. DB 核心概念
|
||||
|
||||
| es | db |
|
||||
| ES | DB |
|
||||
|---|---|
|
||||
| index | 数据库 |
|
||||
| type | 数据表 |
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 面试题
|
||||
es 在数据量很大的情况下(数十亿级别)如何提高查询效率啊?
|
||||
ES 在数据量很大的情况下(数十亿级别)如何提高查询效率啊?
|
||||
|
||||
## 面试官心理分析
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 面试题
|
||||
es 生产集群的部署架构是什么?每个索引的数据量大概有多少?每个索引大概有多少个分片?
|
||||
ES 生产集群的部署架构是什么?每个索引的数据量大概有多少?每个索引大概有多少个分片?
|
||||
|
||||
## 面试官心理分析
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
## 面试题
|
||||
es 写入数据的工作原理是什么啊?es 查询数据的工作原理是什么啊?底层的 lucene 介绍一下呗?倒排索引了解吗?
|
||||
ES 写入数据的工作原理是什么啊?ES 查询数据的工作原理是什么啊?底层的 Lucene 介绍一下呗?倒排索引了解吗?
|
||||
|
||||
## 面试官心理分析
|
||||
|
||||
|
12
summary.md
12
summary.md
@ -10,10 +10,10 @@
|
||||
- [如何设计一个消息队列?](./docs/high-concurrency/mq-design.md)
|
||||
|
||||
- [搜索引擎](./docs/high-concurrency/es-introduction.md)
|
||||
- [es 的分布式架构原理是什么?](./docs/high-concurrency/es-architecture.md)
|
||||
- [es 写入数据的工作原理是什么?](./docs/high-concurrency/es-write-query-search.md)
|
||||
- [es 在数十亿级别数量下如何提高查询效率?](./docs/high-concurrency/es-optimizing-query-performance.md)
|
||||
- [es 生产集群的部署架构是什么?](./docs/high-concurrency/es-production-cluster.md)
|
||||
- [ES 的分布式架构原理是什么?](./docs/high-concurrency/es-architecture.md)
|
||||
- [ES 写入数据的工作原理是什么?](./docs/high-concurrency/es-write-query-search.md)
|
||||
- [ES 在数十亿级别数量下如何提高查询效率?](./docs/high-concurrency/es-optimizing-query-performance.md)
|
||||
- [ES 生产集群的部署架构是什么?](./docs/high-concurrency/es-production-cluster.md)
|
||||
|
||||
- 缓存
|
||||
- [在项目中缓存是如何使用的?](./docs/high-concurrency/why-cache.md)
|
||||
@ -23,7 +23,7 @@
|
||||
- [如何保证 Redis 高并发、高可用?](./docs/high-concurrency/how-to-ensure-high-concurrency-and-high-availability-of-redis.md)
|
||||
- [Redis 的持久化有哪几种方式?](./docs/high-concurrency/redis-persistence.md)
|
||||
- [Redis 集群模式的工作原理能说一下么?](./docs/high-concurrency/redis-cluster.md)
|
||||
- [redis 的雪崩、穿透和击穿,如何应对?](./docs/high-concurrency/redis-caching-avalanche-and-caching-penetration.md)
|
||||
- [Redis 的雪崩、穿透和击穿,如何应对?](./docs/high-concurrency/redis-caching-avalanche-and-caching-penetration.md)
|
||||
- [如何保证缓存与数据库双写一致性?](./docs/high-concurrency/redis-consistence.md)
|
||||
- [如何解决 Redis 的并发竞争问题?](./docs/high-concurrency/redis-cas.md)
|
||||
- [生产环境中的 Redis 是怎么部署的?](./docs/high-concurrency/redis-production-environment.md)
|
||||
@ -49,7 +49,7 @@
|
||||
- [说一下 Dubbo 的工作原理?](./docs/distributed-system/dubbo-operating-principle.md)
|
||||
- [Dubbo 支持哪些序列化协议?](./docs/distributed-system/dubbo-serialization-protocol.md)
|
||||
- [Dubbo 负载均衡策略和集群容错策略?](./docs/distributed-system/dubbo-load-balancing.md)
|
||||
- [Dubbo 的 spi 思想是什么?](./docs/distributed-system/dubbo-spi.md)
|
||||
- [Dubbo 的 SPI 思想是什么?](./docs/distributed-system/dubbo-spi.md)
|
||||
- [如何基于 Dubbo 进行服务治理?](./docs/distributed-system/dubbo-service-management.md)
|
||||
- [分布式服务接口的幂等性如何设计?](./docs/distributed-system/distributed-system-idempotency.md)
|
||||
- [分布式服务接口请求的顺序性如何保证?](./docs/distributed-system/distributed-system-request-sequence.md)
|
||||
|
Loading…
Reference in New Issue
Block a user