mirror of
https://github.com/chai2010/advanced-go-programming-book.git
synced 2025-05-24 04:22:22 +00:00
fix img for ch5-9
This commit is contained in:
parent
c718dec526
commit
f435e89a90
@ -81,35 +81,13 @@ func isTrue(phone string) bool {
|
|||||||
|
|
||||||
这种情况可以按照指定的百分比,返回对应的 true 和 false,和上面的单纯按照概率的区别是这里我们需要调用方提供给我们一个输入参数,我们以该输入参数作为源来计算哈希,并以哈希后的结果来求模,并返回结果。这样可以保证同一个用户的返回结果多次调用是一致的,在下面这种场景下,必须使用这种结果可预期的灰度算法:
|
这种情况可以按照指定的百分比,返回对应的 true 和 false,和上面的单纯按照概率的区别是这里我们需要调用方提供给我们一个输入参数,我们以该输入参数作为源来计算哈希,并以哈希后的结果来求模,并返回结果。这样可以保证同一个用户的返回结果多次调用是一致的,在下面这种场景下,必须使用这种结果可预期的灰度算法:
|
||||||
|
|
||||||
```shell
|

|
||||||
.---------.
|
|
||||||
( user_2 )
|
如果采用随机策略,可能会出现像下图这样的问题:
|
||||||
`---------'
|
|
||||||
+--------+
|

|
||||||
.---------. | set.V2 |---------------------+
|
|
||||||
( user_1 ) +--------+ |
|
举个具体的例子,网站的注册环节,可能有两套API,按照用户ID进行灰度,分别是不同的存取逻辑。如果存储时使用了V1版本的API而获取时使用V2版本的API,那么就可能出现用户注册成功后反而返回注册失败消息的诡异问题。
|
||||||
`---------' | |
|
|
||||||
+--------+ | |
|
|
||||||
+--------------| set.V2 | | |
|
|
||||||
| +--------+ | |
|
|
||||||
| | | |
|
|
||||||
v | | v
|
|
||||||
+-------------+ | | +-------------+
|
|
||||||
| storage_v1 | | | | storage_v2 |
|
|
||||||
+-------------+ | | +-------------+
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| | | |
|
|
||||||
| v | |
|
|
||||||
| +--------+ | |
|
|
||||||
+------------->| get.V2 | | |
|
|
||||||
+--------+ | |
|
|
||||||
| |
|
|
||||||
v |
|
|
||||||
+--------+ |
|
|
||||||
| get.V2 |<--------------------+
|
|
||||||
+--------+
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5.9.3 如何实现一套灰度发布系统
|
## 5.9.3 如何实现一套灰度发布系统
|
||||||
|
|
||||||
@ -136,7 +114,7 @@ func isPassed(cityID int) bool {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
如果公司给 cityID 赋的值比较大,那么我们可以考虑用 map 来存储映射关系,map 的查询比数组稍慢,但扩展会灵活一些:
|
如果公司给cityID赋的值比较大,那么我们可以考虑用map来存储映射关系,map的查询比数组稍慢,但扩展会灵活一些:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
var cityID2Open = map[int]struct{}{}
|
var cityID2Open = map[int]struct{}{}
|
||||||
@ -157,7 +135,7 @@ func isPassed(cityID int) bool {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
按白名单、按业务线、按 UA、按分发渠道发布,本质上和按城市发布是一样的,这里就不再赘述了。
|
按白名单、按业务线、按UA、按分发渠道发布,本质上和按城市发布是一样的,这里就不再赘述了。
|
||||||
|
|
||||||
按概率发布稍微特殊一些,不过不考虑输入实现起来也很简单:
|
按概率发布稍微特殊一些,不过不考虑输入实现起来也很简单:
|
||||||
|
|
||||||
@ -185,7 +163,7 @@ func isPassed(rate int) bool {
|
|||||||
|
|
||||||
### 5.9.3.2 哈希算法
|
### 5.9.3.2 哈希算法
|
||||||
|
|
||||||
求哈希可用的算法非常多,比如 md5,crc32,sha1 等等,但我们这里的目的只是为了给这些数据做个映射,并不想要因为计算哈希消耗过多的 cpu,所以现在业界使用较多的算法是 murmurhash,下面是我们对这些常见的 hash 算法的简单 benchmark:
|
求哈希可用的算法非常多,比如md5,crc32,sha1等等,但我们这里的目的只是为了给这些数据做个映射,并不想要因为计算哈希消耗过多的cpu,所以现在业界使用较多的算法是murmurhash,下面是我们对这些常见的hash算法的简单benchmark:
|
||||||
|
|
||||||
hash.go:
|
hash.go:
|
||||||
|
|
||||||
@ -263,13 +241,13 @@ PASS
|
|||||||
ok _/Users/caochunhui/test/go/hash_bench 7.050s
|
ok _/Users/caochunhui/test/go/hash_bench 7.050s
|
||||||
```
|
```
|
||||||
|
|
||||||
可见 murmurhash 相比其它的算法有三倍以上的性能提升。
|
可见murmurhash相比其它的算法有三倍以上的性能提升。
|
||||||
|
|
||||||
### 5.9.3.3 分布是否均匀
|
### 5.9.3.3 分布是否均匀
|
||||||
|
|
||||||
对于哈希算法来说,性能是一方面的问题,另一方面还要考虑哈希后的值是否分布均匀。
|
对于哈希算法来说,性能是一方面的问题,另一方面还要考虑哈希后的值是否分布均匀。
|
||||||
|
|
||||||
我们先以 15810000000 开头,造一千万个和手机号类似的数字,然后将计算后的哈希值分十个桶,并观察计数是否均匀:
|
我们先以15810000000开头,造一千万个和手机号类似的数字,然后将计算后的哈希值分十个桶,并观察计数是否均匀:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@ -301,4 +279,4 @@ map[7:999475 5:1000359 1:999945 6:1000200 3:1000193 9:1000765 2:1000044 \
|
|||||||
4:1000343 8:1000823 0:997853]
|
4:1000343 8:1000823 0:997853]
|
||||||
```
|
```
|
||||||
|
|
||||||
偏差基本都在 1/100 以内,是可以接受的。
|
偏差都在1/100以内,可以接受。
|
||||||
|
BIN
images/ch5-set-time-line.png
Normal file
BIN
images/ch5-set-time-line.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.5 KiB |
BIN
images/ch5-set-time-line_2.png
Normal file
BIN
images/ch5-set-time-line_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Loading…
x
Reference in New Issue
Block a user