一 、前言
感谢kingshard明星开源项目,本服务正是基于kingshard 开发而来。
本服务适用于相对封闭且经常断电的环境 针对此场景建议使用 MyISAM引擎。
在生产环境中我们数据库可能会遭遇各种各样的不测从而导致数据丢失,大概分为以下几种:
- 硬件故障
- 软件故障(目前生产环境经常发生的)
- 自然灾害
- 黑客攻击
- 误操作
所以为了在数据丢失之后能够恢复数据,我们就需要定期的数据备份,数据备份的策略我们要根据不同的应用场景进行定制,大致有几个参考数据值,我们可以根据这些数值从而定制符合特定环境的策略
- 能够容忍丢失多少数据
- 恢复数据需要多长时间
- 需要恢复拿一些数据
二 、 设计与实现
1.代理
- 收到客户端连接请求后,启动一个goroutine单独处理该请求。
- 首选进行登录验证,验证过程完全兼容MySQL认证协议,由于用户名和密码在配置文件中已经设置好,所以可以利用该信息验证连接请求是否合法。 当用户名和密码都正确时,转入下面的步骤,否则返回出错信息给客户端
- 认证通过后,客户端发送SQL语句
- 对客户端发送过来的SQL语句,进行词法和语义分析,识别出SQL的类型和生成SQL的路由计划。如果有必要还会改写SQL,然后转发到相应的DB。也有可能不做词法和语义分析直接转发到相应的后端DB。如果转发SQL是分表且跨多个DB,则每个DB对应启动一个goroutine发送SQL和接收该DB返回的结果
- 接收并合并结果,然后转发给客户端
2.备份
- 主动链接数据库后 SHOW TABLES 获取所有表
- 启动初始化话备份文件目录 resources /*
- 如果表未持久化过进行初始化备份 , 普通表初始化备份 表结构 索引 核心表备份 表结构 索引 元数据 (核心表并实时记录转发的写操作指令)。
- 根据config.yaml中配置的核心表 ,进行区分核心表以及普通表并启动定时备份与定时检测任务
3.检测
- 定时检测库有无新表增加 一分钟检测一次
- 初始化定时检测核心表创建 30秒检测一次,检测到创建成功后则退出该表初始化检测任务
- 定时检测表损坏情况 定时检测 20 秒 检测一次 检测到表损坏下达表修复任务
4.修复
三 、部署
1.配置
# 地址和端口
addr : ''
# 用户名和密码的用户列表
user_list:
-
user : ''
password : ''
# 日志文件路径,如果不配置则会输出到终端。
log_path : ./log
# log级别,[debug|info|warn|error],默认是error
log_level : info
# 打开SQL日志,设置为on;关闭SQL日志,设置为off
log_sql: on
# 如果设置了该项,则只输出SQL执行时间超过slow_log_time(单位毫秒)的SQL日志,不设置则输出全部SQL日志
#slow_log_time : 100
# sql黑名单文件路径
# 所有在该文件中的sql都会被kingshard拒绝转发
blacklist_sql_file: ./blacklist
# 只允许下面的IP列表连接kingshard,如果不配置则对连接kingshard的IP不做限制
allow_ips : ''
# kingshard使用的字符集,如果不设置该选项,则kingshard使用gbk作为默认字符集
proxy_charset: utf8mb4
# 一个node节点表示mysql集群的一个数据分片,包括一主多从(可以不配置从库
nodes :
-
# node节点名字
name : ''
# 连接池中最大空闲连接数,也就是最多与后端DB建立max_conns_limit个连接
max_conns_limit : 32
# 连接该node中mysql的用户名和密码,master和slave的用户名和密码必须一致
user : ''
password : ''
# master的地址和端口
master : ''
# slave表示一个真正的mysql salve服务器,“@”后面的数字是 读取此从机的负载重量。
down_after_noalive : 32
# 各用户的分表规则
schema_list :
-
#schema的所属用户名
user: ''
#分表分布的node名字
nodes: ['']
#所有未分表的SQL,都会发往默认node
default: ''
shard:
-
#分表使用的db
#db : ''
#分表名字
#table: ''
#分表字段
#key: ''
#分表分布的node
#nodes: ['']
#分表类型
#type: hash
#portal有4个子表
#locations: [1]
#表示每个子表包含的最大记录数,也就是说每个子表最多包好10000条记录。即子表1对应的id为[0,10000),子表2[10000,20000)....
#table_row_limit: 10000
#时间范围
#date_range: [201603-201605,201609-201612]
# 数据库持久化文件目录
db_file_path:
- ''
# 备份周期 单位分钟
bcakup_cycle: 10080
# 核心表(1.会持久化指令 , 表结构 ,元数据 2.表恢复时会连同数据一起恢复)
core_tables:
- "test_table"
2.持久化文件
- .stuct 存储表结构 .data 存储表源数据 .command 实时存储指令
- 目录结构 resources/host:port/user/db_name/table_name
3.运行
- git clone https://github.com/qingolang/go-db-proxy
- cd go-db-proxy
- go mod tidy
- go build -o godbproy cmd/main.go
- 完善 conf/config.yaml
- ./run.sh start