每日新闻

每日新闻

GoCN每日新闻资讯
有问必答

有问必答

Go相关的问题,技术相关的问题
文章分享

文章分享

技术文章分享,让知识传播给更多的人
招聘应聘

招聘应聘

为Gopher服务的招聘应聘平台

关于规范招聘信息发帖说明 置顶

招聘应聘 回复了问题 • 10 人关注 • 4 个回复 • 5971 次浏览 • 2019-10-04 10:59 • 来自相关话题

【蚂蚁金服】蚂蚁金服研发效能团队招人啦!

回复

招聘应聘vs小金刚 发起了问题 • 1 人关注 • 0 个回复 • 62 次浏览 • 15 小时前 • 来自相关话题

GoCN每日新闻(2019-12-10)

回复

每日新闻傅小黑 发起了问题 • 1 人关注 • 0 个回复 • 750 次浏览 • 17 小时前 • 来自相关话题

百度GOPROXY代理服务

开源程序dolfly 发表了文章 • 0 个评论 • 72 次浏览 • 17 小时前 • 来自相关话题

百度GOPROXY代理服务https://goproxy.baidu.com/ ...查看全部

百度GOPROXY代理服务


https://goproxy.baidu.com/

GoCN每日新闻(2019-12-09)

回复

每日新闻kevin 发起了问题 • 1 人关注 • 0 个回复 • 2038 次浏览 • 1 天前 • 来自相关话题

gout v0.0.4发布,新增接口benchmark功能

开源程序guonaihong 发表了文章 • 0 个评论 • 146 次浏览 • 1 天前 • 来自相关话题

gout简介gout 是go开发的流式http client。v0.0.4版本主要功能是benchmark功能拥有此版本gout,助你很方便开发出apache ab此类轮子。benchmark功能性能如何 ...查看全部

gout简介

gout 是go开发的流式http client。v0.0.4版本主要功能是benchmark功能

拥有此版本gout,助你很方便开发出apache ab此类轮子。

benchmark功能性能如何


Changlog:

  • #95 优化文档
  • #97 修改New接口
  • #98 优化文档2
  • #103 quick start增加综合示例
  • #107 BindHeader函数tag设置没生效(fix)
  • #109 修改debug模式默认配色方案
  • #92 benckmark模式
  • #105 优化超时API
  • #102 提升测试覆盖度

项目地址

github地址https://github.com/guonaihong/gout


gin 注解路由,自动参数绑定工具

文章分享xie1xiao1jun 发表了文章 • 0 个评论 • 198 次浏览 • 2 天前 • 来自相关话题

ginprcgolang ...查看全部

ginprc

golang gin 参数自动绑定工具

  • 支持 rpc 自动映射
  • 支持对象注册
  • 支持注解路由
  • 基于 go-gin 的 json restful 风格的 golang 基础库
  • 自带请求参数过滤及绑定实现 binding:"required" validator
  • 代码注册简单且支持多种注册方式

api 接口说明

支持 3 种接口模式

  • func(gin.Context) //go-gin 原始接口
    func(
     api.Context) // 自定义的 context 类型
  • func(api.Context,req) // 自定义的 context 类型,带 request 请求参数
    func(
     api.Context,*req)
  • func(gin.Context,req) //go-gin context 类型,带 request 请求参数
    func(*gin.Context,req)

示例代码

初始化项目 (本项目以 ginweb 为名字)

``` go mod init ginweb ```

