mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 04:22:22 +00:00
remove all ascii img
This commit is contained in:
parent
243aa31f1a
commit
789588b195
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
> 在线交易处理(OLTP, Online transaction processing)是指透过信息系统、电脑网络及数据库,以线上交易的方式处理一般即时性的作业数据,和更早期传统数据库系统大量批量的作业方式并不相同。OLTP通常被运用于自动化的数据处理工作,如订单输入、金融业务…等反复性的日常性交易活动。和其相对的是属于决策分析层次的联机分析处理(OLAP)。
|
> 在线交易处理(OLTP, Online transaction processing)是指透过信息系统、电脑网络及数据库,以线上交易的方式处理一般即时性的作业数据,和更早期传统数据库系统大量批量的作业方式并不相同。OLTP通常被运用于自动化的数据处理工作,如订单输入、金融业务…等反复性的日常性交易活动。和其相对的是属于决策分析层次的联机分析处理(OLAP)。
|
||||||
|
|
||||||
在互联网的业务场景中,也有一些实时性要求不高(可以接受多 s 的延迟),但是查询复杂性却很高的场景。举个例子,在电商的 wms 系统中,或者在大多数业务场景丰富的 crm 或者客服系统中,可能需要提供几十个字段的随意组合查询功能。这种系统的数据维度天生众多,比如一个电商的 wms 中对一件货物的描述,可能有下面这些字段:
|
在互联网的业务场景中,也有一些实时性要求不高(可以接受多秒的延迟),但是查询复杂性却很高的场景。举个例子,在电商的wms系统中,或者在大多数业务场景丰富的crm或者客服系统中,可能需要提供几十个字段的随意组合查询功能。这种系统的数据维度天生众多,比如一个电商的wms中对一件货物的描述,可能有下面这些字段:
|
||||||
|
|
||||||
> 仓库id,入库时间,库位分区id,储存货架id,入库操作员id,出库操作员id,库存数量,过期时间,sku类型,产品品牌,产品分类,内件数量
|
> 仓库id,入库时间,库位分区id,储存货架id,入库操作员id,出库操作员id,库存数量,过期时间,sku类型,产品品牌,产品分类,内件数量
|
||||||
|
|
||||||
@ -20,34 +20,15 @@
|
|||||||
|
|
||||||
## 搜索引擎
|
## 搜索引擎
|
||||||
|
|
||||||
elasticsearch 是开源分布式搜索引擎的霸主,其依赖于 Lucene 实现,在部署和运维方面做了很多优化。当今搭建一个分布式搜索引擎比起 Sphinx 的时代已经是容易很多很多了。只要简单配置客户端 ip 和端口就可以了。
|
Elasticsearch是开源分布式搜索引擎的霸主,其依赖于Lucene实现,在部署和运维方面做了很多优化。当今搭建一个分布式搜索引擎比起Sphinx的时代已经是容易很多很多了。只要简单配置客户端IP和端口就可以了。
|
||||||
|
|
||||||
### 倒排列表
|
### 倒排列表
|
||||||
|
|
||||||
虽然es是针对搜索场景来定制的,但如前文所言,实际应用中常常用es来作为database来使用,就是因为倒排列表的特性。可以用比较朴素的观点来理解倒排索引:
|
虽然es是针对搜索场景来定制的,但如前文所言,实际应用中常常用es来作为database来使用,就是因为倒排列表的特性。可以用比较朴素的观点来理解倒排索引:
|
||||||
|
|
||||||
```
|

|
||||||
┌─────────────────┐ ┌─────────────┬─────────────┬─────────────┬─────────────┐
|
|
||||||
│ order_id: 103 │──────▶│ doc_id:4231 │ doc_id:4333 │ doc_id:5123 │ doc_id:9999 │
|
|
||||||
└─────────────────┘ └─────────────┴─────────────┴─────────────┴─────────────┘
|
|
||||||
|
|
||||||
|
对Elasticsearch中的数据进行查询时,本质就是求多个排好序的序列求交集。非数值类型字段涉及到分词问题,大多数内部使用场景下,我们可以直接使用默认的bi-gram分词。什么是bi-gram分词呢:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
┌─────────────────┐ ┌─────────────┬─────────────┬─────────────┬─────────────┬─────────────┐
|
|
||||||
│ sku_id: 30221 │──────▶│ doc_id:4231 │ doc_id:5123 │ doc_id:5644 │ doc_id:7801 │ doc_id:9999 │
|
|
||||||
└─────────────────┘ └─────────────┴─────────────┴─────────────┴─────────────┴─────────────┘
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
┌─────────────────┐ ┌─────────────┬─────────────┬─────────────┬─────────────┬─────────────┬─────────────┬─────────────┐
|
|
||||||
│ city_id: 3 │──────▶│ doc_id:5123 │ doc_id:9999 │doc_id:10232 │doc_id:54321 │doc_id:63142 │doc_id:71230 │doc_id:90123 │
|
|
||||||
└─────────────────┘ └─────────────┴─────────────┴─────────────┴─────────────┴─────────────┴─────────────┴─────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
对 es 中的数据进行查询时,本质就是求多个排好序的序列求交集。非数值类型字段涉及到分词问题,大多数内部使用场景下,我们可以直接使用默认的 bi-gram 分词。什么是 bi-gram 分词呢:
|
|
||||||
|
|
||||||
即将所有Ti和T(i+1)组成一个词(在es中叫term),然后再编排其倒排列表,这样我们的倒排列表大概就是这样的:
|
即将所有Ti和T(i+1)组成一个词(在es中叫term),然后再编排其倒排列表,这样我们的倒排列表大概就是这样的:
|
||||||
|
|
||||||
@ -178,7 +159,7 @@ if field_1 == 1 || field_2 == 2 {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
这些 Go 代码里 if 后面跟着的表达式在编程语言中有专有名词来表达 Boolean Expression:
|
这些Go代码里`if`后面跟着的表达式在编程语言中有专有名词来表达Boolean Expression:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
4 > 1
|
4 > 1
|
||||||
@ -186,7 +167,7 @@ if field_1 == 1 || field_2 == 2 {
|
|||||||
3 < i && x > 10
|
3 < i && x > 10
|
||||||
```
|
```
|
||||||
|
|
||||||
es 的 Bool Query 方案,实际上就是用 json 来表达了这种程序语言中的 Boolean Expression,为什么可以这么做呢?因为 json 本身是可以表达树形结构的,我们的程序代码在被编译器 parse 之后,也会变成 AST,而 AST 抽象语法树,顾名思义,就是树形结构。理论上 json 能够完备地表达一段程序代码被 parse 之后的结果。这里的 Boolean Expression 被编译器 Parse 之后也会生成差不多的树形结构,而且只是整个编译器实现的一个很小的子集。
|
es的`Bool Query`方案,实际上就是用json来表达了这种程序语言中的Boolean Expression,为什么可以这么做呢?因为json本身是可以表达树形结构的,我们的程序代码在被编译器parse之后,也会变成AST,而AST抽象语法树,顾名思义,就是树形结构。理论上json能够完备地表达一段程序代码被parse之后的结果。这里的Boolean Expression被编译器Parse之后也会生成差不多的树形结构,而且只是整个编译器实现的一个很小的子集。
|
||||||
|
|
||||||
### 基于 client sdk 做开发
|
### 基于 client sdk 做开发
|
||||||
|
|
||||||
@ -281,13 +262,13 @@ func deleteDocument(
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
因为 lucene 的性质,本质上搜索引擎内的数据是不可变的,所以如果要对 document 进行更新,实际上是按照 id 进行完全覆盖的操作,所以与插入的情况是一样的。
|
因为Lucene的性质,本质上搜索引擎内的数据是不可变的,所以如果要对文档进行更新,实际上是按照id进行完全覆盖的操作,所以与插入的情况是一样的。
|
||||||
|
|
||||||
使用es作为数据库使用时,需要注意,因为es有索引合并的操作,所以数据插入到es中到可以查询的到需要一段时间(由es的refresh_interval决定)。所以千万不要把es当成强一致的关系型数据库来使用。
|
使用es作为数据库使用时,需要注意,因为es有索引合并的操作,所以数据插入到es中到可以查询的到需要一段时间(由es的refresh_interval决定)。所以千万不要把es当成强一致的关系型数据库来使用。
|
||||||
|
|
||||||
### 将 sql 转换为 DSL
|
### 将 sql 转换为 DSL
|
||||||
|
|
||||||
比如我们有一段 bool 表达式,user_id = 1 and (product_id = 1 and (star_num = 4 or star_num = 5) and banned = 1),写成 SQL 是如下形式:
|
比如我们有一段bool表达式,`user_id = 1 and (product_id = 1 and (star_num = 4 or star_num = 5) and banned = 1)`,写成SQL是如下形式:
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
select * from xxx where user_id = 1 and (
|
select * from xxx where user_id = 1 and (
|
||||||
@ -378,25 +359,7 @@ SQL 的 where 部分就是 boolean expression。我们之前提到过,这种 b
|
|||||||
|
|
||||||
### 通过时间戳进行增量数据同步
|
### 通过时间戳进行增量数据同步
|
||||||
|
|
||||||
```
|

