# lg-mongodb-sharding **Repository Path**: sunli1103_admin/lg-mongodb-sharding ## Basic Information - **Project Name**: lg-mongodb-sharding - **Description**: 【java训练营作业14-MongoDB集群分片】 第四阶段 大型分布式存储系统架构进阶 模块三 分布式文档存储独角兽MongoDB、知识图谱存储数据库Neo4j 本模块对MongoDB的存储原理以及replica sets & Sharded Cluster等、对Neo4j数据模型及图形理论等进行深入讲解。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-06-19 - **Last Updated**: 2022-05-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 作业说明 ### 课程内容 > **第四阶段 大型分布式存储系统架构进阶** > **模块三 分布式文档存储独角兽MongoDB、知识图谱存储数据库Neo4j** > 本模块对MongoDB的存储原理以及replica sets & Sharded Cluster等、对Neo4j数据模型及图形理论等进行深入讲解。 ### 作业内容 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0620/000528_66892e16_1712191.png "屏幕截图.png") > (1) 如图搭建一个分片集群 要求每个分片节点中的复制集含有一个仲裁节点 > > (2) 使用权限控制 建立访问你访问的数据库lg_resume 这个账号名字是lagou_gx 密码是abc321。这个账号对数据库有读写权限 > > (3) 使用SpringBoot 进行访问分片集群 对lg_resume 库中的lg_resume_datas 进行增加数据 #### 目录结构 ``` README.md 作业说明 resource config MongoDB集群配置文件(路由、配置服务、分片节点) keyfile 权限认证文件 sh 批处理命令(批量关闭进程,批量清空数据库文件) ``` #### 软件版本 ``` VirtualBox 6.1.8 CentOS 7.7 MongoDB 4.2.8 JDK 11 SpringBoot 2.3.1 SpringBoot Web SpringBoot Data JPA SpringBoot Data MongoDB SpringBoot Test ``` #### 实现步骤 **1. 安装MongoDB** [https://www.mongodb.com/try/download/community](https://www.mongodb.com/try/download/community) 官网下载 CentOS7可用版本 4.2.8,注意为taz格式。 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0620/002346_2f20e273_1712191.png "屏幕截图.png") 上传到虚拟机的linux中 `/usr/local/mongodb` 目录,然后解压。 ```shell $ cd /usr/local/mongodb $ tar -xvf mongodb-linux-s390x-rhel72-4.2.8.tgz $ mv mongodb-linux-s390x-rhel72-4.2.8.tgz mongodb-4.2.8 ``` **2. 配置MongoDB** 在 `mongodb-4.2.8` 中创建conf、data、logs文件夹 ```shell $ cd mongodb-4.2.8 $ mkdir conf data logs ``` 在 `data` 中创建数据库集群实例相关数据文件夹 ```shell $ cd conf $ mkdir config_17011 ... ``` ![输入图片说明](https://images.gitee.com/uploads/images/2020/0620/003539_8fefe768_1712191.png "屏幕截图.png") **2.1. 配置节点** 设置17011、17013(略)、17015(略)配置节点的信息 conf/config_17011.conf ```shell # 数据库文件位置 dbpath=data/config_17011 # 日志文件位置 logpath=logs/config_17011.log # 以追加方式写入日志 logappend=true # 是否以守护进程方式运行 fork=true # 绑定ip bind_ip=0.0.0.0 # 绑定端口号 port=17011 # 表示是一个配置服务器 configsvr=true # 配置服务器副本集名称 replSet=configsvr # 开启权限认证 auth=true # 权限认证文件路径 keyFile=keyfile/testKeyFile.file ``` 启动配置节点 ```shell $ ./bin/mongod -f conf/config_17011.conf $ ./bin/mongod -f conf/config_17013.conf $ ./bin/mongod -f conf/config_17015.conf ``` 添加配置节点的集群信息 a. 连接MongoDB服务端 ```shell $ ./bin/mongo --port=17011 ``` b. 添加集群信息 ```mongodb > use admin; > var cfg={"_id":"configsvr", "members":[ {"_id":1, "host":"192.168.3.100:17011"}, {"_id":2, "host":"192.168.3.100:17013"}, {"_id":3, "host":"192.168.3.100:17015"} ] }; > rs.initiate(cfg); > rs.status(); ``` **2.2. 集群分片** 设置37011、37013(略)、37015(略)、37017(略)分片节点的信息 conf/shard1_37011.conf ```shell # 数据库文件位置 dbpath=data/shard1_37011 # 日志文件位置 logpath=logs/shard1_37011.log # 以追加方式写入日志 logappend=true # 是否以守护进程方式运行 fork=true bind_ip=0.0.0.0 port=37011 # 表示是一个分片服务器 shardsvr=true # 配置服务器副本集名称 replSet=shard1 # 开启权限认证 auth=true # 权限认证文件路径 keyFile=keyfile/testKeyFile.file ``` 启动分片节点 ```shell $ ./bin/mongod -f conf/shard1_37011.conf $ ./bin/mongod -f conf/shard1_37013.conf $ ./bin/mongod -f conf/shard1_37015.conf $ ./bin/mongod -f conf/shard1_37017.conf ``` 添加分片的集群信息 a. 连接MongoDB服务端 ```shell $ ./bin/mongo --port=37011 ``` b. 添加集群信息 ```mongodb > use admin; > var cfg={"_id":"shard1", "protocolVersion":1, "members":[ {"_id":1, "host":"192.168.3.100:37011","priority":10}, {"_id":2, "host":"192.168.3.100:37013","priority":1}, {"_id":3, "host":"192.168.3.100:37015","priority":1}, {"_id":4, "host":"192.168.3.100:37017","arbiterOnly":true} ] }; > rs.initiate(cfg); > rs.status(); ``` 设置47011~58011分片节点的信息(略) **2.3. 路由** 设置27017路由节点的信息 conf/route_27017.conf ```shell # 日志文件位置 logpath=logs/route.log # 绑定ip bind_ip=0.0.0.0 # 绑定端口号 port=27017 # 是否以守护进程方式运行 fork=true # 配置集群节点 configdb=configsvr/192.168.3.100:17011,192.168.3.100:17013,192.168.3.100:17015 # 权限认证文件路径 keyFile=keyfile/testKeyFile.file ``` 启动路由节点 ```shell $ ./bin/mongos -f conf/route_27017.conf ``` 添加分片的信息 a. 连接MongoDB服务端 ```shell $ ./bin/mongo --port=27017 ``` b. 添加分片信息 ```mongodb > use admin; > sh.addShard("shard1/192.168.3.100:37011,192.168.3.100:37013,192.168.3.100:37015,192.168.3.100:37017"); > sh.addShard("shard2/192.168.3.100:47011,192.168.3.100:47013,192.168.3.100:47015,192.168.3.100:47017"); > sh.addShard("shard3/192.168.3.100:57011,192.168.3.100:57013,192.168.3.100:57015,192.168.3.100:57017"); > sh.addShard("shard4/192.168.3.100:58011,192.168.3.100:58013,192.168.3.100:58015,192.168.3.100:58017"); > sh.status(); ``` c. 开启分片,并设置分片大小 ```mongodb > sh.enableSharding("lg_resume"); > sh.shardCollection("lg_resume.lg_resume_datas",{"name":"hashed"}); ``` 测试分片 a. 插入测试数据 ```mongodb > use lg_resume; > for (var i = 1; i <= 100; i++) { db.lg_resume_datas.insert({"name":"test" + i, salary:(Math.random()*20000).toFixed(2)}); } ``` b. 确认分片节点状态 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0620/130209_375b81fc_1712191.png "屏幕截图.png") c. 查看分片结果 ```shell $ ./bin/mongo --port=58015 ``` d. 开启从节点可读 ```mongodb > rs.slaveOk(); > use lg_resume; > db.lg_resume_datas.find(); ``` **2.4. 权限** 进入路由节点 ```shell $ ./bin/mongo --port=27017 ``` 创建用户 ```mongodb > use admin; > db.createUser({user:"root",pwd:"root",roles:[{role:"root",db:"admin"}]}); > use lg_resume; > db.createUser({user:"lagou_gx",pwd:"abc321",roles:[{role:"readWrite",db:"lg_resume"}]}); ``` 生成秘钥文件 ```shell $ openssl rand -base64 756 > keyfile/testKeyFile.file $ chmod 600 keyfile/testKeyFile.file ``` 重新设置配置文件(如果此前没有添加权限信息) a. 路由节点添加 ```shell # 权限认证文件路径 keyFile=keyfile/testKeyFile.file ``` b. 其他节点添加 ```shell # 开启权限认证 auth=true # 权限认证文件路径 keyFile=keyfile/testKeyFile.file ``` c. 安装psmisc,进行批量关闭 ```shell $ yum install psmisc $ killall mongod $ killall mongos ``` d. 编写sh,进行批量启动 startup.sh ```shell ./bin/mongod -f conf/config_17011.conf ./bin/mongod -f conf/config_17013.conf ./bin/mongod -f conf/config_17015.conf ./bin/mongod -f conf/shard1_37011.conf ./bin/mongod -f conf/shard1_37013.conf ./bin/mongod -f conf/shard1_37015.conf ./bin/mongod -f conf/shard1_37017.conf ./bin/mongod -f conf/shard2_47011.conf ./bin/mongod -f conf/shard2_47013.conf ./bin/mongod -f conf/shard2_47015.conf ./bin/mongod -f conf/shard2_47017.conf ./bin/mongod -f conf/shard3_57011.conf ./bin/mongod -f conf/shard3_57013.conf ./bin/mongod -f conf/shard3_57015.conf ./bin/mongod -f conf/shard3_57017.conf ./bin/mongod -f conf/shard4_58011.conf ./bin/mongod -f conf/shard4_58013.conf ./bin/mongod -f conf/shard4_58015.conf ./bin/mongod -f conf/shard4_58017.conf ./bin/mongos -f conf/route_27017.conf ``` e. 设置执行权限 ```shell $ chmod +x startup.sh ``` f. 批量启动 ```shell $ ./startup.sh ``` **3. 访问MongoDB** 搭建 `Spring Boot` 项目,使用 `Spring Data` 的 `MongoRepository` 方式访问。 Resume.java ```java package com.lagou.mongodbcluster.bean; import lombok.Data; import org.springframework.data.mongodb.core.mapping.Document; import java.util.Date; @Data @Document("lg_resume_datas") public class Resume { private String id; private String name; private String city; private Date birthday; private double expectSalary; } ``` ResumeRepository.java ```java package com.lagou.mongodbcluster.repository; import com.lagou.mongodbcluster.bean.Resume; import org.springframework.data.mongodb.repository.MongoRepository; public interface ResumeRepository extends MongoRepository { } ``` MongodbClusterApplicationTests.java ```java package com.lagou.mongodbcluster; import com.lagou.mongodbcluster.bean.Resume; import com.lagou.mongodbcluster.repository.ResumeRepository; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.Date; import java.util.List; import java.util.Random; @SpringBootTest class MongodbClusterApplicationTests { @Autowired private ResumeRepository resumeRepository; @Test public void testAdd() { Random random = new Random(); Double expectSalary = random.nextDouble(); Resume resume; for (int i = 1; i <= 100; i++) { resume = new Resume(); resume.setName("name" + i); resume.setCity("city" + i); resume.setBirthday(new Date()); resume.setExpectSalary(expectSalary); resumeRepository.save(resume); } } @Test public void testQuery() { List resumeList = resumeRepository.findAll(); resumeList.forEach(resume -> System.out.println(resume)); } } ``` application.yml ```yml spring: data: mongodb: host: 192.168.3.100 port: 27017 database: lg_resume username: lagou_gx password: abc321 ``` 测试 先执行 `testAdd()` 方法,插入数据,再执行 `testQuery()` 方法查询数据。 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0620/130448_c1b1e245_1712191.png "屏幕截图.png") #### 注意事项 1. 虚拟机空间不足 因为MongoDB集群实例比较多,创建虚拟机时注意需要至少10G磁盘空间,否则需要后期扩容。 先在虚拟机中添加一块8G物理的磁盘,重起虚拟机,然后执行以下shell命令。 ```shell # 查看磁盘编号 $ ls /dev/sd* # 创建pv $ pvcreate /dev/sdb # 使用vgextend命令扩展vg(如果提示 `Couldn't create temporary archive name`,则需要先删除logs文件腾出一些空间) $ vgextend centos /dev/sdb $ lvs # 可用容量小于8G $ lvextend -L +7.9G /dev/mapper/centos-root # 命令使系统重新读取大小 $ xfs_growfs /dev/mapper/centos-root # 查看磁盘信息(成功扩容为16G) $ df -h ``` 2. 关闭服务尽量不使用kill 使用kill命令可能会导致MongoDB实例损坏,需要手动删除 `data/mongod.lock` 然后以修复方式启动 ```shell $ /usr/bin/mongod -f /etc/mongod.conf --repair ``` 正常关闭服务的方式(好像killall命令也可以) ```mongodb > db.shutdownServer(); ``` 3. 批量清除数据 如果MongoDB实例或数据损坏,需要批量删除,可以使用以下sh。但是重新启动后需要再次进行相关设置。 ```shell rm -rf data/config_17011/* rm -rf data/config_17013/* rm -rf data/config_17015/* rm -rf data/shard1_37011/* rm -rf data/shard1_37013/* rm -rf data/shard1_37015/* rm -rf data/shard1_37017/* rm -rf data/shard2_47011/* rm -rf data/shard2_47013/* rm -rf data/shard2_47015/* rm -rf data/shard2_47017/* rm -rf data/shard3_57011/* rm -rf data/shard3_57013/* rm -rf data/shard3_57015/* rm -rf data/shard3_57017/* rm -rf data/shard4_58011/* rm -rf data/shard4_58013/* rm -rf data/shard4_58015/* rm -rf data/shard4_58017/* rm -rf data/route_27017/* ``` 4. 权限问题 a. 权限相关的配置最好第一次就填写好,避免很多配置文件写完再重新修改。 b. 目前发现设置完权限后,分片节点权限认证不成功,无法使用shell进行数据查询,只能通过路由节点授权查询。正在解决中。 5. 重新初始化节点 rs.reconfig(config,{"force":true}); #### 相关资料 [原创【拉勾课程速推指南】阶段四 模块三 分布式文档存储独角兽MongoDB、知识图谱存储数据库Neo4j](https://www.jianshu.com/p/9079248b4ec5)