代码 (详细地址:https://github.com/xxjwxc/ginrpc/tree/master/sample/ginweb)

  package main

import (
"fmt"
"net/http"

_ "ginweb/routers" // debug模式需要添加[mod]/routers 注册注解路由

"github.com/gin-gonic/gin"
"github.com/xxjwxc/ginrpc"
"github.com/xxjwxc/ginrpc/api"
)

type ReqTest struct {
Access_token string `json:"access_token"`
UserName string `json:"user_name" binding:"required"` // 带校验方式
Password string `json:"password"`
}

// Hello ...
type Hello struct {
Index int
}

// Hello 带注解路由(参考beego形式)
// @router /block [post,get]
func (s *Hello) Hello(c *api.Context, req *ReqTest) {
fmt.Println(req)
fmt.Println(s.Index)
c.JSON(http.StatusOK, "ok")
}

// Hello2 不带注解路由(参数为2默认post)
func (s *Hello) Hello2(c *gin.Context, req ReqTest) {
fmt.Println(req)
fmt.Println(s.Index)
c.JSON(http.StatusOK, "ok")
}

//TestFun1 gin 默认的函数回调地址
func TestFun1(c *gin.Context) {
fmt.Println(c.Params)
c.String(200, "ok")
}

//TestFun2 自定义context的函数回调地址
func TestFun2(c *api.Context) {
fmt.Println(c.Params)
c.JSON(http.StatusOK, "ok")
}

//TestFun3 带自定义context跟已解析的req参数回调方式
func TestFun3(c *api.Context, req *ReqTest) {
fmt.Println(c.Params)
fmt.Println(req)
c.JSON(http.StatusOK, "ok")
}

//TestFun4 带自定义context跟已解析的req参数回调方式
func TestFun4(c *gin.Context, req ReqTest) {
fmt.Println(c.Params)
fmt.Println(req)

c.JSON(http.StatusOK, req)
}

func main() {
base := ginrpc.New(ginrpc.WithCtx(func(c *gin.Context) interface{} {
return api.NewCtx(c)
}), ginrpc.WithDebug(true), ginrpc.WithGroup("xxjwxc"))

router := gin.Default()
h := new(Hello)
h.Index = 123
base.Register(router, h) // 对象注册
router.POST("/test1", base.HandlerFunc(TestFun1)) // 函数注册
router.POST("/test2", base.HandlerFunc(TestFun2))
router.POST("/test3", base.HandlerFunc(TestFun3))
router.POST("/test4", base.HandlerFunc(TestFun4))
base.RegisterHandlerFunc(router, []string{"post", "get"}, "/test", TestFun1) // 多种请求方式注册

router.Run(":8080")
}
  • curl
    curl 'http://127.0.0.1:8080/test4' -H 'Content-Type: application/json' -d '{"access_token":"111", "user_name":"222", "password":"333"}'

注解路由

  • 1. 注解路由会自动创建 [mod]/routers/gen_router.go 文件 需要在调用时加:

    _ "[mod]/routers" // debug模式需要添加[mod]/routers 注册注解路由

    默认也会在项目根目录生成 [gen_router.data] 文件 (保留次文件,可以不用添加上面代码嵌入)

  • 2. 注解路由调用方式:

    base := ginrpc.New(ginrpc.WithCtx(func(c *gin.Context) interface{} {
    return api.NewCtx(c)
    }), ginrpc.WithDebug(true), ginrpc.WithGroup("xxjwxc"))
    base.Register(router, new(Hello)) // 对象注册
    router.Run(":8080")

    详细请看 demo ginweb

  • 3. 执行 curl,可以自动参数绑定。直接看结果

    curl 'http://127.0.0.1:8080/xxjwxc/block' -H 'Content-Type: application/json' -d '{"access_token":"111", "user_name":"222", "password":"333"}'
    curl 'http://127.0.0.1:8080/xxjwxc/hello.hello2' -H 'Content-Type: application/json' -d '{"access_token":"111", "user_name":"222", "password":"333"}'
  • 4 参数说明
    ginrpc.WithCtx : 设置自定义 context
    ginrpc.WithDebug (true) : 设置 debug 模式
    ginrpc.WithGroup ("xxjwxc") : 添加路由前缀 (也可以使用 gin.Group 分组)
    ginrpc.WithBigCamel (true) : 设置大驼峰标准 (false 为 web 模式,_, 小写)

    更多

下一步

1.导出api文档
2.导出postman测试配置

代码地址: ginprc 如果喜欢请给星支持

传送门

如果你喜欢,请'star'

GoCN每日新闻(2019-12-08)

回复

每日新闻罗发宣 发起了问题 • 1 人关注 • 0 个回复 • 2863 次浏览 • 2 天前 • 来自相关话题

GoCN每日新闻(2019-12-07)

回复

每日新闻samurai 发起了问题 • 1 人关注 • 0 个回复 • 3784 次浏览 • 3 天前 • 来自相关话题

GoCN每日新闻(2019-12-06)

回复

每日新闻cloudy 发起了问题 • 1 人关注 • 0 个回复 • 4036 次浏览 • 4 天前 • 来自相关话题

分布式图数据库 Nebula Graph 中的集群快照实践

文章分享NebulaGraph 发表了文章 • 0 个评论 • 185 次浏览 • 4 天前 • 来自相关话题


1 概述


1.1 需求背景


图数据库 Nebula Graph 在生产环境中将拥有庞大的数据量和高频率的业务处理,在实际的运行中将不可避免的发生人为的、硬件或业务处理错误的问题,某些严重错误将导致集群无法正常运行或集群中的数据失效。当集群处于无法启动或数据失效的状态时,重新搭建集群并重新倒入数据都将是一个繁琐并耗时的工程。针对此问题,Nebula Graph 提供了集群 snapshot 的创建功能。


Snapshot 功能需要预先提供集群在某个时间点 snapshot 的创建功能,以备发生灾难性问题时用历史 snapshot 便捷地将集群恢复到一个可用状态。


1.2 术语


本文主要会用到以下术语:



  • **StorageEngine:**Nebula Graph 的最小物理存储单元,目前支持 RocksDB 和 HBase,在本文中只针对 RocksDB。

  • Partition:Nebula Graph 的最小逻辑存储单元,一个 StorageEngine 可包含多个 Partition。Partition 分为 leader 和 follower 的角色,Raftex 保证了 leader 和 follower 之间的数据一致性。

  • GraphSpace:每个 GraphSpace 是一个独立的业务 Graph  单元,每个 GraphSpace 有其独立的 tag 和 edge 集合。一个 Nebula Graph 集群中可包含多个 GraphShpace。

  • checkpoint:针对 StorageEngine 的一个时间点上的快照,checkpoint 可以作为全量备份的一个 backup 使用。checkpoint files是 sst files 的一个硬连接。

  • snapshot:本文中的 snapshot 是指 Nebula Graph 集群的某个时间点的快照,即集群中所有 StorageEngine 的 checkpoint 的集合。通过 snapshot 可以将集群恢复到某个 snapshot 创建时的状态。

  • wal:Write-Ahead Logging ,用 raftex 保证 leader 和 follower 的一致性。


2 系统构架


2.1 系统整体架构


image


2.2 存储系统结构关系


image


2.3 存储系统物理文件结构


[bright2star@hp-server storage]$ tree
.
└── nebula
└── 1
├── checkpoints
│ ├── SNAPSHOT_2019_12_04_10_54_42
│ │ ├── data
│ │ │ ├── 000006.sst
│ │ │ ├── 000008.sst
│ │ │ ├── CURRENT
│ │ │ ├── MANIFEST-000007
│ │ │ └── OPTIONS-000005
│ │ └── wal
│ │ ├── 1
│ │ │ └── 0000000000000000233.wal
│ │ ├── 2
│ │ │ └── 0000000000000000233.wal
│ │ ├── 3
│ │ │ └── 0000000000000000233.wal
│ │ ├── 4
│ │ │ └── 0000000000000000233.wal
│ │ ├── 5
│ │ │ └── 0000000000000000233.wal
│ │ ├── 6
│ │ │ └── 0000000000000000233.wal
│ │ ├── 7
│ │ │ └── 0000000000000000233.wal
│ │ ├── 8
│ │ │ └── 0000000000000000233.wal
│ │ └── 9
│ │ └── 0000000000000000233.wal
│ └── SNAPSHOT_2019_12_04_10_54_44
│ ├── data
│ │ ├── 000006.sst
│ │ ├── 000008.sst
│ │ ├── 000009.sst
│ │ ├── CURRENT
│ │ ├── MANIFEST-000007
│ │ └── OPTIONS-000005
│ └── wal
│ ├── 1
│ │ └── 0000000000000000236.wal
│ ├── 2
│ │ └── 0000000000000000236.wal
│ ├── 3
│ │ └── 0000000000000000236.wal
│ ├── 4
│ │ └── 0000000000000000236.wal
│ ├── 5
│ │ └── 0000000000000000236.wal
│ ├── 6
│ │ └── 0000000000000000236.wal
│ ├── 7
│ │ └── 0000000000000000236.wal
│ ├── 8
│ │ └── 0000000000000000236.wal
│ └── 9
│ └── 0000000000000000236.wal
├── data
复制代码

3 处理逻辑分析


3.1 逻辑分析


image


Create snapshot  由 client api  或 console  触发, graph server  对 create snapshot  的 AST 进行解析,然后通过 meta client  将创建请求发送到 meta server 。 meta server  接到请求后,首先会获取所有的 active host ,并创建 adminClient  所需的 request 。通过 adminClient  将创建请求发送到每个 StorageEngine ,StorageEngine 收到 create 请求后,会遍历指定 space 的全部 StorageEngine,并创建 checkpoint ,随后对 StorageEngine 中的全部 partition  的 wal 做 hardlink。在创建 checkpoint 和 wal hardlink 时,因为已经提前向所有 leader partition 发送了 write blocking 请求,所以此时数据库是只读状态的。


因为 snapshot 的名称是由系统的 timestamp 自动生成,所以不必担心 snapshot 的重名问题。如果创建了不必要的 snapshot,可以通过 drop snapshot 命令删除已创建的 snapshot。


3.2 Create Snapshot


image


3.3 Create Checkpoint


image


4 关键代码实现


4.1 Create Snapshot


folly::Future<Status> AdminClient::createSnapshot(GraphSpaceID spaceId, const std::string& name) {
// 获取所有storage engine的host
auto allHosts = ActiveHostsMan::getActiveHosts(kv_);
storage::cpp2::CreateCPRequest req;

// 指定spaceId,目前是对所有space做checkpoint,list spaces 工作已在调用函数中执行。
req.set_space_id(spaceId);

// 指定 snapshot name,已有meta server根据时间戳产生。
// 例如:SNAPSHOT_2019_12_04_10_54_44
req.set_name(name);
folly::Promise<Status> pro;
auto f = pro.getFuture();

// 通过getResponse接口发送请求到所有的storage engine.
getResponse(allHosts, 0, std::move(req), [] (auto client, auto request) {
return client->future_createCheckpoint(request);
}, 0, std::move(pro), 1 /*The snapshot operation only needs to be retried twice*/);
return f;
}
复制代码

4.2 Create Checkpoint


ResultCode NebulaStore::createCheckpoint(GraphSpaceID spaceId, const std::string& name) {
auto spaceRet = space(spaceId);
if (!ok(spaceRet)) {
return error(spaceRet);
}
auto space = nebula::value(spaceRet);

// 遍历属于本space中的所有StorageEngine
for (auto& engine : space->engines_) {

// 首先对StorageEngine做checkpoint
auto code = engine->createCheckpoint(name);
if (code != ResultCode::SUCCEEDED) {
return code;
}

// 然后对本StorageEngine中的所有partition的last wal做hardlink
auto parts = engine->allParts();
for (auto& part : parts) {
auto ret = this->part(spaceId, part);
if (!ok(ret)) {
LOG(ERROR) << "Part not found. space : " << spaceId << " Part : " << part;
return error(ret);
}
auto walPath = folly::stringPrintf("%s/checkpoints/%s/wal/%d",
engine->getDataRoot(), name.c_str(), part);
auto p = nebula::value(ret);
if (!p->linkCurrentWAL(walPath.data())) {
return ResultCode::ERR_CHECKPOINT_ERROR;
}
}
}
return ResultCode::SUCCEEDED;
}
复制代码

5 用户使用帮助


5.1 CREATE SNAPSHOT


CREATE SNAPSHOT  即对整个集群创建当前时间点的快照,snapshot 名称由 meta server 的 timestamp 组成



在创建过程中可能会创建失败,当前版本不支持创建失败的垃圾回收的自动功能,后续将计划在 metaServer 中开发 cluster checker 的功能,将通过异步线程检查集群状态,并自动回收 snapshot 创建失败的垃圾文件。



当前版本如果 snapshot 创建失败,必须通过 DROP SNAPSHOT 命令清除无效的 snapshot。


当前版本不支持对指定的 space 做 snapshot,当执行 CREATE SNAPSHOT 后,将对集群中的所有 space 创建快照。
CREATE SNAPSHOT 语法:


CREATE SNAPSHOT
复制代码

以下为笔者创建 3 个 snapshot 的例子:


(user@127.0.0.1) [default_space]> create snapshot;
Execution succeeded (Time spent: 28211/28838 us)

(user@127.0.0.1) [default_space]> create snapshot;
Execution succeeded (Time spent: 22892/23923 us)

(user@127.0.0.1) [default_space]> create snapshot;
Execution succeeded (Time spent: 18575/19168 us)
复制代码

我们用 5.3 提及的 SHOW SNAPSHOTS 命令看下现在有的快照


(user@127.0.0.1) [default_space]> show snapshots;
===========================================================
| Name | Status | Hosts |
===========================================================
| SNAPSHOT_2019_12_04_10_54_36 | VALID | 127.0.0.1:77833 |
-----------------------------------------------------------
| SNAPSHOT_2019_12_04_10_54_42 | VALID | 127.0.0.1:77833 |
-----------------------------------------------------------
| SNAPSHOT_2019_12_04_10_54_44 | VALID | 127.0.0.1:77833 |
-----------------------------------------------------------
Got 3 rows (Time spent: 907/1495 us)
复制代码

从上 SNAPSHOT_2019_12_04_10_54_36  可见 snapshot 名同 timestamp 有关。


5.2 DROP SNAPSHOT


DROP SNAPSHOT 即删除指定名称的 snapshot,可以通过 SHOW SNAPSHOTS 命令获取 snapshot 的名称,DROP SNAPSHOT 既可以删除有效的 snapshot,也可以删除创建失败的 snapshot。


语法:


DROP SNAPSHOT name
复制代码

笔者删除了 5.1 成功创建的 snapshot SNAPSHOT_2019_12_04_10_54_36 ,并用SHOW SNAPSHOTS 命令查看现有的 snapshot。


(user@127.0.0.1) [default_space]> drop snapshot SNAPSHOT_2019_12_04_10_54_36;
Execution succeeded (Time spent: 6188/7348 us)

(user@127.0.0.1) [default_space]> show snapshots;
===========================================================
| Name | Status | Hosts |
===========================================================
| SNAPSHOT_2019_12_04_10_54_42 | VALID | 127.0.0.1:77833 |
-----------------------------------------------------------
| SNAPSHOT_2019_12_04_10_54_44 | VALID | 127.0.0.1:77833 |
-----------------------------------------------------------
Got 2 rows (Time spent: 1097/1721 us)
复制代码

5.3 SHOW SNAPSHOTS


SHOW SNAPSHOTS 可查看集群中所有的 snapshot,可以通过 SHOW SNAPSHOTS 命令查看其状态(VALID 或 INVALID)、名称、和创建 snapshot 时所有 storage Server 的 ip 地址。
语法:


SHOW SNAPSHOTS
复制代码

以下为一个小示例:


(user@127.0.0.1) [default_space]> show snapshots;
===========================================================
| Name | Status | Hosts |
===========================================================
| SNAPSHOT_2019_12_04_10_54_36 | VALID | 127.0.0.1:77833 |
-----------------------------------------------------------
| SNAPSHOT_2019_12_04_10_54_42 | VALID | 127.0.0.1:77833 |
-----------------------------------------------------------
| SNAPSHOT_2019_12_04_10_54_44 | VALID | 127.0.0.1:77833 |
-----------------------------------------------------------
Got 3 rows (Time spent: 907/1495 us)
复制代码

6 注意事项



  • 当系统结构发生变化后,最好立刻 create snapshot,例如 add host、drop host、create space、drop space、balance 等。

  • 当前版本暂未提供用户指定 snapshot 路径的功能,snapshot 将默认创建在 data_path/nebula 目录下

  • 当前版本暂未提供 snapshot 的恢复功能,需要用户根据实际的生产环境编写 shell 脚本实现。实现逻辑也比较简单,拷贝各 engineServer 的 snapshot 到指定的文件夹下,并将此文件夹设置为 data_path,启动集群即可。


7 附录


最后,附上 Nebula Graph GitHub 地址:github.com/vesoft-inc/… 如果你在使用 Nebula Graph 过程中遇到任何问题,欢迎 GitHub 联系我们或者加入微信交流群,请联系微信号:NebulaGraphbot


关注公众号

Go 开发者进阶周刊

进阶周刊astaxie 发表了文章 • 3 个评论 • 2104 次浏览 • 5 天前 • 来自相关话题

前沿动态(来自Go官方的最新资讯) ...查看全部

前沿动态(来自Go官方的最新资讯)

  1. 2019 Go Developer 官方调查

语言学习(Golang 编程知识与技巧)

  1. [译] Go语言的协程,系统线程以及CPU管理  
  2. Go Module探索之工程、依赖与Gopls
  3. [译] 《Go in Action》第6章 Concurrency 
  4. 你应该知道的Go漏洞之Top5
  5. Go中的版本控制原则
  6. 万字长文带你深入浅出 Golang Runtime   
  7. Go切片内存应用技巧 
  8. Go 编写友好的命令行应用程序
  9. Go 语言中避免类型推断 
  10. Go 命令行解析 flag 包之通过子命令实现看 go 命令源码 
  11. 浅谈 Go 语言中的读写锁和互斥锁 
  12. Go中的中断处理 
  13. 停止信任你的依赖包
  14. Go的组合与继承

工程实践(Go的项目应用实践)

  1. 使用 Go AST 重构代码 
  2. 利用 Go 开发布隆过滤器 
  3. uber-go 漏桶限流器使用与原理分析
  4. Go后台定时任务执行
  5. 使用 OpenFaaS 和 Go 开启 Serverless 之旅 
  6. Go 号称几行代码开启一个 HTTP Server,底层都做了什么?
  7. 70行Go代码打败C
  8. [译]Go: 理解Sync.Pool的设计思想 
  9. Go 项目终极设置

生态拓展(云原生等 Go 生态体系)

  1. k8s v1.17 新特性预告: 拓扑感知服务路由
  2. 蚂蚁金服 Service Mesh 大规模落地系列 - RPC 篇
  3. 给 K8s API “做减法”:阿里巴巴云原生应用管理的挑战和实践 
  4. kubeedge 源码分析系列之 edgecore

开源项目(社区新涌现的开源成果)

  1. nebula: 一个可扩展的overlay网络工具
  2. arachne:Go实现的丢包检测系统 
  3. orbiter:元数据集群管理器  
  4. errwrap:error 检查优化工具  
  5. reflow:字符串自动换行库
  6. Golang 实现的分布式限流滑动窗口算法

彩蛋(活动与招聘)

11.30 Gopher Meetup 北京站 PPT 下载

  • 探探长链接项目的Go语言实践
  • 蚂蚁金服深度剖析Mosn
  • 美团构建部署平台解析与 Go 的实践 
  • Go语言电子表格文档格式标准实践
  • 探探微服务架构演进之路 

12.24 Gopher Meetup 上海站站活动 报名

[上海徐汇] 积梦智能招聘Go工程师 详情

 

【Golang+mysql】记一次mysql数据库迁移(一)

文章分享stayfoo 发表了文章 • 0 个评论 • 251 次浏览 • 5 天前 • 来自相关话题

# 记一次mysql数据库迁移(一)

原文: https://github.com/stayfoo/stayfoo-hub/blob/master/docs/mysql/blog/%E8%AE%B0%E4%B8%80%E6%AC%A1mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%81%E7%A7%BB%EF%BC%88%E4%B8%80%EF%BC%89.md


## 一、准备

- 目标:

腾讯云 `CVM` 自建 `mysql` 数据迁移到腾讯云数据库 `mysql` 。

- 腾讯云 `CVM` 自建 `mysql` 现状:
- 1、mysql 版本:`Ver 8.0.15 for Linux on x86_64 (MySQL Community Server - GPL)`
- 2、mysql 文件目录数据大小: 2.4 G (`/var/lib/mysql`)
> - 查看 `msyql` 数据目录位置:`mysql> show variables like '%datadir%';`
> - 查看 `/var/lib/mysql` 目录的大小: `du -sh`

```
mysql> show variables like '%datadir%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| datadir | /var/lib/mysql/ |
+---------------+-----------------+
1 row in set (0.04 sec)
```

- 3、只有一个 `root` 账户,只允许 `localhost` 访问
- 4、数据库字符集:`charset=utf8`

- 起因:

`api` 服务、报表计划任务、以及其他计划任务、自建 `mysql` 都在同一台腾讯 `CVM` 上面。计划任务执行的时候,`mysql` 占用 `CPU` 过高,会导致 `api` 服务无法正常使用。所以考虑腾讯云数据库 `mysql`,使用主从架构(先尝试使用一主一从),`master mysql` 主要服务于 `api` 服务,`slave mysql` 主要用于计划任务。

- 腾讯云数据库 `mysql` :
- 1、腾讯云数据库 `mysql` 与腾讯云服务器 `CVM`,同一账号下,同一个地域支持使用内网 `ip` 访问。(比如 `CVM` 是重庆,云数据库必须也是重庆,并且是在同一账号下)

- 2、购买腾讯云 `mysql 5.7`(支持的最大版本,没有`8.0`):先购买一台高可用版 `mysql`,作为 `master mysql`,之后可以扩展多台 `slave mysql`

- 3、迁移工具:腾讯云`DTS`,`mysqldump`(备用)


## 二、迁移

- 1、使用 DTS 迁移

购买完云 `mysql`,初始化,开始使用 `DTS` 进行迁移。 自建 `mysql` 和 云 `mysql` 是属于同一个账号下,同一区域下,可以使用内网直接访问。

![image](https://note.youdao.com/yws/api/personal/file/WEBdd29c8faff09c4b8a0edf6ace1913e40?method=download&shareKey=36844f0af6f14b7822a5909e962c7f8c)


- 2、查看 `CVM` 自建 `mysql` 用户

```
mysql> select host,user,plugin from user;
```

发现只有一个 `root` 账号,只能 `localhost` 访问,需要创建新账号,指定购买的云 `mysql` 的内网 `ip` 授权访问的新账号。在 `CVM` 自建 `mysql` 创建账号:

```
mysql> GRANT ALL PRIVILEGES ON *.* TO "stay"@"1xx.xx.0.0" IDENTIFIED BY "111";
```

创建账号,并授权,发现报错。提示不能用 `grant` 创建用户。 原来 `mysql8.0` 以前的版本可以使用 `grant` 在授权的时候隐式的创建用户。`mysql8.0` 以后已经不支持。`mysql8.0` 必须先创建用户,然后再授权,命令如下:

```
mysql> CREATE USER 'stay'@'172.30.0.0' IDENTIFIED BY '密码';
Query OK, 0 rows affected (0.48 sec)

mysql> grant all privileges on *.* TO 'stay'@'172.30.0.0';
Query OK, 0 rows affected (0.48 sec)
```

> 注意:密码不能和 root 账户相同。

> 参考 mysql8.0 文档:https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html


- 3、在腾讯云 `mysql` 操作 `DTS`

输入源库设置,接入类型选择云主机自建,选择自建 `mysql` 所在的主机实例`ID`,所属区域,自建 `mysql` 的端口号,输入新建的账号,密码。

配置完成之后,测试连通性,`Telnet` 通过,`MySQL Connect` 失败。提示:`MySQL Connect无法连接源实例。请检查实例账号、密码,并确认源实例是否取消对[172.30.0.0/20]的访问限制` 如图:

![image](https://note.youdao.com/yws/api/personal/file/WEB35ab8e244772d87b39aa852e9649e39b?method=download&shareKey=68a0f3bca7898ca4ee6e17a837b45241)


创建账号的时候,对`[172.30.0.0/20]`的访问是授权的。

尝试设置 `CVM` 服务器安全组,把 `172.30.0.0`(即云`mysql`内网 `ip`)设置为信任访问 `3306` 端口。测试连接依然不行。

尝试新创建了一个对所有`ip`都能访问授权的账号,并测试在本地电脑远程连接自建 `mysql` 是没有问题的。然后把这个账号密码配置到 `DTS` 源库上,测试连通性,依然不行。

给腾讯云 mysql 提了工单,让腾讯云工程师协助解决。工单:

![image](https://note.youdao.com/yws/api/personal/file/WEBe3bc59fddbf77defc52f1e2ea4101c96?method=download&shareKey=73600f556d6c42f24a061ac38d761f5c)


> 源库连接失败原因:
> - 数据库账号或密码不正确
> - 源数据库对来源IP进行了限制
> - 源数据库服务器设置了防火墙
> - 网络互通问题
> 可以参考:https://help.aliyun.com/document_detail/52099.html?spm=a2c4g.11186623.2.27.2d2e37admhRAPG


知道是因为版本问题导致的,自建 `mysql` 是 `8.0.15`,而腾讯云 `mysql` 最高支持 `5.7`,`DTS` 不支持从 `8.0.15` 迁移到 `5.7`,所以连通性测试会一直失败。


- 4、使用 `mysqldump` 手动迁移数据

> mysqldump 工作原理:查出需要备份的表结构 -> 生成一个 create sql语句(sql后缀名的文本文件);表中所有记录 -> 转成一条 insert 语句。

先从源数据库导出数据库表结构信息:
```
# 导出数据库表结构(导出的是创建表结构的sql语句)
mysqldump --opt -d[库名] -u[数据库用户名] -p[密码] > /导出的文件名字存储路径.sql
```

从源数据库导出数据信息:
```
mysqldump -t[数据库名] -u[数据库用户名] -p[数据库密码] > xxx.sql
```

`CVM` 主机上使用内网 `ip` 链接云 `mysql`,先创建同名数据库:

```
mysql> create DATABASE sf_factory charset=utf8;
```

然后,依次导入数据库表结构信息,数据库数据:

```
mysql> source [导出的数据库表结构.sql];
mysql> source [导出的数据库数据.sql];
```

> 参考 msyql 8.0官方文档:https://dev.mysql.com/doc/refman/8.0/en/mysqldump-copying-to-other-server.html


- 5、验证数据完整性

- 6、删除自建 `mysql` 多余账号信息

```
mysql> drop user stay@"172.30.0.0/20";
```

方式一:`drop` 不仅会将 `user` 表中的数据删除,还会删除对应权限表内容。

```
#drop user xxxx; 默认删除的是 'xxxx'@'%'
drop user xxxx;

drop user 'xxxx'@'localhost';
drop user 'xxxx'@'172.xx.x.x';
```

方式二:`delete` 只会删除 `user` 中的内容。所以使用 `delete` 删除用户后需要执行 `FLUSH PRIVILEGES;`刷新权限,否则下次使用 `create` 创建用户会报错。





httplib.Post请求触发

开源程序spf 回复了问题 • 2 人关注 • 2 个回复 • 95 次浏览 • 5 天前 • 来自相关话题

GoCN每日新闻(2019-12-05)

回复

每日新闻data_worm 发起了问题 • 1 人关注 • 0 个回复 • 5476 次浏览 • 5 天前 • 来自相关话题