简介
  • Go语言实现云端分布式文件存储系统,包含微服务和容器化
  • 可以用虚拟机搭建Linux服务器环境
  • 过程中还会用到postman等工具
文件上传服务
// 代码先不放了,架构还需演进

架构演进

-- 后续补充
show master status
-- 创建文件表
CREATE TABLE `tbl_file` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `file_sha1` char(40) NOT NULL DEFAULT '' COMMENT '文件hash',
  `file_name` varchar(256) NOT NULL DEFAULT '' COMMENT '文件名',
  `file_size` bigint(20) DEFAULT '0' COMMENT '文件大小',
  `file_addr` varchar(1024) NOT NULL DEFAULT '' COMMENT '文件存储位置',
  `create_at` datetime default NOW() COMMENT '创建日期',
  `update_at` datetime default NOW() on update current_timestamp() COMMENT '更新日期',
  `status` int(11) NOT NULL DEFAULT '0' COMMENT '状态(可用/禁用/已删除等状态)',
  `ext1` int(11) DEFAULT '0' COMMENT '备用字段1',
  `ext2` text COMMENT '备用字段2',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_file_hash` (`file_sha1`),
  KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- 创建用户表
CREATE TABLE `tbl_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(64) NOT NULL DEFAULT '' COMMENT '用户名',
  `user_pwd` varchar(256) NOT NULL DEFAULT '' COMMENT '用户encoded密码',
  `email` varchar(64) DEFAULT '' COMMENT '邮箱',
  `phone` varchar(128) DEFAULT '' COMMENT '手机号',
  `email_validated` tinyint(1) DEFAULT 0 COMMENT '邮箱是否已验证',
  `phone_validated` tinyint(1) DEFAULT 0 COMMENT '手机号是否已验证',
  `signup_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '注册日期',
  `last_active` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后活跃时间戳',
  `profile` text COMMENT '用户属性',
  `status` int(11) NOT NULL DEFAULT '0' COMMENT '账户状态(启用/禁用/锁定/标记删除等)',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_username` (`user_name`),
  KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 创建用户token表
CREATE TABLE `tbl_user_token` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(64) NOT NULL DEFAULT '' COMMENT '用户名',
  `user_token` char(40) NOT NULL DEFAULT '' COMMENT '用户登录token',
    PRIMARY KEY (`id`),
  UNIQUE KEY `idx_username` (`user_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 创建用户文件表
CREATE TABLE `tbl_user_file` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `user_name` varchar(64) NOT NULL,
  `file_sha1` varchar(64) NOT NULL DEFAULT '' COMMENT '文件hash',
  `file_size` bigint(20) DEFAULT '0' COMMENT '文件大小',
  `file_name` varchar(256) NOT NULL DEFAULT '' COMMENT '文件名',
  `upload_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间',
  `last_update` datetime DEFAULT CURRENT_TIMESTAMP 
          ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
  `status` int(11) NOT NULL DEFAULT '0' COMMENT '文件状态(0正常1已删除2禁用)',
  UNIQUE KEY `idx_user_file` (`user_name`, `file_sha1`),	-- 唯一性约束
  KEY `idx_status` (`status`),
  KEY `idx_user_id` (`user_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
MySQL主从配置
  • 小插曲:借助docker配置MySQL主从模式
  • 以下docker相关的命令,需要在root用户环境下或通过sudo提升权限来进行操作

1.拉取MySQL5.7镜像到本地

docker pull mysql:5.7

# 如果你只需要跑一个mysql实例,不做主从,那么执行以下命令即可,不用再做后面的参考步骤:
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
#然后用shell或客户端软件通过配置( 用户名:root 密码:132456 IP:你的本机ip 端口:3306)来登录即可

2. 准备MySQL配置文件

/etc/mysql/my.cnf/etc/mysql/conf.d/data/mysql/conf/
  • /data/mysql/conf/master.conf
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
log_bin = log  #开启二进制日志,用于从节点的历史复制回放
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server = utf8
server_id = 1  #需保证主库和从库的server_id不同, 假设主库设为1
replicate-do-db=fileserver  #需要复制的数据库名,需复制多个数据库的话则重复设置这个选项
  • /data/mysql/conf/slave.conf
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
log_bin = log  #开启二进制日志,用于从节点的历史复制回放
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server = utf8
server_id = 2  #需保证主库和从库的server_id不同, 假设从库设为2
replicate-do-db=fileserver  #需要复制的数据库名,需复制多个数据库的话则重复设置这个选项

3. Docker分别运行MySQL主/从两个容器

  • 将mysql主节点运行起来
mkdir -p /data/mysql/datam
docker run -d --name mysql-master -p 13306:3306 -v /data/mysql/conf/master.conf:/etc/mysql/mysql.conf.d/mysqld.cnf -v /data/mysql/datam:/var/lib/mysql  -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

运行参数说明:

–name mysql-master: 容器的名称设为mysql-master
-p 13306:3306: 将host的13306端口映射到容器的3306端口
-v /data/mysql/conf/master.conf:/etc/mysql/mysql.conf.d/mysqld.cnf : master.conf配置文件挂载
-v /data/mysql/datam:/var/lib/mysql : mysql容器内数据挂载到host的/data/mysql/datam, 用于持久化
-e MYSQL_ROOT_PASSWORD=123456 : mysql的root登录密码为123456

  • 将mysql从节点运行起来
mkdir -p /data/mysql/datas
docker run -d --name mysql-slave -p 13307:3306 -v /data/mysql/conf/slave.conf:/etc/mysql/mysql.conf.d/mysqld.cnf -v /data/mysql/datas:/var/lib/mysql  -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

运行参数说明:

–name mysql-slave: 容器的名称设为mysql-slave
-p 13307:3306: 将host的13307端口映射到容器的3306端口
-v /data/mysql/conf/slave.conf:/etc/mysql/mysql.conf.d/mysqld.cnf : slave.conf配置文件挂载
-v /data/mysql/datas:/var/lib/mysql : mysql容器内数据挂载到host的/data/mysql/datas, 用于持久化
-e MYSQL_ROOT_PASSWORD=123456 : mysql的root登录密码为123456

4.登录MySQL主节点配置同步信息

  • 登录mysql
# 192.168.1.xx 是你本机的内网ip
mysql -u root -h 192.168.1.xx -P13306 -p123456
  • 在mysql client中执行
mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY 'slave';
mysql> flush privileges;
mysql> create database fileserver default character set utf8mb4;

再获取status, 得到类似如下的输出:

mysql> show master status G;
*************************** 1. row ***************************
             File: log.000025
         Position: 155
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

5.登录MySQL从节点配置同步信息

  • 另开一个tab登录mysql
# 192.168.1.xx 是你本机的内网ip
mysql -u root -h 192.168.1.xx -P13307 -p123456
  • 在mysql client中操作:
mysql> stop slave;
#注意其中的日志文件和数值要和上面show master status的值对应
mysql> CHANGE MASTER TO MASTER_HOST='你的本地ip地址如192.168.1.x',master_port=13306,MASTER_USER='slave',MASTER_PASSWORD='slave',MASTER_LOG_FILE='log.000025',MASTER_LOG_POS=155;
mysql> start slave;

再获取status, 正常应该得到类似如下的输出:

mysql> show slave status G;
// ...
Slave_IO_Running: Yes 
Slave_SQL_Running: Yes 
// ...
fileserver
小结
  • 下节实现基于用户的资源隔离部分