|
||||||
┌────────────────────────┐ ┌────────────────────────┐
|
|
||||||
│ move 10 min data to es │ │ move 10 min data to es │
|
|
||||||
└────────────────────────┘ └────────────────────────┘
|
|
||||||
|
|
||||||
│ │ ┌───────────────┐
|
|
||||||
───────────────┼────────────────┬──────────────┴─────────────┬──────────────▶ │ time passes │
|
|
||||||
│ ┌───────┐ │ │ └───────────────┘
|
|
||||||
│◀──┤ 10min ├───▶│ ┌────────────────────────┐
|
|
||||||
│ └───────┘ │ │ move 10 min data to es │
|
|
||||||
│ └────────────────────────┘
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
┌────────────────────────┐
|
|
||||||
│ move 10 min data to es │
|
|
||||||
└────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
这种同步方式与业务强绑定,例如wms系统中的出库单,我们并不需要非常实时,稍微有延迟也可以接受,那么我们可以每分钟从MySQL的出库单表中,把最近十分钟创建的所有出库单取出,批量存入es中,具体的逻辑实际上就是一条SQL:
|
这种同步方式与业务强绑定,例如wms系统中的出库单,我们并不需要非常实时,稍微有延迟也可以接受,那么我们可以每分钟从MySQL的出库单表中,把最近十分钟创建的所有出库单取出,批量存入es中,具体的逻辑实际上就是一条SQL:
|
||||||
|
|
||||||
@ -416,55 +379,9 @@ select * from wms_orders where update_time >= date_sub(
|
|||||||
|
|
||||||
### 通过 binlog 进行数据同步
|
### 通过 binlog 进行数据同步
|
||||||
|
|
||||||
```
|

|
||||||
┌────────────────────────┐
|
|
||||||
│ MySQL master │
|
|
||||||
└────────────────────────┘
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌───────────────────┐
|
|
||||||
│ row format binlog │
|
|
||||||
└───────────────────┘
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
┌───────────────┴──────────────┐
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
▼ ▼
|
|
||||||
┌────────────────────────┐ ┌─────────────────┐
|
|
||||||
│ MySQL slave │ │ canal │
|
|
||||||
└────────────────────────┘ └─────────────────┘
|
|
||||||
│
|
|
||||||
┌─────────┴──────────┐
|
|
||||||
│ parsed binlog │
|
|
||||||
└─────────┬──────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌────────────────┐
|
|
||||||
│ kafka │─────┐
|
|
||||||
└────────────────┘ │
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
┌───────────┴──────┐
|
|
||||||
│ kafka consumer │
|
|
||||||
└───────────┬──────┘
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│ ┌────────────────┐
|
|
||||||
└─────▶│ elasticsearch │
|
|
||||||
└────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
业界使用较多的是阿里开源的 canal,来进行 binlog 解析与同步。canal 会伪装成 MySQL 的从库,然后解析好行格式的 binlog,再以更容易解析的格式(例如 json) 发送到消息队列。
|
业界使用较多的是阿里开源的Canal,来进行binlog解析与同步。canal会伪装成MySQL的从库,然后解析好行格式的binlog,再以更容易解析的格式(例如json)发送到消息队列。
|
||||||
|
|
||||||
由下游的kafka消费者负责把上游数据表的自增主键作为es的document的id进行写入,这样可以保证每次接收到binlog时,对应id的数据都被覆盖更新为最新。MySQL的row格式的binlog会将每条记录的所有字段都提供给下游,所以实际上在向异构数据目标同步数据时,不需要考虑数据是插入还是更新,只要一律按id进行覆盖即可。
|
由下游的kafka消费者负责把上游数据表的自增主键作为es的document的id进行写入,这样可以保证每次接收到binlog时,对应id的数据都被覆盖更新为最新。MySQL的row格式的binlog会将每条记录的所有字段都提供给下游,所以实际上在向异构数据目标同步数据时,不需要考虑数据是插入还是更新,只要一律按id进行覆盖即可。
|
||||||
|
|
||||||
|
BIN
images/ch6-binlog-sync.png
Normal file
BIN
images/ch6-binlog-sync.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
images/ch6-posting_list.png
Normal file
BIN
images/ch6-posting_list.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
images/ch6-sync.png
Normal file
BIN
images/ch6-sync.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Loading…
x
Reference in New Issue
Block a user