一、简介 1. 简单介绍
MongoDB是一个基于分布式文件存储 的数据库
由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库 和非关系数据库 之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。
Mongo最大的特点是它支持的查询语言 非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引
2. 业务应用场景 传统的关系型数据库(如MySQL),在数据操作的三高
需求以及应对Web2.0的网站需求面前,显得力不从心,而 MongoDB可应对“三高“需求
High performance:对数据库高并发读写的需求
Huge Storage:对海量数据的高效率存储和访问的需求
High Scalability && High Availability:对数据库的高可扩展性和高可用性的需求
具体应用场景 :
社交场景,使用 MongoDB存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。
游戏场景,使用 MongoDB存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、高效率存储和访问。
物流场景,使用 MongoDB存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来
物联网场景,使用 MongoDB存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。 视频直播,使用 MongoDB存储用户信息、点赞互动信息等。
这些应用场景中,数据操作方面的共同特点 是:
(1)数据量大
(2)写入操作频繁(读写都很频繁)
(3)价值较低的数据,对事务性要求不高
对于这样的数据,我们更适合使用 MongoDB来实现数据的存储。
3. 什么时候选择MongoDB
MongoDB是一个开源、高性能、无模式(没有具体的列)的文档型数据库,当初的设计就是用于简化开发和方便扩展,是NoSQL数据库产品中的一种。是最像关系型数据库(MySQL)的非关系型数据库。
它支持的数据结构非常松散,是一种类似于 JSON 的 格式叫BSON,所以它既可以存储比较复杂的数据类型,又相当的灵活。 MongoDB中的记录是一个文档,它是一个由字段和值对(field:value)组成的数据结构。MongoDB文档类似于JSON对象,即一个文档认为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 # 对文档数据库进行操作的基本方式包括了读、写、改、删四种。 # 1 、写Insert 命令 DB.Books.Insert(“Book_ID”:”100002 ”,”Name”:”《C语言》”,”Price”:”60 ”) # 2 、选Select 命令 DB.Books.find(“Name”:”《C语言》”) # 3 、改Update 命令 DB.Books.Update({“Book_ID”:”100002 ”},{$set {“Price”:78 }}) # 4 、删Remove命令 DB.Books.Remove({“Book_ID”:”100004 ”}) 。
相对MySQL,在以上以用场景可以以更低的成本解决问题(包括学习、开发、运维等成本)
4. 体系机构
在MongoDB中,数据库存储着集合和文档。一个数据库可以创建多个集合,原则上我们通常将逻辑相近的集合都放在一个数据库中,不过出于性能和数据量的考虑,也可分开存储。MongoDB默认提供admin、local、config以及test数据库四个数据库,具体介绍如下:
admin数据库 ,主要存储数据库账号的相关信息。
local数据库 ,可以用于存储限于本地单台服务器的任意集合,如oplog日志就存储在local数据库中,该数据库的数据不会被复制到从节点上。
config数据库 ,用于存储分片集群中与分片相关的元数据信息。
test数据库 ,是MongoDB默认创建的一个测试库,当连接mongod服务时,如果不指定连接的具体数据库,默认就会连接到test数据库。
集合 就是MongoDB的一组文档,分为一般集合和上限集合。一般集合 我们通常称之为集合,集合是无模式或动态模式 的,也就意味着集合没有固定的格式。在读写数据前,不需要创建集合模式就可使用,因此集合中的文档可以拥有不同的字段,也可以任意增减某个文档的字段。
需要注意的是,通常插入集合的数据都具有一定的关联性。
上限集合 (Capped collections)与一般集合的主要区别在于其可以限制集合的容量大小 ,在数据存满时,可以从头开始覆盖最开始的文档,从而进行**循环写入 **。
文档 是以 键值对的形式 存储在集合中,其中,键用于唯一标识一个文档,为字符串类型,而值则可以是各种复杂的文件类型,我们称这种存储形式为BSON (BSON是类JSON的一种二进制形式的存储格式,简称BinaryJSON,它和JSON一样,支持内嵌的文档对象和数组对象 ,但是BSON有JSON没有的一些数据类型,如Date和BinData类型)。
文档中不能有重复的键,每个文档都有一个默认的_id键 ,它相当于关系型数据库中的主键,这个键的值在同一个集合中必须是唯一的,_id键值默认是ObjectId类型,在插入文档的时候,如果用户不设置文档的_id值,MongoDB会自动生成一个唯一的ObjectId值 进行填充。
MongoDB的最小存储单位就是文档(document)对象 。文档(document)对象对应于关系型数据库的行。数据在MongoDB中以BSON(Binary-JSON)文档的格式存储在磁盘上。
BSON (Binary Serialized Document Format)是一种类json的一种二进制形式的存储格式 ,简称Binary JSON。BSON和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型。
BSON采用了类似于 C 语言结构体的名称、对表示方法,支持内嵌的文档对象和数组对象,具有轻量性、可遍历性、高效性的三个特点,可以有效描述非结构化数据和结构化数据。这种格式的优点是灵活性高,但它的缺点是空间利用率不是很理想。
Bson中,除了基本的JSON类型:string,integer,boolean,double,null,array和object ,mongo还使用了特殊的数据类型。这些类型包括date,object id,binary data,regular expression 和code 。每一个驱动都以特定语言的方式实现了这些类型,查看你的驱动的文档来获取详细信息。BSON数据类型参考列表:
文档的键是字符串类型,而值除字符串类型外,还可以为内嵌文档、数组、Date等类型,文档内容具体如下
1 2 3 4 5 6 7 8 9 10 11 12 {_id: ObjectId("5099803df3f4948bd2f98391"), name: { first : "Alan", last : "Turing" }, birth: new Date ('Jun 23, 1912' ), death: new Date ('Jun 07, 1954' ), contribs: [ "Turing machine", "Turing test", "Turingery" ], views : NumberLong(1250000 )} _id:该字段的值为ObjectId类型。 name:该字段的值是由first 、last 字段组成的内嵌文档。 birth和death:这两个字段对应的值均为Date 类型。 contribs:该字段的值为字符串数组类型。 views:该字段的值为NumberLong类型。
数字类型 MongoDB支持三种数字类型(即32位整数(Int32 )、64位整数(Int64 )和64位浮点数(Double ))。 使用mongo shell命令行交互界面和JavaScript命令这两种方式查看和操作MongoDB时,数值被默认转为64位浮点数。可通过Java等语言可存储包含整数(32位和64位整型)的文档。 如果想要通过mongo shell插入/更新文档内的整数(32位/64位)类型数值,则可以通过函数NumberInt(“Number”)和NumberLong(“Number”)进行操作。
1 2 3 4 5 6 7 # 在mongo shell查看文档中的64 位整数时,会通过封装函数NumberLong()显示。 { "_id":Objectld("5e042c88b2275b76df53b302"), "age32":32 , "age64":NumberLong(64 ) }
日期类型 在mongo shell中创建包含日期类型数值的文档 ,类似于在javascript中创建日期的方式,需要使用**new Date(…)**的方式。MongoDB会将存储的日期自动保存成ISODate日期类型。默认情况下MongoDB中存储的是标准的时间(GMT),中国时间是东八区(GMT+8),若是我们将当前时间存储至MongoDB中会发现减少8个小时。不过有些编程语言已对此进行相关处理,比如Java读取时会自动加上时区8小时。
1 2 3 4 5 6 7 # 在mongo shell插入Date 类型文档的操作。 > db.bigdata.insert({"time":new Date ("2019-02-12 12:12:12")}) > db.bigdata.find() { "_id":Objectld("5de915201bc9accea9a23154"), "time":ISODate("2019-02-12T04:12:12Z") }
数组类型 MongoDB数组是一系列元素的集合 ,使用中括号“[ ]”表示数组 。数组元素允许重复且位置固定,数组中可以存在不同数据类型的元素。在关系数据库中,数组的这种设计实现方式是不常见的。
1 2 3 4 5 6 7 8 9 10 11 # 数组类型文档的结构。 { "_id":Objectld("5de91c6f1bc9accea9a2315b"), "hobby":[ "swim", "run", "sing", 4.0 , "sing" ] }
ObjectId类型 ObjectId 是一个12字节BSON类型 ,由一组十六进制的24位字符串构成,每个字节存储2位十六进制字符,总共使用了12字节的存储空间,具有格式如下所示。
Time:ObjectId的前4个字节表示时间戳,即前8位字符“5de91c6f” ,通过十六进制转换成十进制内容为“1575558255”,这个数字就是一个时间戳格式,通过时间戳的转换,可变为常见的时间格式。
Machine:在Time后的3个字节表示所在主机的唯一标识符,即Time之后的6位字符“1bc9ac” ,一般是机器主机名的散列值,这样就确保了不同主机生成不同的机器hash值,这样可以防止在分布式中出现ObjectId相同的冲突情况,这也就是**在同一台机器生成的ObjectId中间字符串都是一模一样的原因 **。
PID:在Machine后的2个字节表示进程标识符,即Machine后的4位字符“cea9” ,可以**确保在同一台机器不同的MongoDB进程不会出现相同的ObjectId **。
INC:在PID后的3个字节是一个随机值 ,即PID之后的4位字符“a2315b”。前面介绍的9个字节是为了保证1秒内不同机器 不同进程 生成的ObjectId不冲突,这3个字节生成的随机值是为了确保1秒内产生的ObjectId不发生冲突 。
内嵌文档 MongoDB一大优势在于能够在一条文档中存储对象类型的数据 ,并适当增加冗余让数据库更便于使用。文档中一个对象类型的字段在MongoDB中被称为内嵌文档 (Embedded),也是MongoDB推荐的存储格式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 内嵌文档类型的文档格式(6 -9 行) { "_id" : ObjectId("5de92bda1bc9accea9a2315e"), "name" : "mongo", "price" : 50.0 , "size" : { "h" : 8.5 , "w" : 11.0 }, "reading" : [ "John", "Dave" ] }
Code类型 在MongoDB数据库的文档中,可以存储一些JavaScript方法,这些方法可以重复使用\
1 2 3 4 5 # Code类型的文档格式如下。 { "_id" : ObjectId("5de92fdd1bc9accea9a23161"), "jscode" : function jsCode(a){ b= a+ 2 ;return b;} }
5. 数据类型 BSON数据类型参考列表:
提示 :shell默认使用64位浮点型数值。 {“x”:3.14或{“x”:3}。对于整型值,可以使用NumberInt(4字节符号整数)或 NumberLong(8字节符号整数),{“x”:NumberInt(“3” ){“x”:NumberLong(“3”)}
6. 特点
高性能 MongoDB提供高性能的数据持久性。特别是,
对嵌入式数据模型的支持减少了数据库系统上I/O活动。
索引支持更快的查询,并且可以包含来自嵌入式文档和数组的键。(文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求、地理位置索引可用于构建各种O2O应用)
mmapv1、 wiredtiger、 mongorocks( rocks)、 In-memory等多引擎支持满足各种场景需求
Gridfs解决文件存储的需求
高可用性 MongoDB的复制工具称为副本集( replica set),它可提供自动故障转移和数据冗余
高扩展性 MongoDB提供了水平可扩展性作为其核心功能的一部分。
分片将数据分布在一组集群的机器上。(海量数据存储,服务能力水平扩展)
从3.4开始,MoηgoDB支持基于片键创建数据区域。在一个平衡的集群中, MongoDB将一个区域所覆盖的读写只定向到该区域内的那些片。
丰富的查询支持 MongoDB支持丰富的査询语言,支持读和写操作(CRUD),比如数据聚合、文本搜索和地理空间查询等
其他特点
如无模式(动态模式)、灵活的文档模型
二、Windows安装&启动&连接 1. 下载压缩包 下载地址:https://www.mongodb.com/try/download/community
这里以zip的格式进行下载
附加:mongodb的命名格式: x.y.z
1 2 3 - y为奇数表示当前版本为开发版,如:1.5.2、4.1.13 - y为偶数表示当前版本为稳定版,如:1.6.3、4.0.10 - z为修正版本号,越大越好
2. 解压 下载完成后得到压缩包,解压;其中的bin目录就存放着mongodb相关的命令
3. 安装服务 首先要在安装目录里创建两个目录:
数据目录:data
日志目录:logs
然后以管理员模式,切换到安装目录下的bin目录运行以下格式命令来指定mongdb的数据及日志目录
1 mongod --install --dbpath 数据目录 --logpath 日志目录\日志名称
注意整个文件的路径中不能包含中文,中文,中文!踩过坑!
具体的代码为如下所示:
1 mongod --install --dbpath D:\JAVA_Environment\MongoDB\mongodb-win32-x86_64-windows-4.4.2\data --logpath D:\JAVA_Environment\MongoDB\mongodb-win32-x86_64-windows-4.4.2\logs\mongodb.log
没有任何报错和提示,则代表MongoDB服务创建成功
我们可以进行验证,win+r输入services.msc
看到MongoDB服务即成功
补充一下:如果想要删除MongoDB服务的话
4. 启动服务 输入以下命令启动服务
输入http://localhost:27017/
如果看到以下内容,代表启动成功
5. shell连接登录&退出 输入以下命令进行登录与退出
1 2 3 4 5 6 #登录 mongo mongo --host=localhost --port=27017 #退出 exit
相关语法 :
1 2 3 4 5 mongod --install --dbpath 数据目录 --logpath 日志目录\日志名称 #创建服务 mongod --remove #卸载服务 net start mongodb #启动服务 net stop mongodb #关闭服务 mongod #是处理MongoDB系统的主要进程。它处理数据请求,管理数据存储,和执行后台管理操作。当我们运行mongod命令意味着正在启动MongoDB进程,并且在后台运行。
6. Compass图形化连接登录 MongoDB的GUI。直观地浏览您的数据。在几秒钟内运行查询。借助完整的CRUD功能与您的数据进行交互。查看和优化您的查询性能。在Linux,Mac或Windows上可用。Compass使您能够做出更明智的索引,文档验证等决策。
下载地址:https://www.mongodb.com/try/download/compass
点击Download
下载即可,下载完成后得到压缩包
解压,可以看到MongoDBCompass.exe
双击运行,直接Next,最后Get Stated,默认选项即可
然后直接点击CONNECT就会连接本地的数据库localhost:27017
可以看到所有的数据库及相关信息
三、Linux安装&启动&连接 1 2 3 4 5 6 7 cd /opt mkdir module cd module mkdir mongodb cd mongodb rm -rf /path/to/directory 强制删除文件
传输、解压、移动安装包
(1). 打开Linux虚拟机并通过传输工具WinSCP 连接Linux平台,并存储在CentOS中的 /opt/ 路径下。
1 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-4.4.24.tgz
(2). 在Xshell中执行tar -zxvf mongodb-linux-x86_64-rhel80-4.4.24.tgz
命令,解压tgz包。
(3). 执行mv mongodb-linux-x86_64-rhel80-4.4.24/* /opt/module/mongodb
,移动解压后的文件夹到/opt/module/mongodb
新建并修改配置文件
(1). 新建几个目录,分别用来存储数据和日志。
1 2 3 4 5 6 7 8 9 [root@localhost mongodb]# mkdir -p shihanshuo/data/db [root@localhost mongodb]# mkdir -p shihanshuo/logs [root@localhost mongodb]# touch shihanshuo/logs/mongologs.log
(2). 新建并修改配置文件 vi shihanshuo/mongod.conf
按键盘 i 键或者insert键,进入编辑(插入)模式,在文件中写入以下内容
配置文件的内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 systemLog: destination: file path: "/opt/module/mongodb/shihanshuo/logs/mongologs.log" logAppend: true storage: dbPath: "/opt/module/mongodb/shihanshuo/data/db" journal: enabled: true processManagement: fork: true net: bindIp: localhost,192.168.24.105 port: 27017
复制后,按键盘 Esc 键,退出编辑模式,然后键盘组合键 Shift + :键,输入wq写保存。
wq:写保存
q:退出
wq!:强制写保存
q!:强制退出
设置环境变量,使用mongo命令启动服务
(1). 由于Mongodb的相关服务均放在解压后/mongodb/bin路径下,若想启动服务,必须在bin目录下启动。因此为了避免启动之前需要进入到该路径,我们配置用户的环境变量即可
(2). 执行vi /etc/profile
命令,编辑用户环境变量文件。找到export字段在其下方添加代码。
1 2 export MONGODB_HOME=/opt/module/mongodbexport PATH=$PATH :$MONGODB_HOME /bin
(3). 添加并wq写保存
(4). 执行source /etc/profile
命令,初始化用户环境变量。
在任意路径下,即可执行mongod -f /opt/module/mongodb/shihanshuo/mongod.conf
启动服务mongo连接到服务器
1 2 3 4 5 6 7 [root@localhost mongodb]# vi /etc/profile [root@localhost mongodb]# source /etc/profile [root@localhost mongodb]# cd [root@localhost ~]# mongod -f /opt/module/mongodb/shihanshuo/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8075 child process started successfully, parent exiting
启动和关闭MongoDB服务
(1). 执行ps -ef|grep mongod
查看服务进程。
(2). 确保mongodb服务启动后,使用客户端连接远程数据库服务器在终端执行 mongo --host=192.168.24.105
然后执行show dbs
查看当前数据库。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@localhost ~]# mongo --host=192.168.24.105 MongoDB shell version v4.2.18 connecting to: mongodb://192.168.24.105:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("43fc9a44-2f87-443c-9b57-eb55d50aace3" ) } MongoDB server version: 4.2.18 Welcome to the MongoDB shell. For interactive help , type "help" . For more comprehensive documentation, see https://docs.mongodb.com/ Questions? Try the MongoDB Developer Community Forums https://community.mongodb.com > show dbs admin 0.000GB config 0.000GB local 0.000GB>
(3). 执行exit退出mongo shell,执行kill -2 8075
结束mongodb服务的进程。
1 2 3 4 5 6 7 8 9 10 11 12 13 > show dbs admin 0.000GB config 0.000GB local 0.000GB> exit bye [root@Server01 ~]# ps -ef|grep mongod root 8607 1 0 23:26 ? 00:00:00 mongod -f /opt/module/mongodb/standalone/mongod.conf root 8664 3744 0 23:27 pts/0 00:00:00 grep --color=auto mongod [root@Server01 ~]# kill -2 8607 [root@Server01 ~]# ps -ef|grep mongod root 8674 3744 0 23:27 pts/0 00:00:00 grep --color=auto mongod [root@Server01 ~]#
启动报错的解决:
报错一:ERROR: child process failed, exited with error number 48
解决方案:通过mongod –repair检查具体错误。
原来是端口冲突。删除前面没执行成功的文件,然后修改XXX.conf配置文件。将其中端口号改为27016后。重新执行后成功。
如果启动后没有关闭,再起启动也会报错48.则可以先使用关闭命令关闭,然后再次启动。
报错二:-bash: /usr/local/mongodb6/bin/mongod: Permission denied
启动的时候报错了,是因为没权限访问该文件
解决方案:给mongodb文件夹分配最高权限
sudo chmod -R 777 /usr/local/mongodb
-R 是指级联应用到目录里的所有子目录和文件 777 是所有用户拥有的最高权限
centOS启动mongoDB错误:./mongod: error while loading shared libraries: libcrypto.so.10: cannot open share
[root]# rpm -qa | grep libcrypto.so [root]# rpm -qa | grep libcrypt [root]# dnf install compat-openssl10
我们发现启动失败,出现这种情况我们编辑用户级配置文件 vim ~/.bashrc
添加配置信息: export PATH=/usr/local/mongodb/bin:$PATH (中间那部分就是你的安装目录下的bin)
wq保存退出
然后刷新:source ~/.bashrc
再次启动
6. Compass图形化连接登录 利用Compass进行连接,Hostname为服务器的公网IP,其他默认
连接失败的原因:
未打开安全组策略
暴露给外部的端口需要打开对应的安全组设置
防火墙开放端口未设置
首先查看防火墙是否开启,结果为not running表示未开启,则不是防火墙的问题,跳过
查看防火墙是否开启 firewall-cmd –state
如果显示running,则继续排查,查看防火墙开放的端口
查看防火墙所开放的端口 1 2 3 4 firewall-cmd --list-ports [root@zsr ~]# firewall-cmd --list-ports 20/tcp 21/tcp 22/tcp 80/tcp 8888/tcp 39000-40000/tcp 3306/tcp 3306/udp 8080/tcp 8080/udp 3355/tcp
也可以用firewall-cmd –list-all查看防火墙的详细信息
我这里的问题就是防火墙未开放27017端口,所以要开放防火墙的对外暴露的端口
开放90端口(–premanent表示永久添加) 1 firewall-cmd --permanent --add-port=27017/tcp
重启防火墙(修改配置后要重启防火墙)
添加完成后再次查看就可以看到27017端口被开放
四、基本常用命令 1. 数据库相关 1 2 3 4 5 6 7 8 9 10 11 # 查看所有数据库 show databases # 选择数据库(如果数据库不存在,不会报错;会隐式创建:当后期该数据库有数据时自动创建) use 数据库名 # 查看当前正在使用的数据库命令: db # 删除数据库(先选中数据库) db.dropDatabase()
2. 集合相关 1 2 3 4 5 6 7 8 # 查看所有集合 show collections # 创建集合(插入数据会隐式创建) db.createCollection('集合名') # 删除集合 db.集合名.drop()
五、CURD 增:插入文档
集合存在则直接插入数据,不存在则隐式创建集合并插入数据
json数据格式要求key得加""
,但这里为了方便查看,对象的key统一不加""
;查看集合数据时系统会自动给key加""
mongodb会自动给每条数据创建全球唯一的_id
键(我们也可以自定义_id
的值,只要给插入的json数据增加_id
键即可覆盖,但是不推荐这样做)
测试 :
插入一条数据
1 db.student.insert({name:"shs",age:20})
一次插入多条数据并指定_id
1 db.stuent.insert([{_id:1,namme:"z",age:20},{_id:2,namme:"x",age:21},{_id:3,namme:"c",age:23}])
批量插入多条文章评论:
1 2 3 4 5 db.comment.insertMany([ {"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date ("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000 ),"state":"1"}, {"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔悴","createdatetime":new Date ("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888 ),"state":"1"}, {"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船长","createdatetime":new Date ("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666 ),"state":"1"}, ]);
提示: 插入时指定了 _id ,则主键就是该值。
如果某条数据插入失败,将会终止插入,但已经插入成功的数据不会回滚掉。
因为批量插入由于数据较多容易出现失败,因此,可以使用try catch进行异常捕捉处理 ,测试的时候可以不处理。如(掌握):
1 2 3 4 5 6 7 8 9 try { db.comment.insertMany([ {"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date ("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000 ),"state":"1"}, {"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔悴","createdatetime":new Date ("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888 ),"state":"1"}, {"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船长","createdatetime":new Date ("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666 ),"state":"1"}, ]); } catch (e) { print (e); }
利用for循环插入数据
1 2 3 for(var i=1;i<10;i++){ db.student.insert({name:"a"+i,age:i}) }
删:删除文档 1 2 3 4 5 6 7 8 db.集合名.remove(条件 [,是否删除一条]) db.student.remove({},true) db.student.remove({},false) # 是否删除一条 - false删除多条,即全部删除(默认) - true删除一条
改:修改文档 1 2 3 4 5 6 7 8 9 10 11 db.集合名.update(条件, 新数据 [,是否新增, 是否修改多条]) # 新数据 - 默认是对原数据进行替换 - 若要进行修改,格式为 {修改器:{key:value}} # 是否新增 - 条件匹配不到数据时是否插入: true插入,false不插入(默认) # 是否修改多条 - 条件匹配成功的数据是否都修改: true都修改,false只修改一条(默认)
修改器
作用
$inc
递增
$rename
重命名列
$set
修改列值
$unset
删除列
准备工作 :插入十条数据
1 2 3 for(var i=1;i<=10;i++){ db.people.insert({name:"zsr"+i,age:i}) }
将{name:“zsr1”}更改为{name:“zsr2”}
1 db.people.update({name:"zsr1"},{name:"zsr2"})
发现问题 :默认不是修改而是替换
解决问题 :使用修改器将{name:“zsr3”}更改为{name:“zsr3333”}
1 db.people.update({name:"zsr3"},{$set:{name:"zsr3333"}})
给{name:“zsr10”}的年龄增加或减少2岁
1 2 3 4 5 # 增加两岁 db.people.update({name:"zsr10"},{$inc:{age:2}}) # 减少两岁 db.people.update({name:"zsr10"},{$inc:{age:-2}})
一次写多个修改器
首先插入一条数据
1 db.people.insert({username:"gcc",age:20,sex:"女",address:"unknown"})
任务:修改gcc的username为bareth,age+11,sex字段重命名为sexuality,删除address字段
1 2 3 4 5 6 db.people.update({username:"gcc"},{ $ set :{username:"bareth" }, $ inc:{age:11}, $ rename:{sex:"sexuality" }, $ unset :{address:true }})
查:查询文档 1 2 3 4 5 6 7 8 9 10 11 12 db.集合名.find(条件 [,查询的列]) db.集合名.find(条件 [,查询的列]).pretty() #格式化查看 # 条件 - 查询所有数据 {}或不写 - 查询指定要求数据 {key:value}或{key:{运算符:value}} # 查询的列(可选参数) - 不写则查询全部列 - {key:1} 只显示key列 - {key:0} 除了key列都显示 - 注意:_id列都会存在
运算符
作用
$gt
大于
$gte
大于等于
$lt
小于
$lte
小于等于
$ne
不等于
$in
in
$nin
not in
查询指定列的所有数据
1 2 3 db.student.find({},{name:1}) 只查询name列 db.student.find({},{name:0}) 查询除了name列以外的列
查询指定条件的数据
统计查询 使用count()方法
【示例】 (1)统计所有记录数: 统计comment集合的所有的记录数:
(2)按条件统计记录数: 例如:统计userid为1003的记录条数
1 db.comment.count({userid:1003})
六、排序&分页&复杂查询 数据准备 :
1 2 3 for(var i=1;i<5;i++){ db.person.insert({_id:i,name:"p"+i,age:10+i}) }
排序 1 2 3 4 5 db.集合名.find().sort(json数据) # json数据(key:value) - key就是要排序的字段 - value为1表示升序,-1表示降序
1 db.people.find().sort({age:-1}) 按年龄降序排列
分页 1 2 3 4 5 6 7 8 9 10 db.集合名.find().sort().skip(数字).limit(数字)[.count()] # skip(数字) - 指定跳过的数量(可选) # limit (数字)- 限制查询的数量 # count() - 统计数量
测试:
实战 :数据库有1~10条数据,每页显示2条,一共5页
1 2 3 4 5 6 7 8 skip计算公式: (当前页-1)*每页显示的条数 页数 起始 终止 跳过数 1页 1 2 0 2页 3 4 2 3页 5 6 4 4页 7 8 6 5页 9 10 8
1 2 3 4 5 6 7 8 9 # 数据准备 for(var i=1;i<11;i++){ db.page.insert({_id:i,name:"p"+i}) } # 分5页,每页2条显示 for(var i=0;i<10;i=i+2){ db.page.find().skip(i).limit(2) }
复杂查询 文档的正则复杂条件查询 MongoDB的模糊查询是通过正则表达式的方式实现的。格式为:
db.collection.find({field:/正则表达式/})
或
db.集合.find({字段:/正则表达式/})
提示:正则表达式是js的语法,直接量的写法。
例如,我要查询评论内容包含“开水”的所有文档,代码如下:
1 db.comment.find({content:/ 开水/ })
如果要查询评论的内容中以“专家”开头的,代码如下:
1 db.comment.find({content:/ ^ 专家/ })
文档的比较查询 <, <=, >, >= 这个操作符也是很常用的 ,格式如下:
1 2 3 4 5 db.集合名称.find({ "field" : { $gt: value }}) // 大于: field > value db.集合名称.find({ "field" : { $lt: value }}) // 小于: field < value db.集合名称.find({ "field" : { $gte: value }}) // 大于等于: field >= value db.集合名称.find({ "field" : { $lte: value }}) // 小于等于: field <= value db.集合名称.find({ "field" : { $ne: value }}) // 不等于: field != value
示例:查询评论点赞数量大于700的记录
1 db.comment.find({likenum:{$gt:NumberInt(700 )}})
文档的包含查询 包含使用$in操作符。 示例:查询评论的集合中userid字段包含1003或1004的文档
1 db.comment.find({userid:{$in :["1003","1004"]}})
不包含使用$nin操作符。 示例:查询评论集合中userid字段不包含1003和1004的文档
1 db.comment.find({userid:{$nin:["1003","1004"]}})
文档的条件连接查询 我们如果需要查询同时满足两个以上条件,需要使用$and操作符将条件进行关联 。(相当于SQL的and)格式为:
示例:查询评论集合中likenum大于等于700 并且小于2000的文档:
1 db.comment.find({$and :[{likenum:{$gte:NumberInt(700 )}},{likenum:{$lt:NumberInt(2000 )}}]})
如果两个以上条件之间是或者的关系,我们使用操作符进行关联 ,与前面and的使用方式相同格式为:
示例:查询评论集合中userid为1003,或者点赞数小于1000的文档记录
1 db.comment.find({$or :[ {userid:"1003"} ,{likenum:{$lt:1000 } }]})
小结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 选择切换数据库:use articledb 插入数据:db.comment.insert({bson数据}) 查询所有数据:db.comment.find(); 条件查询数据:db.comment.find({条件}) 查询符合条件的第一条记录:db.comment.findOne({条件}) 查询符合条件的前几条记录:db.comment.find({条件}).limit(条数) 查询符合条件的跳过的记录:db.comment.find({条件}).skip(条数) 修改数据:db.comment.update({条件},{修改后的数据}) 或db.comment.update({条件},{$set:{要修改部分的字段:数据}) 修改数据并自增某字段值:db.comment.update({条件},{$inc:{自增的字段:步进值}}) 删除数据:db.comment.remove({条件}) 统计查询:db.comment.count({条件}) 模糊查询:db.comment.find({字段名:/正则表达式/}) 条件比较运算:db.comment.find({字段名:{$gt:值}}) 包含查询:db.comment.find({字段名:{$in:[值1,值2]}})或db.comment.find({字段名:{$nin:[值1,值2]}}) 条件连接查询:db.comment.find({$and:[{条件1},{条件2}]})或db.comment.find({$or:[{条件1},{条件2}]})
七、聚合查询 1. 语法 1 2 3 4 db.集合名.aggregate([ {管道:{表达式}} ... ])
常用管道 :
$group
将集合中的文档分组,用于统计结果
$match
过滤数据,只输出符合条件的文档
$sort
聚合数据进一步排序
$skip
跳过指定文档数
$limit
限制集合数据返回文档数
常用表达式 :
$sum
总和($num:1同count表示统计)
$avg
平均
$min
最小值
$max
最大值
2. 测试 数据准备:
1 2 3 4 5 db.people.insert({_id:1,name:"a",sex:"男",age:21}) db.people.insert({_id:2,name:"b",sex:"男",age:20}) db.people.insert({_id:3,name:"c",sex:"女",age:20}) db.people.insert({_id:4,name:"d",sex:"女",age:18}) db.people.insert({_id:5,name:"e",sex:"男",age:19})
统计男生、女生的总年龄
1 2 3 db.people.aggregate([ {$group:{_id:"$sex",age_sum:{$sum:"$age"}}} ])
统计男生女生的总人数
1 2 3 db.people.aggregate([ {$group:{_id:"$sex",sum:{$sum:1}}} ])
求学生总数和平均年龄
1 2 3 db.people.aggregate([ {$group:{_id:null,total_num:{$sum:1},total_avg:{$avg:"$age"}}} ])
查询男生、女生人数,按人数升序
1 2 3 4 db.people.aggregate([ {$group:{_id:"$sex",rs:{$sum:1}}}, {$sort:{rs:1}} ])
Map-Reduce操作 MongoDB提供Map-Reduce操作来进行聚合操作。通常,Map-Reduce操作有两个阶段,即Map和Reduce阶段 ,其中Map阶段是对集合中的每个输入文档进行处理,处理结束后输出一个或多个结果,****Reduce阶段是将Map阶段输出的一个或多个结果进行合并输出 。
①query阶段,查询集合orders中字段status为A的文档
②map阶段,按照字段cust_id进行分组,将字段cust_id相同的amount值放到一个数组中
③reduce阶段,通过函数sum对每组的amount值进行求和
④output阶段,将结果输出到集合order_totals中
1 2 3 4 5 6 7 8 9 10 db.COLLECTION_NAME.mapReduce( function (){emit(key,value );}, / / map函数 function (key,values ){return reduceFunction}, / / reduce函数 { query:条件, out :New_COLLECTION_NAME, sort:条件, limit:number } )
示例:
查询集合comment中字段state为1的文档,按照字段nickname对文档进行分组,计算出每个评论者的评论条数。
1 2 3 4 5 6 7 8 db.comment.mapReduce( function (){emit(this.nickname,1 );}, function (key,values ){return Array.sum (values )}, { query:{state:"1"}, out :"comment_total" } )
查询结果集合comment_total中的结果数据。
八、索引 1. 简介 索引 是一种排序好的便于快速查询数据的数据结构,用于帮助数据库高效的查询数据
优点 :
提高数据查询的效率,降低数据库的IO成本
通过索引对数据进行排序,降低数据排序的成本,降低CPU的消耗
缺点 :
占用磁盘空间
大量索引影响SQL语句的执行效率,因为每次插入和修改数据都要更新索引
2. 语法 创建索引语法 :
1 2 3 4 5 6 7 8 9 10 11 12 # 创建索引 db.集合名.createIndex(待创建索引的列:方式 [,额外选项]) # 创建复合索引 db.集合名.createIndex({key1:方式,key2:方式} [,额外选项]) # 参数说明: - `待创建索引的列:方式`:{key:1}/{key:-1} 1表示升序,-1表示降序; 例如{age:1}表示创建age索引并按照升序方法排列 - `额外选项`:设置索引的名称或者唯一索引等 设置名称:{name:索引名} 唯一索引:{unique:列名}
删除索引语法 :
1 2 3 4 5 # 删除全部索引 db.集合名.dropIndexes() # 删除指定索引 db.集合名.dropIndex(索引名)
查看索引语法 :
1 2 # 查看索引 db.集合名.getIndexes()
3. 练习 十万条数据准备 :
1 2 3 4 5 6 # 选择数据库 use test # 插入100000条数据 for(var i=0;i<100000;i++){ db.data.insert({name:"zsr"+i,age:i}) }
创建普通索引
1 2 3 4 5 # 给name添加普通升序索引 db.data.createIndex({name:1}) db.data.getIndexes() # 查看索引
1 2 # 给age创建索引并起名age_up db.data.createIndex({age:1},{name:"age_up"})
删除索引
1 2 # 删除name列的索引 db.data.dropIndex("name_1")
创建复合/组合索引 :也就是一次给两个字段建立索引
1 2 # 给name和age添加组合索引 db.data.createIndex({name:1,age:1})
创建唯一索引
1 2 3 4 5 # 删除所有索引 db.data.dropIndexes() # 给name创建唯一索引 db.data.createIndex({name:1},{unique:"name"})
4. 分析索引(explain) 1 db.集合名.find().explain('executionStats')
我们通过简单的案例来测试索引的好处
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 > db.data.find({age:500}).explain('executionStats' ) { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.data", "indexFilterSet" : false, "parsedQuery" : { "age" : { "$eq" : 500 } }, "winningPlan" : { "stage" : "COLLSCAN", "filter" : { "age" : { "$eq" : 500 } }, "direction" : "forward" }, "rejectedPlans" : [ ] }, "executionStats" : { #执行计划相关统计信息 "executionSuccess" : true, #执行成功的状态 "nReturned" : 1, #返回结果集数目 "executionTimeMillis" : 37, #执行所需要的ms数 "totalKeysExamined" : 0, #索引检查的时间 "totalDocsExamined" : 100000, #检查文档总数 "executionStages" : { "stage" : "COLLSCAN", #索引扫描方式 "filter" : { #过滤条件 "age" : { "$eq" : 500 } }, "nReturned" : 1, #返回结果集数目 "executionTimeMillisEstimate" : 1, #预估执行时间(ms) "works" : 100002, #工作单元数,一个查询会被派生为一个小的工作单元 "advanced" : 1, #优先返回的结果数 "needTime" : 100000, "needYield" : 0, "saveState" : 100, "restoreState" : 100, "isEOF" : 1, "direction" : "forward", "docsExamined" : 100000 #文档检查数目 } }, "serverInfo" : { "host" : "LAPTOP-8J48VF43", "port" : 27017, "version" : "4.4.2", "gitVersion" : "15e73dc5738d2278b688f8929aee605fe4279b0e" }, "ok" : 1 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 # 给age添加升序索引 > db.data.createIndex({age:1}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 2, "numIndexesAfter" : 3, "ok" : 1 } # 性能分析 > db.data.find({age:500}).explain('executionStats' ) { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.data", "indexFilterSet" : false, "parsedQuery" : { "age" : { "$eq" : 500 } }, "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "age" : 1 }, "indexName" : "age_1", "isMultiKey" : false, "multiKeyPaths" : { "age" : [ ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { "age" : [ "[500.0, 500.0]" ] } } }, "rejectedPlans" : [ ] }, "executionStats" : { #执行计划相关统计信息 "executionSuccess" : true, #执行成功的状态 "nReturned" : 1, #返回结果集数目 "executionTimeMillis" : 1, #执行所需要的ms数 "totalKeysExamined" : 1, #索引检查的时间 "totalDocsExamined" : 1, #检查文档总数 "executionStages" : { "stage" : "FETCH", #索引扫描方式 "nReturned" : 1, #返回结果集数目 "executionTimeMillisEstimate" : 0, #预估执行时间(ms) "works" : 2, #工作单元数,一个查询会被派生为一个小的工作单元 "advanced" : 1, #优先返回的结果数 "needTime" : 0, "needYield" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 1, "docsExamined" : 1, "alreadyHasObj" : 0, "inputStage" : { "stage" : "IXSCAN", "nReturned" : 1, "executionTimeMillisEstimate" : 0, "works" : 2, "advanced" : 1, "needTime" : 0, "needYield" : 0, "saveState" : 0, "restoreState" : 0, "isEOF" : 1, "keyPattern" : { "age" : 1 }, "indexName" : "age_1", "isMultiKey" : false, "multiKeyPaths" : { "age" : [ ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { "age" : [ "[500.0, 500.0]" ] }, "keysExamined" : 1, "seeks" : 1, "dupsTested" : 0, "dupsDropped" : 0 } } }, "serverInfo" : { "host" : "LAPTOP-8J48VF43", "port" : 27017, "version" : "4.4.2", "gitVersion" : "15e73dc5738d2278b688f8929aee605fe4279b0e" }, "ok" : 1 }
三种扫描方式
COLLSCAN
:全盘扫描
INSCAN
:索引扫描
FETCH
:根据索引去检索指定document
5. 选择规则 如何选择合适的列创建索引?
为常做条件、排序、分组的字段建立索引
选择唯一性索引
选择较小的数据列,为较长的字符串使用前缀索引
九、权限机制
安装完Mongodb
后,在命令行输入mongo
命令即可登录数据库,这肯定是不安全的,我们需要使用权限机制,开启验证模式
创建账号语法 创建账号
1 2 3 4 5 6 7 8 db.createUser({ "user":"账号", "pwd":"密码", "roles":[{ role:"角色", db:"所属数据库" }] })
角色种类
超级用户角色:root
数据库用户角色:read
、readWrite
数据库管理角色:dbAdmin
、userAdmin
集群管理角色: clusterAdmin
、clusterManager
、clusterMonitor
、hostManager
备份恢复角色: backup
、restore
所有数据库角色: readAnyDatabase
、readWriteAnyDatabase
、userAdminAnyDatabase
、dbAdminAnyDatabase
角色说明
root
:只在admin数据库中可用。超级账号,超级权限;
read
:允许用户读取指定数据库;
readWrite
:允许用户读写指定数据库
开启验证模式
验证模式 :值用户需要输入账号密码才能登录使用
1. 添加超级管理员账号 1 2 3 4 5 6 7 8 9 10 11 12 # 必须使用admin数据库 use admin # 创建超级用户 db.createUser({ "user":"zsr", "pwd":"123456", "roles":[{ role:"root", db:"admin" }] })
然后查看admin数据库中的集合system.users
可以查看详细信息
2. 卸载服务 首先exit
退出登录,然后以管理员模式打开终端输入如下命令卸载服务
3. 安装需要身份验证的服务 1 mongod --install --dbpath 数据目录 --logpath 日志目录\日志名称 --auth
这里为:
1 mongod --install --dbpath D:\JAVA_Environment\MongoDB\mongodb-win32-x86_64-windows-4.4.2\data --logpath D:\JAVA_Environment\MongoDB\mongodb-win32-x86_64-windows-4.4.2\logs\mongodb-zsr.log --auth
4. 启动服务
5. 登录测试 输入mongo
命令登录,可以发现不再显示警告,且查看数据库看不到,这是因为还没有身份验证,没有通过账号登录
6. 通过超级管理员账号登录 1 2 # 方法一 mongo 服务器ip地址:端口号/数据库 -u 用户名 -p 密码
1 2 3 4 # 方法二 mongo #先登录 use admin #选择数据库 db.auth(用户名,密码)
练习
添加用户shop1可以读shop数据库
添加用户shop2可以读写shop数据库
注意:必须在对应的数据库中创建用户
1 2 3 4 use shop for(var i=1;i<=10;i++){ db.goods.insert({name:"goods"+i,price:i}) }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 use shop # 创建shop1用户 db.createUser({ "user":"shop1", "pwd":"123456", "roles":[{ role:"read", db:"shop" }] }) # 创建shop2用户 db.createUser({ "user":"shop2", "pwd":"123456", "roles":[{ role:"readWrite", db:"shop" }] })
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 # 验证shop1可读 C:\WINDOWS\system32>mongo localhost:27017/shop -u shop1 -p 123456 MongoDB shell version v4.4.2 connecting to: mongodb://localhost:27017/shop?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("727ada5f-985f-4858-bb30-523d1777fa3a") } MongoDB server version: 4.4.2 > show dbs shop 0.000GB > db.goods.find() { "_id" : ObjectId("60364ec9fd9e42c81a76f431"), "name" : "goods1", "price" : 1 } { "_id" : ObjectId("60364ec9fd9e42c81a76f432"), "name" : "goods2", "price" : 2 } { "_id" : ObjectId("60364ec9fd9e42c81a76f433"), "name" : "goods3", "price" : 3 } { "_id" : ObjectId("60364ec9fd9e42c81a76f434"), "name" : "goods4", "price" : 4 } { "_id" : ObjectId("60364ec9fd9e42c81a76f435"), "name" : "goods5", "price" : 5 } { "_id" : ObjectId("60364ec9fd9e42c81a76f436"), "name" : "goods6", "price" : 6 } { "_id" : ObjectId("60364ec9fd9e42c81a76f437"), "name" : "goods7", "price" : 7 } { "_id" : ObjectId("60364ec9fd9e42c81a76f438"), "name" : "goods8", "price" : 8 } { "_id" : ObjectId("60364ec9fd9e42c81a76f439"), "name" : "goods9", "price" : 9 } { "_id" : ObjectId("60364ec9fd9e42c81a76f43a"), "name" : "goods10", "price" : 10 } > db.goods.insert({name:"zsr" }) WriteCommandError({ "ok" : 0, "errmsg" : "not authorized on shop to execute command { insert: \"goods\", ordered: true, lsid: { id: UUID(\"727ada5f-985f-4858-bb30-523d1777fa3a\") }, $db: \"shop\" }", "code" : 13, "codeName" : "Unauthorized" }) # 验证shop2可读可写 C:\WINDOWS\system32>mongo localhost:27017/shop -u shop2 -p 123456 MongoDB shell version v4.4.2 connecting to: mongodb://localhost:27017/shop?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("1fbca023-aeb3-4514-b2e4-700934000cc9") } MongoDB server version: 4.4.2 > db.goods.find() { "_id" : ObjectId("60364ec9fd9e42c81a76f431"), "name" : "goods1", "price" : 1 } { "_id" : ObjectId("60364ec9fd9e42c81a76f432"), "name" : "goods2", "price" : 2 } { "_id" : ObjectId("60364ec9fd9e42c81a76f433"), "name" : "goods3", "price" : 3 } { "_id" : ObjectId("60364ec9fd9e42c81a76f434"), "name" : "goods4", "price" : 4 } { "_id" : ObjectId("60364ec9fd9e42c81a76f435"), "name" : "goods5", "price" : 5 } { "_id" : ObjectId("60364ec9fd9e42c81a76f436"), "name" : "goods6", "price" : 6 } { "_id" : ObjectId("60364ec9fd9e42c81a76f437"), "name" : "goods7", "price" : 7 } { "_id" : ObjectId("60364ec9fd9e42c81a76f438"), "name" : "goods8", "price" : 8 } { "_id" : ObjectId("60364ec9fd9e42c81a76f439"), "name" : "goods9", "price" : 9 } { "_id" : ObjectId("60364ec9fd9e42c81a76f43a"), "name" : "goods10", "price" : 10 } > db.goods.insert({name:"zsr" }) 可写 WriteResult({ "nInserted" : 1 })
十、备份还原 下载MongoDB数据库工具
进行备份还原之前,首先要下载相关的工具
MongoDB Database Tools
:https://www.mongodb.com/try/download/database-tools
MongoDB数据库工具是用于处理MongoDB部署的命令行实用程序的集合。这些工具独立于MongoDB Server计划发布,使您能够获得更频繁的更新,并在新功能可用时立即加以利用。有关更多信息,请参阅MongoDB数据库工具文档。
下载后得到压缩包 解压 然后点击进入bin
目录,可以看到各种工具,接下来的备份还原就需要用到其中的mongodump
和mongorestore
将其中的所有exe
文件拷贝到MongoDB
安装目录下的bin
目录中
备份数据库mongodump 1 2 3 4 5 6 7 8 9 10 # 导出数据 mongodump -h -port -u -p -d -o # 说明 -h 服务器ip地址(一般不写,默认本机) -port 端口(一般不写,默认27017) -u 账号 -p 密码 -d 数据库(不写则表示导出全部) -o 备份到指定目录下
1️⃣ 备份所有数据:
在MongoDB
安装目录下新建一个data_backup
目录用于存放所有的备份数据
1 mongodump -u zsr -p 123456 -o D:\JAVA_Environment\MongoDB\mongodb-win32-x86_64-windows-4.4.2\data_backup
然后再查看data_backup
目录,可以看到备份的所有的数据库
2️⃣ 备份指定数据:
在MongoDB
安装目录下新建一个data_backup2
目录用于存放备份的shop数据库
1 2 # 用具有读权限的shop1/shop2用户都可以 mongodump -u shop1 -p 123456 -d shop -o D:\JAVA_Environment\MongoDB\mongodb-win32-x86_64-windows-4.4.2\data_backup2
然后再查看data_backu2
目录,可以看到备份的shop数据库
还原数据库mongorestore 1 2 3 4 5 6 7 8 9 mongostore -h -port -u -p -d --drop 备份数据目录 # 说明 -h 服务器ip地址(一般不写,默认本机) -port 端口(一般不写,默认27017) -u 账号 -p 密码 -d 数据库(不写则表示还原全部数据) --drop 先删除数据库再导入,不写则覆盖
1️⃣ 还原所有数据:
首先删除几个数据库 然后输入如下命令从data_backup
目录进行恢复
1 mongorestore -u zsr -p 123456 --drop D:\JAVA_Environment\MongoDB\mongodb-win32-x86_64-windows-4.4.2\data_backup
然后再次登录查看数据库,可以发现已经恢复
2️⃣ 还原指定数据:
首先删除shop数据库 然后输入如下命令从data_backup2
目录恢复shop数据库
1 2 # 用具有写权限的shop2用户 mongorestore -u shop2 -p 123456 -d shop --drop D:\JAVA_Environment\MongoDB\mongodb-win32-x86_64-windows-4.4.2\data_backup2\shop
然后再次登录查看shop数据库,可以发现已经恢复
十一、测试使用Java操作MongoDB 搭建Java环境 JDK的卸载 删除JDK的文件夹
1、在控制面板–程序中,卸载java8的旧版本
2、然后找到安装路径后,直接删除
删除环境变量的配置
此电脑–高级系统设置–环境变量–删除JAVA_HOME
删除Path中关于java的目录
测试是否卸载成功
WIN + R 打开CMD,输入java -version 测试是否卸载成功。
安装新版的JDK 1、百度搜索JDK 8
2、同意协议3、下载电脑对应的版本
4、双击安装JDK
5、记住安装路径(避免使用中文路径)
6、配置环境变量
1.此电脑–右键–属性–高级系统设置–环境变量
2.环境变量–>JAVA_HOME
3.配置Path变量
新建 %JAVA_HOME%\bin
新建 %JAVA_HOME%\jre\bin
4.测试是否成功
CMD中,输入java -version
maven的安装 访问maven官网下载Windows系统下的Maven安装包,本书下载的是maven 3.8.3版本,即apache-maven-3.8.3-bin.zip安装包。
将Maven安装路径下的bin目录添加到系统环境变量的Path变量中,这里添加的C:\Environment\Maven\apache-maven-3.8.3\bin。
Maven环境变量配置完成后,在Windows的DOS窗口执行“mvn -version”命令,查看Maven是否安装配置成功。
修改Maven配置文件settings.xml,该文件位于Maven安装路径下的conf文件夹内,向配置文件中添加本地仓库路径和远程仓库路径,需要注意的是本地仓库路径需要提前创建。
本地仓库
远程仓库(可配阿里云-自行百度)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 <mirrors > <mirror > <id > nexus-aliyun</id > <name > nexus-aliyun</name > <url > http://maven.aliyun.com/nexus/content/groups/public</url > <mirrorOf > central</mirrorOf > </mirror > <mirror > <id > alimaven</id > <name > aliyun maven</name > <url > https://maven.aliyun.com/repository/public</url > <mirrorOf > central</mirrorOf > </mirror > <mirror > <id > alimaven-central</id > <name > aliyun maven central</name > <url > https://maven.aliyun.com/repository/central</url > <mirrorOf > central</mirrorOf > </mirror > <mirror > <id > alimaven-spring</id > <name > aliyun maven-spring</name > <url > https://maven.aliyun.com/repository/spring</url > <mirrorOf > central</mirrorOf > </mirror > <mirror > <id > central</id > <name > Maven Repository Switchboard</name > <url > https://repo1.maven.org/maven2/</url > <mirrorOf > central</mirrorOf > </mirror > <mirror > <id > jboss-public-repository-group</id > <mirrorOf > central</mirrorOf > <name > JBoss Public Repository Group</name > <url > http://repository.jboss.org/nexus/content/groups/public</url > </mirror > <mirror > <id > spring-snapshots</id > <mirrorOf > central</mirrorOf > <name > Spring Snapshots</name > <url > https://repo.spring.io/snapshot</url > </mirror > <mirror > <id > spring-milestones</id > <mirrorOf > central</mirrorOf > <name > Spring Milestones</name > <url > https://repo.spring.io/milestone</url > </mirror > <mirror > <id > maven-default-http-blocker</id > <mirrorOf > external:http:*</mirrorOf > <name > Pseudo repository to mirror external repositories initially using HTTP.</name > <url > http://0.0.0.0/</url > <blocked > true</blocked > </mirror > </mirrors >
基于Java API操作MongoDB idea项目建立 配置IDEA工具,在IDEA安装完成后的界面,单击“Configure”→“Settings”→“Build,Execution,Deployment”→“Build Tools”→“Maven”,将Maven添加至IDEA工具中。
配置IDEA工具,在IDEA安装完成后的界面,“Configure”→“Structure for New Projects”→“Project”,将jdk添加至IDEA工具中。
打开IDEA工具,单击“Create New Project”→“Maven”,选择创建一个Maven项目。
添加Maven项目的名称和指定项目的存储路径。
完成Maven项目的创建。
在项目article中配置pom.xml文件,引入MongoDB相关的依赖和单元测试的依赖 。
项目实训 文章评论 需要实现 以下功能:
1)基本增删改查API
2)根据文章id查询评论
3)评论点赞
数据库:articledb
文章微服务模块搭建 (1)搭建项目工程article,并设置pom.xml引入依赖: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.1.6.RELEASE</version > <relativePath /> </parent > <groupId > org.example</groupId > <artifactId > article</artifactId > <version > 1.0-SNAPSHOT</version > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-mongodb</artifactId > </dependency > </dependencies > <properties > <maven.compiler.source > 8</maven.compiler.source > <maven.compiler.target > 8</maven.compiler.target > </properties > </project >
(2)在article\src\main\resources下创建文件application.yml 1 2 3 4 5 spring: #数据源配置 data: mongodb: uri: mongodb:
(3)创建启动类 在article\src\main\java下创建类cn.itcast.article.ArticleApplication(此处命名方法使用到包机制)
1 2 3 4 5 6 7 8 9 10 11 12 package cn.itcast.article;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class ArticleApplication { public static void main (String[] args) { SpringApplication.run(ArticleApplication.class, args); } }
(4)启动项目,看是否能正常启动,控制台没有错误。
文章评论实体类的编写 在article\src\main\java下创建实体类,创建包cn.itcast.article,包下建包po用于存放实体类,创建实体类
cn.itcast.article.po.Comment
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 package cn.itcast.article.po;import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.index.CompoundIndex;import org.springframework.data.mongodb.core.index.Indexed;import org.springframework.data.mongodb.core.mapping.Document;import org.springframework.data.mongodb.core.mapping.Field;import java.io.Serializable;import java.time.LocalDateTime;import java.util.Date;@Document(collection="comment") @CompoundIndex( def = "{'userid': 1, 'nickname': -1}") public class Comment implements Serializable { private String id; @Field("content") private String content; private Date publishtime; @Indexed private String userid; private String nickname; private LocalDateTime createdatetime; private Integer likenum; private Integer replynum; private String state; private String parentid; private String articleid; public String getId () { return id; } public void setId (String id) { this .id = id; } public String getContent () { return content; } public void setContent (String content) { this .content = content; } public Date getPublishtime () { return publishtime; } public void setPublishtime (Date publishtime) { this .publishtime = publishtime; } public String getUserid () { return userid; } public void setUserid (String userid) { this .userid = userid; } public String getNickname () { return nickname; } public void setNickname (String nickname) { this .nickname = nickname; } public LocalDateTime getCreatedatetime () { return createdatetime; } public void setCreatedatetime (LocalDateTime createdatetime) { this .createdatetime = createdatetime; } public Integer getLikenum () { return likenum; } public void setLikenum (Integer likenum) { this .likenum = likenum; } public Integer getReplynum () { return replynum; } public void setReplynum (Integer replynum) { this .replynum = replynum; } public String getState () { return state; } public void setState (String state) { this .state = state; } public String getParentid () { return parentid; } public void setParentid (String parentid) { this .parentid = parentid; } public String getArticleid () { return articleid; } public void setArticleid (String articleid) { this .articleid = articleid; } @Override public String toString () { return "Comment{" + "id='" + id + '\'' + ", content='" + content + '\'' + ", publishtime=" + publishtime + ", userid='" + userid + '\'' + ", nickname='" + nickname + '\'' + ", createdatetime=" + createdatetime + ", likenum=" + likenum + ", replynum=" + replynum + ", state='" + state + '\'' + ", parentid='" + parentid + '\'' + ", articleid='" + articleid + '\'' + '}' ; } }
文章评论的基本增删改查 (1)创建数据访问接口 cn.itcast.article包下创建dao包,包下创建接口 cn.itcast.article.dao.CommentRepository
1 2 3 4 5 6 7 8 9 10 11 12 13 package cn.itcast.article.dao;import cn.itcast.article.po.Comment;import org.springframework.data.domain.Page;import org.springframework.data.domain.Pageable;import org.springframework.data.mongodb.repository.MongoRepository;public interface CommentRepository extends MongoRepository <Comment,String > { Page<Comment> findByParentid (String parentid,Pageable pageable) ; }
(2)创建业务逻辑类 cn.itcast.article包下创建service包,包下创建类 cn.itcast.article.service.CommentService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 package cn.itcast.article.service;import cn.itcast.article.dao.CommentRepository;import cn.itcast.article.po.Comment;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.Page;import org.springframework.data.domain.PageRequest;import org.springframework.data.domain.Pageable;import org.springframework.data.mongodb.core.MongoTemplate;import org.springframework.data.mongodb.core.query.Criteria;import org.springframework.data.mongodb.core.query.Query;import org.springframework.data.mongodb.core.query.Update;import org.springframework.stereotype.Service;import java.util.List;@Service public class CommentService { @Autowired private CommentRepository commentRepository; @Autowired private MongoTemplate mongoTemplate; public void saveComment (Comment comment) { commentRepository.save(comment); } public void updateComment (Comment comment) { commentRepository.save(comment); } public void deleteCommentById (String id) { commentRepository.deleteById(id); } public List<Comment> findCommentList () { return commentRepository.findAll(); } public Comment findCommentById (String id) { return commentRepository.findById(id).orElse(null ); } public Page<Comment> findCommentListByParentid (String parentid,int page,int size) { return commentRepository.findByParentid(parentid,PageRequest.of(page-1 ,size)); } public void updateCommentLikenum (String id) { Query query = Query.query(Criteria.where("_id" ).is(id)); Update update = new Update (); update.inc("likenum" ); mongoTemplate.updateFirst(query,update,Comment.class); } }
(3)新建Junit测试类,测试保存和查询所有: 在article\src\test\java下新建测试类cn.itcast.article.service.CommentServiceTest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 package cn.itcast.article.service;import cn.itcast.article.ArticleApplication;import cn.itcast.article.po.Comment;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.domain.Page;import org.springframework.test.context.junit4.SpringRunner;import java.time.LocalDateTime;import java.util.List;@RunWith(SpringRunner.class) @SpringBootTest(classes = ArticleApplication.class) public class CommentServiceTest { @Autowired private CommentService commentService; @Test public void testFindCommentList () { List<Comment> commentList = commentService.findCommentList(); System.out.println(commentList); } @Test public void testFindAll () { List<Comment> list = commentService.findCommentList(); System.out.println(list); } @Test public void testFindCommentById () { Comment commentById = commentService.findCommentById("1" ); System.out.println(commentById); } @Test public void testSaveComment () { Comment comment=new Comment (); comment.setArticleid("100000" ); comment.setContent("测试添加的数据" ); comment.setCreatedatetime(LocalDateTime.now()); comment.setUserid("1003" ); comment.setNickname("凯撒大帝" ); comment.setState("1" ); comment.setLikenum(0 ); comment.setReplynum(0 ); commentService.saveComment(comment); } @Test public void testFindCommentListByParentid () { Page<Comment> page = commentService.findCommentListByParentid("3" , 1 , 2 ); System.out.println("----总记录数:" + page.getTotalElements()); System.out.println("----当前页数据:" + page.getContent()); } @Test public void testUpdateCommentLikenum () { commentService.updateCommentLikenum("1" ); } }
添加一条测试数据
根据上级ID查询文章评论的分页列表
插入一条测试数据
1 db.comment.insert([{"parentid":"3","nickname":"张三"}])
MongoTemplate实现评论点赞
十二、MongoDB副本集 MongoDB独立模式可以简单且快速的构建MongoDB数据库系统,然而独立模式存在弊端,即一旦MongoDB发生宕机,将会面临数据丢失的风险,这在生产环境中是不允许发生的,此时我们可以利用MongoDB提供的高可用机制,即复制。MongoDB支持两种复制类型:传统的主/从复制和副本集,副本集可以理解为传统主/从复制的一种复杂形式,支持自动故障恢复功能,拥有更高的可用性,是MongoDB部署中的一种推荐方法 。
副本集概述 副本集(Replica Set)是一组MongoDB实例保持其相同数据集的集群,由一个主(Primary )服务器和多个副本(Secondary )服务器构成。通过复制(Replication )将数据的更新由主服务器推送到其它副本服务器上 ,在一定的延迟之后,达到每个MongoDB实例维护相同的数据集副本。副本集通过维护冗余的数据库副本 、读写分离 和故障自动转移 的功能,摆脱数据库在使用过程中出现的环境故障影响,是所有生产环境部署的基础。
数据的冗余 :副本集可以确保副本节点与主节点数据的自动异步同步,以防止单个数据库服务宕机造成数据丢失的问题。这些副本节点可以和主节点位于同一数据中心或出于安全考虑分布于其它数据中心。
自动故障转移 :副本集没有固定的主节点,整个集群会选举出一个主节点,当这个主节点不能正常工作时,会选举出一个副本节点切换为主节点,客户端会连接到这个新的主节点,并且数据和应用程序都将保持可用。MongoDB副本集实现这样的主/副本切换是自动的,因此副本集是保证MongoDB高可用的基础。
读写分离 :副本集可以将读取请求分流到所有副本上,以减轻主节点的读写压力。
副本集成员 副本集有三个主要成员主节点(Primary)、副本节点(Secondary)、仲裁节点(Arbiter)。
主节点 ——主节点是副本集中负责处理客户端请求和读写数据主要成员。主节点通过oplog(操作日志)记录所有操作。副本集中有且只有一个主节点 ,如果当前主节点不可用,则会从副本节点中选举出新的主节点 。
副本节点 ——副本节点定期轮询主节点获取oplog记录的操作内容,然后对自己的数据副本执行这些操作,从而保证副本节点的数据副本与主节点保持一致 。副本集中可以有一个或多个副本节点。当主节点宕机时,副本集会根据优先级选举出新的主节点。
仲裁节点 ——仲裁节点不会同步 主节点的数据副本,也不会被选举 为主节点,它主要是参与选举投票 。仲裁节点需要的资源很小。当副本集中成员个数为偶数时,建议添加一个仲裁节点,防止选举新的主节点过程中出现票数一致,导致无法选举出新的主节点。
副本集成员架构
客户端程序(Client Application)通过驱动器(Driver)连接副本集主节点(Primary)进行读写操作,当主节点数据副本发生变化,此时副本节点(Secondary)通过Replication(复制)同步主节点的数据副本,使副本集中副本节点与主节点存储相同数据副本。
副本集中的各节点还会通过传递心跳信息(Heartbeat)来检测各自的健康状态。当主节点故障时,拥有投票权的副本节点和仲裁节点(Arbiter)会触发一次新的选举操作,并从副本节点中选举出新的主节点,以确保副本集正常运行 。
部署副本集 推荐方案 通过三台虚拟机部署官方推荐方案的副本集,该副本集包含一个主节点和两个副本节点,三台虚拟机的创建可参考本书资源中提供的环境配置文档,副本集各服务器的基本信息及角色分配如下表。
虚拟机名称
IP****地址
成员角色
主机名
NoSQL_01
192.168.24.14
主节点
nosql01
NoSQL_02
192.168.24.15
副本节点
nosql02
NoSQL_03
192.168.24.16
副本节点
nosql03
为了降低资源分配,这里仅使用一台服务器,但是分配3个端口(27017、27018、27019)来分别实现主节点、副本节点、和仲裁节点的功能。
1.创建主节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 mkdir -p /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/logs \ & mkdir -p /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/data/db vi /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/logs/mongologs.log" logAppend: true storage: dbPath: "/opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/logs/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27017 replication: replSetName: shihanshuors mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/mongod.conf
2.创建副本节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 mkdir -p /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/logs \ & mkdir -p /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/data/db vi /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/logs/mongologs.log" logAppend: true storage: dbPath: "/opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/logs/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27018 replication: replSetName: shihanshuors mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf
3.创建仲裁节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 mkdir -p /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/logs \ & mkdir -p /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/data/db vi /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/logs/mongologs.log" logAppend: true storage: dbPath: "/opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/logs/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27019 replication: replSetName: shihanshuors mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/mongod.conf
4.启动服务 执行 ps -ef|grep mongod
查看端口是否已启动服务
5.初始化配置副本集和主节点 使用客户端命令连接任意一个节点,但这里尽量要连接主节点(27017节点):
由于之前已经配置过环境变量且当前是在本机中测试,因此可以使用 mongo --port=27017
连接上之后,很多命令无法使用,比如 show dbs
等,必须初始化副本集才行。准备初始化新的副本集:rs.initiate()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 [root@Server01 ~]# ps -ef | grep mongod root 2454 1 0 20:20 ? 00:00:01 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/mongod.conf root 2519 1 0 20:21 ? 00:00:01 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf root 2590 1 6 20:23 ? 00:00:00 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/mongod.conf root 2645 2338 0 20:23 pts/0 00:00:00 grep --color=auto mongod [root@Server01 ~]# mongo --port=27017 MongoDB shell version v4.4.24 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("aeaf58ca-9271-4d80-9c27-ef91bf1f42ca" ) } MongoDB server version: 4.4.24 --- The server generated these startup warnings when booting: 2023-10-08T20:20:45.692+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted 2023-10-08T20:20:45.692+08:00: You are running this process as the root user, which is not recommended 2023-10-08T20:20:45.692+08:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . We suggest setting it to 'never' 2023-10-08T20:20:45.692+08:00: Soft rlimits too low 2023-10-08T20:20:45.692+08:00: currentValue: 1024 2023-10-08T20:20:45.692+08:00: recommendedMinimum: 64000 --- > show dbs uncaught exception: Error: listDatabases failed:{ "topologyVersion" : { "processId" : ObjectId("65229e9d3d28ff7e81a43fe4" ), "counter" : NumberLong(0) }, "ok" : 0, "errmsg" : "not master and slaveOk=false" , "code" : 13435, "codeName" : "NotPrimaryNoSecondaryOk" } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12 shellHelper.show@src/mongo/shell/utils.js:937:13 shellHelper@src/mongo/shell/utils.js:819:15 @(shellhelp2):1:1 > rs.initiate () { "info2" : "no configuration specified. Using a default configuration for the set" , "me" : "192.168.24.105:27017" , "ok" : 1 } shihanshuors:SECONDARY> shihanshuors:SECONDARY> shihanshuors:PRIMARY> shihanshuors:PRIMARY> show dbs admin 0.000GB config 0.000GB local 0.000GBshihanshuors:PRIMARY>
提示: 1)“ok”的值为1,说明创建成功。 2)命令行提示符发生变化,变成了一个从节点角色,此时默认不能读写。稍等片刻,回车,变成主节点。
6.查看副本集的配置内容 说明 : 返回包含当前副本集配置的文档。语法 : rs.conf(configuration) rs.config() 是该方法的别名。
configuration:可选,如果没有配置,则使用默认主节点配置
【示例】 在27017上执行副本集中当前节点的默认节点配置:rs.conf()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 shihanshuors:PRIMARY> rs.conf () { "_id" : "shihanshuors" , "version" : 1, "term" : 1, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true , "members" : [ { "_id" : 0, "host" : "192.168.24.105:27017" , "arbiterOnly" : false , "buildIndexes" : true , "hidden" : false , "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true , "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("65229fa43d28ff7e81a43ffc" ) } } shihanshuors:PRIMARY>
说明:
1) “_id” : “shihanshuors” :副本集的配置数据存储的主键值,默认就是副本集的名字
2) “members” :副本集成员数组,此时只有一个: “host” : “192.168.24.105:27017”,该成员不是仲裁节点:”arbiterOnly” : false ,优先级(权重值): “priority” : 1,
3) “settings” :副本集的参数配置。
7.查看副本集状态 检查副本集状态。
说明 : 返回包含状态信息的文档。此输出使用从副本集的其他成员发送的心跳包中获得的数据反映副本集的当前状态。语法 : rs.status()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 shihanshuors:PRIMARY> rs.status () { "set" : "shihanshuors" , "date" : ISODate("2023-10-08T12:26:22.897Z" ), "myState" : 1, "term" : NumberLong(1), "syncSourceHost" : "" , "syncSourceId" : -1, "heartbeatIntervalMillis" : NumberLong(2000), "majorityVoteCount" : 1, "writeMajorityCount" : 1, "votingMembersCount" : 1, "writableVotingMembersCount" : 1, "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1696767978, 1), "t" : NumberLong(1) }, "lastCommittedWallTime" : ISODate("2023-10-08T12:26:18.962Z" ), "readConcernMajorityOpTime" : { "ts" : Timestamp(1696767978, 1), "t" : NumberLong(1) }, "readConcernMajorityWallTime" : ISODate("2023-10-08T12:26:18.962Z" ), "appliedOpTime" : { "ts" : Timestamp(1696767978, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1696767978, 1), "t" : NumberLong(1) }, "lastAppliedWallTime" : ISODate("2023-10-08T12:26:18.962Z" ), "lastDurableWallTime" : ISODate("2023-10-08T12:26:18.962Z" ) }, "lastStableRecoveryTimestamp" : Timestamp(1696767958, 1), "electionCandidateMetrics" : { "lastElectionReason" : "electionTimeout" , "lastElectionDate" : ISODate("2023-10-08T12:25:08.924Z" ), "electionTerm" : NumberLong(1), "lastCommittedOpTimeAtElection" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "lastSeenOpTimeAtElection" : { "ts" : Timestamp(1696767908, 1), "t" : NumberLong(-1) }, "numVotesNeeded" : 1, "priorityAtElection" : 1, "electionTimeoutMillis" : NumberLong(10000), "newTermStartDate" : ISODate("2023-10-08T12:25:08.951Z" ), "wMajorityWriteAvailabilityDate" : ISODate("2023-10-08T12:25:08.969Z" ) }, "members" : [ { "_id" : 0, "name" : "192.168.24.105:27017" , "health" : 1, "state" : 1, "stateStr" : "PRIMARY" , "uptime" : 337, "optime" : { "ts" : Timestamp(1696767978, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2023-10-08T12:26:18Z" ), "lastAppliedWallTime" : ISODate("2023-10-08T12:26:18.962Z" ), "lastDurableWallTime" : ISODate("2023-10-08T12:26:18.962Z" ), "syncSourceHost" : "" , "syncSourceId" : -1, "infoMessage" : "Could not find member to sync from" , "electionTime" : Timestamp(1696767908, 2), "electionDate" : ISODate("2023-10-08T12:25:08Z" ), "configVersion" : 1, "configTerm" : 1, "self" : true , "lastHeartbeatMessage" : "" } ], "ok" : 1, "$clusterTime " : { "clusterTime" : Timestamp(1696767978, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1696767978, 1) }
说明: 1) “set” : “shihanshuors” :副本集的名字 2) “myState” : 1:说明状态正常 3) “members” :副本集成员数组,此时只有一个:”name” : “192.168.24.105:27017”,该成员的角色是”stateStr” : “PRIMARY”,该节点是健康的:”health” : 1 。
8.添加副本从节点 在主节点添加从节点,将其他成员加入到副本集语法 :rs.add(host, arbiterOnly) 选项:
【示例】 将27018的副本节点添加到副本集中:rs.add(“192.168.24.105:27018”)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 shihanshuors:PRIMARY> rs.add("192.168.24.105:27018" ) { "ok" : 1, "$clusterTime " : { "clusterTime" : Timestamp(1696768126, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1696768126, 1) } shihanshuors:PRIMARY> shihanshuors:PRIMARY> rs.status () { "set" : "shihanshuors" , "date" : ISODate("2023-10-08T12:32:15.646Z" ), "myState" : 1, "term" : NumberLong(1), "syncSourceHost" : "" , "syncSourceId" : -1, "heartbeatIntervalMillis" : NumberLong(2000), "majorityVoteCount" : 2, "writeMajorityCount" : 2, "votingMembersCount" : 2, "writableVotingMembersCount" : 2, "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1696768329, 1), "t" : NumberLong(1) }, "lastCommittedWallTime" : ISODate("2023-10-08T12:32:09.024Z" ), "readConcernMajorityOpTime" : { "ts" : Timestamp(1696768329, 1), "t" : NumberLong(1) }, "readConcernMajorityWallTime" : ISODate("2023-10-08T12:32:09.024Z" ), "appliedOpTime" : { "ts" : Timestamp(1696768329, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1696768329, 1), "t" : NumberLong(1) }, "lastAppliedWallTime" : ISODate("2023-10-08T12:32:09.024Z" ), "lastDurableWallTime" : ISODate("2023-10-08T12:32:09.024Z" ) }, "lastStableRecoveryTimestamp" : Timestamp(1696768319, 1), "electionCandidateMetrics" : { "lastElectionReason" : "electionTimeout" , "lastElectionDate" : ISODate("2023-10-08T12:25:08.924Z" ), "electionTerm" : NumberLong(1), "lastCommittedOpTimeAtElection" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "lastSeenOpTimeAtElection" : { "ts" : Timestamp(1696767908, 1), "t" : NumberLong(-1) }, "numVotesNeeded" : 1, "priorityAtElection" : 1, "electionTimeoutMillis" : NumberLong(10000), "newTermStartDate" : ISODate("2023-10-08T12:25:08.951Z" ), "wMajorityWriteAvailabilityDate" : ISODate("2023-10-08T12:25:08.969Z" ) }, "members" : [ { "_id" : 0, "name" : "192.168.24.105:27017" , "health" : 1, "state" : 1, "stateStr" : "PRIMARY" , "uptime" : 690, "optime" : { "ts" : Timestamp(1696768329, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2023-10-08T12:32:09Z" ), "lastAppliedWallTime" : ISODate("2023-10-08T12:32:09.024Z" ), "lastDurableWallTime" : ISODate("2023-10-08T12:32:09.024Z" ), "syncSourceHost" : "" , "syncSourceId" : -1, "infoMessage" : "" , "electionTime" : Timestamp(1696767908, 2), "electionDate" : ISODate("2023-10-08T12:25:08Z" ), "configVersion" : 2, "configTerm" : 1, "self" : true , "lastHeartbeatMessage" : "" }, { "_id" : 1, "name" : "192.168.24.105:27018" , "health" : 1, "state" : 2, "stateStr" : "SECONDARY" , "uptime" : 209, "optime" : { "ts" : Timestamp(1696768329, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1696768329, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2023-10-08T12:32:09Z" ), "optimeDurableDate" : ISODate("2023-10-08T12:32:09Z" ), "lastAppliedWallTime" : ISODate("2023-10-08T12:32:09.024Z" ), "lastDurableWallTime" : ISODate("2023-10-08T12:32:09.024Z" ), "lastHeartbeat" : ISODate("2023-10-08T12:32:14.434Z" ), "lastHeartbeatRecv" : ISODate("2023-10-08T12:32:15.611Z" ), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "" , "syncSourceHost" : "192.168.24.105:27017" , "syncSourceId" : 0, "infoMessage" : "" , "configVersion" : 2, "configTerm" : 1 } ], "ok" : 1, "$clusterTime " : { "clusterTime" : Timestamp(1696768329, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1696768329, 1) } shihanshuors:PRIMARY>
说明: 1) “ok” : 1 :说明添加成功。可以查看副本集状态:rs.status()
2) “name” : “192.168.24.105:27018”,是第二个节点的名字,其角色是 “stateStr” : “SECONDARY”
9.添加仲裁从节点 添加一个仲裁节点到副本集语法 :rs.addArb(host)
【示例】 将27019的仲裁节点添加到副本集中:rs.addArb(“192.168.24.105:27019”)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 shihanshuors:PRIMARY> rs.addArb("192.168.24.105:27019" ) { "ok" : 1, "$clusterTime " : { "clusterTime" : Timestamp(1696768393, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1696768393, 1) } shihanshuors:PRIMARY> rs.status () { "set" : "shihanshuors" , "date" : ISODate("2023-10-08T12:33:17.655Z" ), "myState" : 1, "term" : NumberLong(1), "syncSourceHost" : "" , "syncSourceId" : -1, "heartbeatIntervalMillis" : NumberLong(2000), "majorityVoteCount" : 2, "writeMajorityCount" : 2, "votingMembersCount" : 3, "writableVotingMembersCount" : 2, "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1696768393, 1), "t" : NumberLong(1) }, "lastCommittedWallTime" : ISODate("2023-10-08T12:33:13.643Z" ), "readConcernMajorityOpTime" : { "ts" : Timestamp(1696768393, 1), "t" : NumberLong(1) }, "readConcernMajorityWallTime" : ISODate("2023-10-08T12:33:13.643Z" ), "appliedOpTime" : { "ts" : Timestamp(1696768393, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1696768393, 1), "t" : NumberLong(1) }, "lastAppliedWallTime" : ISODate("2023-10-08T12:33:13.643Z" ), "lastDurableWallTime" : ISODate("2023-10-08T12:33:13.643Z" ) }, "lastStableRecoveryTimestamp" : Timestamp(1696768379, 1), "electionCandidateMetrics" : { "lastElectionReason" : "electionTimeout" , "lastElectionDate" : ISODate("2023-10-08T12:25:08.924Z" ), "electionTerm" : NumberLong(1), "lastCommittedOpTimeAtElection" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "lastSeenOpTimeAtElection" : { "ts" : Timestamp(1696767908, 1), "t" : NumberLong(-1) }, "numVotesNeeded" : 1, "priorityAtElection" : 1, "electionTimeoutMillis" : NumberLong(10000), "newTermStartDate" : ISODate("2023-10-08T12:25:08.951Z" ), "wMajorityWriteAvailabilityDate" : ISODate("2023-10-08T12:25:08.969Z" ) }, "members" : [ { "_id" : 0, "name" : "192.168.24.105:27017" , "health" : 1, "state" : 1, "stateStr" : "PRIMARY" , "uptime" : 752, "optime" : { "ts" : Timestamp(1696768393, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2023-10-08T12:33:13Z" ), "lastAppliedWallTime" : ISODate("2023-10-08T12:33:13.643Z" ), "lastDurableWallTime" : ISODate("2023-10-08T12:33:13.643Z" ), "syncSourceHost" : "" , "syncSourceId" : -1, "infoMessage" : "" , "electionTime" : Timestamp(1696767908, 2), "electionDate" : ISODate("2023-10-08T12:25:08Z" ), "configVersion" : 3, "configTerm" : 1, "self" : true , "lastHeartbeatMessage" : "" }, { "_id" : 1, "name" : "192.168.24.105:27018" , "health" : 1, "state" : 2, "stateStr" : "SECONDARY" , "uptime" : 271, "optime" : { "ts" : Timestamp(1696768393, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1696768393, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2023-10-08T12:33:13Z" ), "optimeDurableDate" : ISODate("2023-10-08T12:33:13Z" ), "lastAppliedWallTime" : ISODate("2023-10-08T12:33:13.643Z" ), "lastDurableWallTime" : ISODate("2023-10-08T12:33:13.643Z" ), "lastHeartbeat" : ISODate("2023-10-08T12:33:17.650Z" ), "lastHeartbeatRecv" : ISODate("2023-10-08T12:33:17.654Z" ), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "" , "syncSourceHost" : "192.168.24.105:27017" , "syncSourceId" : 0, "infoMessage" : "" , "configVersion" : 3, "configTerm" : 1 }, { "_id" : 2, "name" : "192.168.24.105:27019" , "health" : 1, "state" : 7, "stateStr" : "ARBITER" , "uptime" : 4, "lastHeartbeat" : ISODate("2023-10-08T12:33:17.654Z" ), "lastHeartbeatRecv" : ISODate("2023-10-08T12:33:15.670Z" ), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "" , "syncSourceHost" : "" , "syncSourceId" : -1, "infoMessage" : "" , "configVersion" : 3, "configTerm" : 1 } ], "ok" : 1, "$clusterTime " : { "clusterTime" : Timestamp(1696768393, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1696768393, 1) } shihanshuors:PRIMARY>
说明 : 1) “ok” : 1 :说明添加成功。可以查看副本集状态:rs.status()
2) “name” : “192.168.24.105:27019” 是第二个节点的名字,其角色是 “stateStr” : “ARBITER”
10.可使用可视化工具创建连接
Studio 3T版本
副本集操作 副本集的数据读写操作 目标:测试三个不同角色的节点的数据读写情况。
1.登录主节点27017 使用mongo shell 登录主节点27017,写入和读取数据:
1 mongo --host=192.168.24.105 --port=27017
1 2 3 4 5 6 7 8 9 10 11 shihanshuors:PRIMARY> show dbs admin 0.000GB config 0.000GB local 0.000GBshihanshuors:PRIMARY> use articledb switched to db articledb shihanshuors:PRIMARY> db articledb shihanshuors:PRIMARY>db.comment.insert({"articleid" :"100000" ,"content" :"今天天气真好,阳光 明媚" ,"userid" :"1001" ,"nickname" :"Rose" ,"createdatetime" :new Date()}) WriteResult({ "nInserted" : 1 }) shihanshuors:PRIMARY> db.comment.find()
或使用可视化工具打开主节点服务器
插入测试数据
1 db.comment.insert({"articleid":"100000","content":"今天天气真好,阳光明媚","userid":"1001","nickname":"Rose","createdatetime":new Date ()})
2.登录从节点27018: 使用mongo shell 登录从节点,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 [root@Server01 ~]# mongo --host=192.168.24.105 --port=27018 MongoDB shell version v4.4.24 connecting to: mongodb://192.168.24.105:27018/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("4b677922-4900-45d4-a671-3f5a32659899" ) } MongoDB server version: 4.4.24 --- The server generated these startup warnings when booting: 2023-10-08T20:21:35.751+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted 2023-10-08T20:21:35.751+08:00: You are running this process as the root user, which is not recommended 2023-10-08T20:21:35.751+08:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . We suggest setting it to 'never' 2023-10-08T20:21:35.751+08:00: Soft rlimits too low 2023-10-08T20:21:35.751+08:00: currentValue: 1024 2023-10-08T20:21:35.751+08:00: recommendedMinimum: 64000 --- shihanshuors:SECONDARY> show dbs uncaught exception: Error: listDatabases failed:{ "topologyVersion" : { "processId" : ObjectId("65229ecfc331e179e72265cd" ), "counter" : NumberLong(4) }, "operationTime" : Timestamp(1696769379, 1), "ok" : 0, "errmsg" : "not master and slaveOk=false" , "code" : 13435, "codeName" : "NotPrimaryNoSecondaryOk" , "$clusterTime " : { "clusterTime" : Timestamp(1696769379, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } } } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12 shellHelper.show@src/mongo/shell/utils.js:937:13 shellHelper@src/mongo/shell/utils.js:819:15 @(shellhelp2):1:1 shihanshuors:SECONDARY> rs.slaveOk() WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead. shihanshuors:SECONDARY> show dbs admin 0.000GB articledb 0.000GB config 0.000GB local 0.000GBshihanshuors:SECONDARY> use articledb switched to db articledb shihanshuors:SECONDARY> db.comment.find () { "_id" : ObjectId("6241111d951e2161fb8bb4b9" ), "articleid" : "100000" , "content" : "今天天气真好,阳光 明媚" , "userid" : "1001" , "nickname" : "Rose" , "createdatetime" : ISODate("2022-03-28T01:36:29.589Z" ) } shihanshuors:SECONDARY>
发现,不能读取集合的数据。当前从节点只是一个备份,不是奴隶节点,无法读取数据,写当然更不行。 因为默认情况下,从节点是没有读写权限的,可以增加读的权限,但需要进行设置。
设置读操作权限:说明 : 设置为奴隶节点,允许在从成员上运行读的操作语法 :rs.slaveOk()
或 rs.slaveOk(true)
提示: 该命令是 db.getMongo().setSlaveOk()
的简化命令。
现在可实现了读写分离,让主插入数据,让从来读取数据。 如果要取消作为奴隶节点的读权限:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 shihanshuors:SECONDARY> rs.slaveOk(false ) WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead. shihanshuors:SECONDARY> db.comment.find() Error: error: { "operationTime" : Timestamp(1648432243, 1), "ok" : 0, "errmsg" : "not master and slaveOk=false" , "code" : 13435, "codeName" : "NotPrimaryNoSecondaryOk" , "$clusterTime " : { "clusterTime" : Timestamp(1648432243, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } } } shihanshuors:SECONDARY>
3.登录仲裁者节点27019 仲裁者节点27019,不存放任何业务数据的,可以登录查看,我们发现,arbiter并没有进行数据同步,因为仲裁节点只参与投票,不接收数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 [root@localhost ~]# mongo --host=192.168.24.105 --port=27019 MongoDB shell version v4.2.18 connecting to: mongodb://192.168.24.105:27019/? --- shihanshuors:ARBITER> show dbs 2022-03-28T09:52:21.744+0800 E QUERY [js] uncaught exception: Error: listDatabases failed:{ "ok" : 0, "errmsg" : "not master and slaveOk=false" , "code" : 13435, "codeName" : "NotPrimaryNoSecondaryOk" } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12 shellHelper.show@src/mongo/shell/utils.js:906:13 shellHelper@src/mongo/shell/utils.js:790:15 @(shellhelp2):1:1 shihanshuors:ARBITER> rs.slaveOk() WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead. shihanshuors:ARBITER> use articledb switched to db articledb shihanshuors:ARBITER> db articledb shihanshuors:ARBITER> db.comment.find() Error: error: { "ok" : 0, "errmsg" : "node is not in primary or recovering state" , "code" : 13436, "codeName" : "NotPrimaryOrSecondary" } shihanshuors:ARBITER>
副本集机制 同步机制 为了保证副本集中各成员中的数据副本一致,副本集的副本节点默认会以主节点作为同步源 进行数据同步。
MongoDB使用两种形式完成数据同步过程,分别是完整同步 和变化同步 。
在副本集新增成员 情况下,采用完整同步 方式同步数据副本。
新增成员选择副本集中的主节点作为同步源。
扫描源数据库中的每个集合,并将这些集合中的所有文档插入本地,此过程比较耗时。
通过主节点的oplog重建本地oplog。
完成初始化同步,成为副本节点。
在副本集主节点中数据副本发生变化的情况下,采用变化同步 方式同步数据副本。
副本集主节点数据副本发生变化时,oplog会记录变化内容。
副本节点获取主节点oplog记录变化内容并执行相关操作。
副本节点根据主节点oplog重建本地oplog。
选举机制 如果副本集的主节点在使用过程中发生故障导致无法使用,则其它拥有投票权的成员便会通过选举机制从副本集所有符合选举条件的成员中选出新的主节点。选举的过程可以由任意的非主节点成员发起 ,然后根据优先级和Bully算法(评判谁的数据最新)选举出主节点。在选举出主节点之前,整个集群服务是只读的 ,不能执行写入操作。非仲裁节点都有一个优先级的配置,范围为0~100, 值越大,则越优先成为主节点。默认情况下,优先级是1;如果优先级是0,则不能成为主节点。
1.主节点的选举原则 MongoDB在副本集中,会自动进行主节点的选举,主节点选举的触发条件 :
1) 主节点故障
2) 主节点网络不可达(默认心跳信息为10秒)
3) 人工干预(rs.stepDown(600))
一旦触发选举,就要根据一定规则来选主节点。选举规则是根据票数来决定谁获胜:
1) 票数最高,且获得了“大多数 ”成员的投票支持的节点获胜。“大多数”的定义为:假设复制集内投票成员数量为N,则大多数为 N/2 + 1 。例如:3个投票成员,则大多数的值是2。当复制集内存活成员数量不足大多数时,整个复制集将无法选举出Primary,复制集将无法提供写服务,处于只读状态。
2) 若票数相同,且都获得了“大多数”成员的投票支持的,数据新的节点获胜 。数据的新旧是通过操作日志oplog来对比的。
在获得票数的时候,优先级(priority)参数影响重大。
可以通过设置优先级(priority)来设置额外票数。优先级即权重,取值为0-1000,相当于可额外增加0-1000的票数,优先级的值越大,就越可能获得多数成员的投票(votes)数。指定较高的值可使成员更有资格成为主要成员,更低的值可使成员更不符合条件。
默认情况下,优先级的值是1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 [root@Server01 mongodb]# mongo --host=192.168.24.105 --port=27017 MongoDB shell version v4.4.24 connecting to: mongodb://192.168.24.105:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("ce47fbae-a157-442f-99f5-354b4e076b84" ) } MongoDB server version: 4.4.24 --- The server generated these startup warnings when booting: 2023-10-14T19:40:26.611+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted 2023-10-14T19:40:26.611+08:00: You are running this process as the root user, which is not recommended 2023-10-14T19:40:26.611+08:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . We suggest setting it to 'never' 2023-10-14T19:40:26.611+08:00: Soft rlimits too low 2023-10-14T19:40:26.611+08:00: currentValue: 1024 2023-10-14T19:40:26.611+08:00: recommendedMinimum: 64000 2023-10-14T19:40:26.645+08:00: 2023-10-14T19:40:26.645+08:00: ** WARNING: This replica set has a Primary-Secondary-Arbiter architecture, but readConcern:majority is enabled 2023-10-14T19:40:26.645+08:00: ** for this node. This is not a recommended configuration. Please see 2023-10-14T19:40:26.645+08:00: ** https://dochub.mongodb.org/core/psa-disable-rc-majority 2023-10-14T19:40:26.645+08:00: --- shihanshuors:PRIMARY> shihanshuors:PRIMARY> shihanshuors:PRIMARY> shihanshuors:PRIMARY> shihanshuors:PRIMARY> rs.conf () { "_id" : "shihanshuors" , "version" : 3, "term" : 2, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true , "members" : [ { "_id" : 0, "host" : "192.168.24.105:27017" , "arbiterOnly" : false , "buildIndexes" : true , "hidden" : false , "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "192.168.24.105:27018" , "arbiterOnly" : false , "buildIndexes" : true , "hidden" : false , "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "192.168.24.105:27019" , "arbiterOnly" : true , "buildIndexes" : true , "hidden" : false , "priority" : 0, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true , "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("65229fa43d28ff7e81a43ffc" ) } } shihanshuors:PRIMARY>
可以看出,主节点和副本节点的优先级各为1,即,默认可以认为都已经有了一票。但选举节点,优先级是0,(要注意是,官方说了,选举节点的优先级必须是0,不能是别的值。即不具备选举权,但具有投票权)
故障测试 1.副本节点故障测试 关闭27018副本节点:发现,主节点和仲裁节点对27018的心跳失败。因为主节点还在,因此,没有触发投票选举。如果此时,在主节点写入数据。
1)关闭副本节点27018
1 2 3 4 5 6 [root@Server01 ~]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf --shutdown killing process with pid: 2677 [root@Server01 ~]# ps -ef | grep mongod root 2604 1 0 19:40 ? 00:00:13 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/mongod.conf root 2752 1 0 19:40 ? 00:00:09 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/mongod.conf root 3455 2308 0 20:15 pts/0 00:00:00 grep --color=auto mongod
2)登入主节点27017,执行 use articledb 切换后执行 db.comment.find() 查看当且数据,最后插入一条新的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 shihanshuors:PRIMARY> show dbs admin 0.000GB articledb 0.000GB config 0.000GB local 0.000GBshihanshuors:PRIMARY> use articledb switched to db articledb shihanshuors:PRIMARY> db articledb shihanshuors:PRIMARY> db.comment.find () { "_id" : "7" , "articleid" : "100001" , "content" : "吃饭前,先喝杯水或一碗汤,可减少饭量,对控制体重有帮助" , "userid" : "1007" , "nickname" : "玛丽莲•梦露" , "age" : "18" , "phone" : " 13937165554" , "createdatetime" : ISODate("2023-10-08T12:46:31.423Z" ), "likenum" : "8888" , "state" : "null" } shihanshuors:PRIMARY> db.comment.insert({ "_id" : "1" , "articleid" : "100001" , "content" : "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。" , "userid" : "1002" , "nickname" : "相忘于江湖" , "createdatetime" : ISODate("2022-03-28T10:08:15.522Z" ), "likenum" : 1000, "state" : "1" }) WriteResult({ "nInserted" : 1 }) shihanshuors:PRIMARY> db.comment.find () { "_id" : "7" , "articleid" : "100001" , "content" : "吃饭前,先喝杯水或一碗汤,可减少饭量,对控制体重有帮助" , "userid" : "1007" , "nickname" : "玛丽莲•梦露" , "age" : "18" , "phone" : " 13937165554" , "createdatetime" : ISODate("2023-10-08T12:46:31.423Z" ), "likenum" : "8888" , "state" : "null" } { "_id" : "1" , "articleid" : "100001" , "content" : "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。" , "userid" : "1002" , "nickname" : "相忘于江湖" , "createdatetime" : ISODate("2022-03-28T10:08:15.522Z" ), "likenum" : 1000, "state" : "1" } shihanshuors:PRIMARY>
3)再启动从节点,会发现,主节点写入的数据,会自动同步给从节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 [root@Server01 ~]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 3494 child process started successfully, parent exiting [root@Server01 ~]# ps -ef | grep mongod root 2604 1 0 19:40 ? 00:00:14 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/mongod.conf root 2752 1 0 19:40 ? 00:00:10 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/mongod.conf root 3494 1 26 20:17 ? 00:00:00 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf root 3578 2308 0 20:18 pts/0 00:00:00 grep --color=auto mongod [root@Server01 ~]# [root@Server01 ~]# mongo --host=192.168.24.105 --port=27018 MongoDB shell version v4.4.24 connecting to: mongodb://192.168.24.105:27018/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("172e00ad-5cb7-4f1c-90c5-c7dde3a0f9ff" ) } MongoDB server version: 4.4.24 --- The server generated these startup warnings when booting: 2023-10-14T20:17:59.369+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted 2023-10-14T20:17:59.369+08:00: You are running this process as the root user, which is not recommended 2023-10-14T20:17:59.369+08:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . We suggest setting it to 'never' 2023-10-14T20:17:59.369+08:00: Soft rlimits too low 2023-10-14T20:17:59.369+08:00: currentValue: 1024 2023-10-14T20:17:59.369+08:00: recommendedMinimum: 64000 2023-10-14T20:17:59.385+08:00: 2023-10-14T20:17:59.385+08:00: ** WARNING: This replica set has a Primary-Secondary-Arbiter architecture, but readConcern:majority is enabled 2023-10-14T20:17:59.386+08:00: ** for this node. This is not a recommended configuration. Please see 2023-10-14T20:17:59.386+08:00: ** https://dochub.mongodb.org/core/psa-disable-rc-majority 2023-10-14T20:17:59.386+08:00: --- shihanshuors:SECONDARY> show dbs uncaught exception: Error: listDatabases failed:{ "topologyVersion" : { "processId" : ObjectId("652a86f6ba6f60e664835b08" ), "counter" : NumberLong(3) }, "operationTime" : Timestamp(1697285917, 1), "ok" : 0, "errmsg" : "not master and slaveOk=false" , "code" : 13435, "codeName" : "NotPrimaryNoSecondaryOk" , "$clusterTime " : { "clusterTime" : Timestamp(1697285917, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } } } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12 shellHelper.show@src/mongo/shell/utils.js:937:13 shellHelper@src/mongo/shell/utils.js:819:15 @(shellhelp2):1:1 shihanshuors:SECONDARY> rs.slaveOk() WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead. shihanshuors:SECONDARY> shihanshuors:SECONDARY> use articledb switched to db articledb shihanshuors:SECONDARY> db.comment.find () { "_id" : "7" , "articleid" : "100001" , "content" : "吃饭前,先喝杯水或一碗汤,可减少饭量,对控制体重有帮助" , "userid" : "1007" , "nickname" : "玛丽莲•梦露" , "age" : "18" , "phone" : " 13937165554" , "createdatetime" : ISODate("2023-10-08T12:46:31.423Z" ), "likenum" : "8888" , "state" : "null" } { "_id" : "1" , "articleid" : "100001" , "content" : "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。" , "userid" : "1002" , "nickname" : "相忘于江湖" , "createdatetime" : ISODate("2022-03-28T10:08:15.522Z" ), "likenum" : 1000, "state" : "1" } shihanshuors:SECONDARY>
2.主节点故障测试 关闭27017节点:发现,从节点和仲裁节点对27017的心跳失败,当失败超过10秒,此时因为没有主节点了,会自动发起投票。而副本节点只有27018,因此,候选人只有一个就是27018,开始投票。27019向27018投了一票,27018本身自带一票,因此共两票,超过了“大多数”27019是仲裁节点,没有选举权,27018不向其投票,其票数是0。最终结果,27018成为主节点。具备读写功能。在27018写入数据查看。
1)关闭(原)主节点27017
1 2 3 4 5 6 7 [root@Server01 ~]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/mongod.conf --shutdown killing process with pid: 2604 [root@Server01 ~]# ps -ef | grep mongod root 2752 1 0 19:40 ? 00:00:10 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/mongod.conf root 3494 1 1 20:17 ? 00:00:01 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf root 3614 2308 0 20:20 pts/0 00:00:00 grep --color=auto mongod [root@Server01 ~]#
2)登入(原)副本节点27018(触发选举机制),执行 use articledb 切换后执行 db.comment.find() 查看当且数据,最后插入一条新的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 shihanshuors:SECONDARY> shihanshuors:PRIMARY> shihanshuors:PRIMARY> use articledb switched to db articledb shihanshuors:PRIMARY> db articledb shihanshuors:PRIMARY> db.comment.find () { "_id" : "7" , "articleid" : "100001" , "content" : "吃饭前,先喝杯水或一碗汤,可减少饭量,对控制体重有帮助" , "userid" : "1007" , "nickname" : "玛丽莲•梦露" , "age" : "18" , "phone" : " 13937165554" , "createdatetime" : ISODate("2023-10-08T12:46:31.423Z" ), "likenum" : "8888" , "state" : "null" } { "_id" : "1" , "articleid" : "100001" , "content" : "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。" , "userid" : "1002" , "nickname" : "相忘于江湖" , "createdatetime" : ISODate("2022-03-28T10:08:15.522Z" ), "likenum" : 1000, "state" : "1" } shihanshuors:PRIMARY> shihanshuors:PRIMARY> db.comment.insert({ "_id" : "2" , "articleid" : "100001" , "content" : "我夏天空腹喝凉开水,冬天喝温开水" , "userid" : "1005" , "nickname" : "伊人憔悴" , "createdatetime" : ISODate("2022-01-01T00:00:00Z" ), "likenum" : 888, "state" : "1" }) WriteResult({ "nInserted" : 1 }) shihanshuors:PRIMARY> db.comment.find () { "_id" : "7" , "articleid" : "100001" , "content" : "吃饭前,先喝杯水或一碗汤,可减少饭量,对控制体重有帮助" , "userid" : "1007" , "nickname" : "玛丽莲•梦露" , "age" : "18" , "phone" : " 13937165554" , "createdatetime" : ISODate("2023-10-08T12:46:31.423Z" ), "likenum" : "8888" , "state" : "null" } { "_id" : "1" , "articleid" : "100001" , "content" : "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。" , "userid" : "1002" , "nickname" : "相忘于江湖" , "createdatetime" : ISODate("2022-03-28T10:08:15.522Z" ), "likenum" : 1000, "state" : "1" } { "_id" : "2" , "articleid" : "100001" , "content" : "我夏天空腹喝凉开水,冬天喝温开水" , "userid" : "1005" , "nickname" : "伊人憔悴" , "createdatetime" : ISODate("2022-01-01T00:00:00Z" ), "likenum" : 888, "state" : "1" }
3)再启动27017节点,发现27017变成了从节点,27018仍保持主节点。登录27017节点,发现是从节点了,数据自动从27018同步。从而实现了高可用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 [root@Server01 ~]# mongo --host=192.168.24.105 --port=27017 MongoDB shell version v4.4.24 connecting to: mongodb://192.168.24.105:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("a865267b-fdae-4243-9af1-3b83847358bc" ) } MongoDB server version: 4.4.24 --- The server generated these startup warnings when booting: 2023-10-14T20:22:09.784+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted 2023-10-14T20:22:09.784+08:00: You are running this process as the root user, which is not recommended 2023-10-14T20:22:09.784+08:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . We suggest setting it to 'never' 2023-10-14T20:22:09.784+08:00: Soft rlimits too low 2023-10-14T20:22:09.784+08:00: currentValue: 1024 2023-10-14T20:22:09.784+08:00: recommendedMinimum: 64000 2023-10-14T20:22:09.801+08:00: 2023-10-14T20:22:09.801+08:00: ** WARNING: This replica set has a Primary-Secondary-Arbiter architecture, but readConcern:majority is enabled 2023-10-14T20:22:09.801+08:00: ** for this node. This is not a recommended configuration. Please see 2023-10-14T20:22:09.801+08:00: ** https://dochub.mongodb.org/core/psa-disable-rc-majority 2023-10-14T20:22:09.801+08:00: --- shihanshuors:SECONDARY> shihanshuors:SECONDARY> rs.slaveOk() WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead. shihanshuors:SECONDARY> use articledb switched to db articledb shihanshuors:SECONDARY> db.comment.find () { "_id" : "7" , "articleid" : "100001" , "content" : "吃饭前,先喝杯水或一碗汤,可减少饭量,对控制体重有帮助" , "userid" : "1007" , "nickname" : "玛丽莲•梦露" , "age" : "18" , "phone" : " 13937165554" , "createdatetime" : ISODate("2023-10-08T12:46:31.423Z" ), "likenum" : "8888" , "state" : "null" } { "_id" : "1" , "articleid" : "100001" , "content" : "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。" , "userid" : "1002" , "nickname" : "相忘于江湖" , "createdatetime" : ISODate("2022-03-28T10:08:15.522Z" ), "likenum" : 1000, "state" : "1" } { "_id" : "2" , "articleid" : "100001" , "content" : "我夏天空腹喝凉开水,冬天喝温开水" , "userid" : "1005" , "nickname" : "伊人憔悴" , "createdatetime" : ISODate("2022-01-01T00:00:00Z" ), "likenum" : 888, "state" : "1" } shihanshuors:SECONDARY>
3.仲裁节点和主节点故障 先关掉仲裁节点27019,再关掉现在的主节点27018
1 2 3 4 5 6 7 8 9 10 11 12 [root@Server01 ~]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/mongod.conf --shutdown killing process with pid: 2752 [root@Server01 ~]# ps -ef | grep mongod root 3494 1 0 20:17 ? 00:00:02 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf root 3641 1 0 20:22 ? 00:00:01 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/mongod.conf root 3765 2308 0 20:24 pts/0 00:00:00 grep --color=auto mongod [root@Server01 ~]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf --shutdown killing process with pid: 3494 [root@Server01 ~]# ps -ef | grep mongod root 3641 1 0 20:22 ? 00:00:01 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/mongod.conf root 3782 2308 0 20:25 pts/0 00:00:00 grep --color=auto mongod [root@Server01 ~]#
登录27017后,发现,27017仍然是从节点,副本集中没有主节点了,导致此时,副本集是只读状态,无法写入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 shihanshuors:SECONDARY> exit bye [root@Server01 ~]# mongo --host=192.168.24.105 --port=27017 MongoDB shell version v4.4.24 connecting to: mongodb://192.168.24.105:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("f818db1d-cf2c-4d65-bf4e-043639455521" ) } MongoDB server version: 4.4.24 --- The server generated these startup warnings when booting: 2023-10-14T20:22:09.784+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted 2023-10-14T20:22:09.784+08:00: You are running this process as the root user, which is not recommended 2023-10-14T20:22:09.784+08:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . We suggest setting it to 'never' 2023-10-14T20:22:09.784+08:00: Soft rlimits too low 2023-10-14T20:22:09.784+08:00: currentValue: 1024 2023-10-14T20:22:09.784+08:00: recommendedMinimum: 64000 2023-10-14T20:22:09.801+08:00: 2023-10-14T20:22:09.801+08:00: ** WARNING: This replica set has a Primary-Secondary-Arbiter architecture, but readConcern:majority is enabled 2023-10-14T20:22:09.801+08:00: ** for this node. This is not a recommended configuration. Please see 2023-10-14T20:22:09.801+08:00: ** https://dochub.mongodb.org/core/psa-disable-rc-majority 2023-10-14T20:22:09.801+08:00: --- shihanshuors:SECONDARY> shihanshuors:SECONDARY> show dbs uncaught exception: Error: listDatabases failed:{ "topologyVersion" : { "processId" : ObjectId("652a87f1c99e4b9d4891fa33" ), "counter" : NumberLong(4) }, "operationTime" : Timestamp(1697286312, 1), "ok" : 0, "errmsg" : "not master and slaveOk=false" , "code" : 13435, "codeName" : "NotPrimaryNoSecondaryOk" , "$clusterTime " : { "clusterTime" : Timestamp(1697286312, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } } } : _getErrorWithCode@src/mongo/shell/utils.js:25:13 Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12 shellHelper.show@src/mongo/shell/utils.js:937:13 shellHelper@src/mongo/shell/utils.js:819:15 @(shellhelp2):1:1 shihanshuors:SECONDARY> rs.slaveOk() WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead. shihanshuors:SECONDARY> show dbs admin 0.000GB articledb 0.000GB config 0.000GB local 0.000GBshihanshuors:SECONDARY> use articledb switched to db articledb shihanshuors:SECONDARY> db.comment.find () { "_id" : "7" , "articleid" : "100001" , "content" : "吃饭前,先喝杯水或一碗汤,可减少饭量,对控制体重有帮助" , "userid" : "1007" , "nickname" : "玛丽莲•梦露" , "age" : "18" , "phone" : " 13937165554" , "createdatetime" : ISODate("2023-10-08T12:46:31.423Z" ), "likenum" : "8888" , "state" : "null" } { "_id" : "1" , "articleid" : "100001" , "content" : "我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。" , "userid" : "1002" , "nickname" : "相忘于江湖" , "createdatetime" : ISODate("2022-03-28T10:08:15.522Z" ), "likenum" : 1000, "state" : "1" } { "_id" : "2" , "articleid" : "100001" , "content" : "我夏天空腹喝凉开水,冬天喝温开水" , "userid" : "1005" , "nickname" : "伊人憔悴" , "createdatetime" : ISODate("2022-01-01T00:00:00Z" ), "likenum" : 888, "state" : "1" } shihanshuors:SECONDARY> shihanshuors:SECONDARY> rs.status () { "set" : "shihanshuors" , "date" : ISODate("2023-10-14T12:29:19.062Z" ), "myState" : 2, "term" : NumberLong(5), "syncSourceHost" : "" , "syncSourceId" : -1, "heartbeatIntervalMillis" : NumberLong(2000), "majorityVoteCount" : 2, "writeMajorityCount" : 2, "votingMembersCount" : 3, "writableVotingMembersCount" : 2, "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1697286312, 1), "t" : NumberLong(4) }, "lastCommittedWallTime" : ISODate("2023-10-14T12:25:12.022Z" ), "readConcernMajorityOpTime" : { "ts" : Timestamp(1697286312, 1), "t" : NumberLong(4) }, "readConcernMajorityWallTime" : ISODate("2023-10-14T12:25:12.022Z" ), "appliedOpTime" : { "ts" : Timestamp(1697286312, 1), "t" : NumberLong(4) }, "durableOpTime" : { "ts" : Timestamp(1697286312, 1), "t" : NumberLong(4) }, "lastAppliedWallTime" : ISODate("2023-10-14T12:25:12.022Z" ), "lastDurableWallTime" : ISODate("2023-10-14T12:25:12.022Z" ) }, "lastStableRecoveryTimestamp" : Timestamp(1697286312, 1), "members" : [ { "_id" : 0, "name" : "192.168.24.105:27017" , "health" : 1, "state" : 2, "stateStr" : "SECONDARY" , "uptime" : 430, "optime" : { "ts" : Timestamp(1697286312, 1), "t" : NumberLong(4) }, "optimeDate" : ISODate("2023-10-14T12:25:12Z" ), "lastAppliedWallTime" : ISODate("2023-10-14T12:25:12.022Z" ), "lastDurableWallTime" : ISODate("2023-10-14T12:25:12.022Z" ), "syncSourceHost" : "" , "syncSourceId" : -1, "infoMessage" : "" , "configVersion" : 3, "configTerm" : 4, "self" : true , "lastHeartbeatMessage" : "" }, { "_id" : 1, "name" : "192.168.24.105:27018" , "health" : 0, "state" : 8, "stateStr" : "(not reachable/healthy)" , "uptime" : 0, "optime" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "optimeDurable" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "optimeDate" : ISODate("1970-01-01T00:00:00Z" ), "optimeDurableDate" : ISODate("1970-01-01T00:00:00Z" ), "lastAppliedWallTime" : ISODate("2023-10-14T12:25:12.022Z" ), "lastDurableWallTime" : ISODate("2023-10-14T12:25:12.022Z" ), "lastHeartbeat" : ISODate("2023-10-14T12:29:18.638Z" ), "lastHeartbeatRecv" : ISODate("2023-10-14T12:25:12.099Z" ), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "Error connecting to 192.168.24.105:27018 :: caused by :: Connection refused" , "syncSourceHost" : "" , "syncSourceId" : -1, "infoMessage" : "" , "configVersion" : 3, "configTerm" : 4 }, { "_id" : 2, "name" : "192.168.24.105:27019" , "health" : 0, "state" : 8, "stateStr" : "(not reachable/healthy)" , "uptime" : 0, "lastHeartbeat" : ISODate("2023-10-14T12:29:18.638Z" ), "lastHeartbeatRecv" : ISODate("2023-10-14T12:24:24.090Z" ), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "Error connecting to 192.168.24.105:27019 :: caused by :: Connection refused" , "syncSourceHost" : "" , "syncSourceId" : -1, "infoMessage" : "" , "configVersion" : 3, "configTerm" : 4 } ], "ok" : 1, "$clusterTime " : { "clusterTime" : Timestamp(1697286312, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1697286312, 1) } shihanshuors:SECONDARY>
为啥不选举了?因为27017的票数,没有获得大多数,即没有大于等于2,它只有默认的一票(优先级是1)如果要触发选举,随便加入一个成员即可。
1)如果只加入27019仲裁节点成员,则主节点一定是27017,因为没得选了,仲裁节点不参与选举,但参与投票。(不演示) 2)如果只加入27018节点,会发起选举。因为27017和27018都是两票,则按照谁数据新,谁当主节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@Server01 ~]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 3838 child process started successfully, parent exiting [root@Server01 ~]# ps -ef | grep mongod root 3641 1 0 20:22 ? 00:00:05 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/mongod.conf root 3838 1 22 20:30 ? 00:00:00 mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf root 3910 2308 0 20:30 pts/0 00:00:00 grep --color=auto mongod [root@Server01 ~]# shihanshuors:SECONDARY> shihanshuors:PRIMARY> shihanshuors:PRIMARY> shihanshuors:PRIMARY> shihanshuors:SECONDARY>
4.仲裁节点和从节点故障 先关掉仲裁节点27019,再关掉现在的副本节点27018 10秒后,27017主节点自动降级为副本节点。(服务降级) 副本集不可写数据了,已经故障了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 shihanshuors:ARBITER> use admin switched to db admin shihanshuors:ARBITER> db.shutdownServer() 2022-10-16T18:50:11.394+0800 I NETWORK [js] DBClientConnection failed to receive message from 127.0.0.1:27019 - HostUnreachable: Connection closed by peer server should be down... 2022-10-16T18:50:11.397+0800 I NETWORK [js] trying reconnect to 127.0.0.1:27019 failed 2022-10-16T18:50:11.397+0800 I NETWORK [js] reconnect 127.0.0.1:27019 failed failed 2022-10-16T18:50:11.400+0800 I NETWORK [js] trying reconnect to 127.0.0.1:27019 failed 2022-10-16T18:50:11.400+0800 I NETWORK [js] reconnect 127.0.0.1:27019 failed failed > exit bye 2022-10-16T18:50:13.658+0800 I NETWORK [js] trying reconnect to 127.0.0.1:27019 failed 2022-10-16T18:50:13.658+0800 I NETWORK [js] reconnect 127.0.0.1:27019 failed failed 2022-10-16T18:50:13.659+0800 I QUERY [js] Failed to end session { id : UUID("7310bf73-7d1e-4ef2-9e58-b6969fb9e4b8" ) } due to SocketException: socket exception [CONNECT_ERROR] server [couldn't connect to server 127.0.0.1:27019, connection attempt failed: SocketException: Error connecting to 127.0.0.1:27019 :: caused by :: Connection refused] [root@localhost ~]# shihanshuors:SECONDARY> use admin switched to db admin shihanshuors:SECONDARY> db.shutdownServer() 2022-10-16T18:50:26.186+0800 I NETWORK [js] DBClientConnection failed to receive message from 127.0.0.1:27018 - HostUnreachable: Connection closed by peer server should be down... 2022-10-16T18:50:26.190+0800 I NETWORK [js] trying reconnect to 127.0.0.1:27018 failed 2022-10-16T18:50:26.191+0800 I NETWORK [js] reconnect 127.0.0.1:27018 failed failed 2022-10-16T18:50:26.193+0800 I NETWORK [js] trying reconnect to 127.0.0.1:27018 failed 2022-10-16T18:50:26.194+0800 I NETWORK [js] reconnect 127.0.0.1:27018 failed failed > exit bye 2022-10-16T18:50:27.624+0800 I NETWORK [js] trying reconnect to 127.0.0.1:27018 failed 2022-10-16T18:50:27.624+0800 I NETWORK [js] reconnect 127.0.0.1:27018 failed failed 2022-10-16T18:50:27.624+0800 I QUERY [js] Failed to end session { id: UUID("ebfe9c0a-93d0-45e3-82db-150c5c79a695") } due to SocketException: socket exception [CONNECT_ERROR] server [couldn' t connect to server 127.0.0.1:27018, connection attempt failed: SocketException: Error connecting to 127.0.0.1:27018 :: caused by :: Connection refused][root@localhost ~]#
心跳检测机制 副本集的心跳检测机制是通过副本集每个成员每两秒钟ping一次其它所有成员了解系统的健康状况,该机制发现故障后,会自动选举和故障转移,常见应用场景如下:
某个节点失去了响应,副本集就会采取相应的措施。这时副本集会判断失去响应的是主节点还是副本节点,如果是多个副本节点中的某一个副本节点,则副本集不做任何处理,只需要等待副本节点重新上线。如果是主节点挂掉了,则副本集会开始选举,选出新的主节点。
副本集中主节点突然失去了其它大多数节点的心跳,主节点会把自己降级为副本节点。这是为了防止网络原因让主节点和其它副本节点断开时,其它的副本节点中推举出了一个新的主节点,如此以来,一旦原来的主节点没有降级,那么网络恢复之后,副本集就会拥有两个主节点。如果客户端继续运行,就会对两个主节点都进行读写操作,导致副本集混乱。
停止服务的方式有两种:快速关闭和标准关闭 ,下面依次说明:
(一)快速关闭方法(快速,简单,数据可能会出错)
目标 :通过系统的kill命令直接杀死进程: 杀完要检查一下,避免有的没有杀掉。
kill -2 54410 #通过进程编号关闭节点
【补充】如果一旦是因为数据损坏,则需要进行如下操作(了解): 1)删除lock文件:rm -rf /mongodb/single/data/db/*.lock
2 )修复数据:/usr/local/mongdb/bin/mongod --repair --dbpath=/mongodb/single/data/db
(二)标准的关闭方法(数据不容易出错,但麻烦):
目标:通过mongo客户端中的shutdownServer命令来关闭服务 主要的操作步骤参考如下:
//客户端登录服务,注意,这里通过localhost登录,如果需要远程登录,必须先登录认证才行。mongo --port 27017
//#切换到admin库use admin
//关闭服务db.shutdownServer()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 > use admin switched to db admin > db admin > db.shutdownServer() 2022-10-12T18:29:41.739+0800 I NETWORK [js] DBClientConnection failed to receive message from 127.0.0.1:27017 - HostUnreachable: Connection closed by peer server should be down... 2022-10-12T18:29:41.743+0800 I NETWORK [js] trying reconnect to 127.0.0.1:27017 failed 2022-10-12T18:29:41.743+0800 I NETWORK [js] reconnect 127.0.0.1:27017 failed failed > exit bye 2022-10-12T18:29:45.252+0800 I NETWORK [js] trying reconnect to 127.0.0.1:27017 failed 2022-10-12T18:29:45.252+0800 I NETWORK [js] reconnect 127.0.0.1:27017 failed failed 2022-10-12T18:29:45.252+0800 I QUERY [js] Failed to end session { id : UUID("e0e0b382-53c9-43e6-ac4a-ec1c0babfdf4" ) } due to SocketException: socket exception [CONNECT_ERROR] server [couldn't connect to server 127.0.0.1:27017, connection attempt failed: SocketException: Error connecting to 127.0.0.1:27017 :: caused by :: Connection refused] [root@localhost ~]# ps -ef | grep mongod root 10774 10300 0 18:29 pts/1 00:00:00 grep --color=auto mongod
安全认证 默认情况下部署的MongoDB副本集不会开启安全认证功能,这样会对副本集的安全带来一定影响,任何人都可以操作副本集,这在生产环境中是不允许发生的。MongoDB 副本集之间通信有两种安全认证机制,一种是通过KeyFile,另外一种是通过证书x.509 ,官网推荐使用证书的方式,不过我们这里搭建测试和开发环境没必要去弄证书,因此我们直接通过配置KeyFile就可以实现安全通信,不过在生产环境中推荐使用证书x.509。
KeyFile是MongoDB副本集安全认证的一种形式,该形式是通过一个密钥文件使副本集中各服务器进行内部通信使用,当作副本集内部的密码,这个密钥文件基本上是一个明文的文件,副本集中每个成员的密钥文件内容须保持一致。
密钥文件的使用需要注意一下几点:
内容至少包含六个字符,文件的大小不能超过1024字节;
文件中的空白字符在认证过程没有实际意义;
文件编码为base64,但不能包含等于号;
密钥文件权限一定要等于或小于 600(rw只有拥有者有读写权限),否则会报权限太高的错误;
MongoDB副本集中的KeyFile安全认证可以理解为MongoDB单机模式下的auth认证功能,开启KeyFile安全认证,就不需要再使用auth认证(隐含就是开启了auth),这个时候登录MongoDB副本集的客户端就需要用户名和密码进行认证。KeyFile认证不是必选项,不过副本集中一个成员开启了KeyFile认证的情况下,其它成员也必须开启KeyFile认证,否则将不会加入该副本集。
在副本集中开启KeyFile安全认证功能 1、创建用于存放KeyFile文件的目录。
1 2 3 [root@localhost ~]# mkdir -p /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key [root@localhost ~]# mkdir -p /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/key [root@localhost ~]# mkdir -p /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/key
2、在/opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key目录下新建KeyFile文件并命名为keyfile。
1 2 3 4 5 6 7 8 9 10 11 [root@localhost ~]# touch /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/keyfile [root@localhost ~]# ll /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/ 总用量 4 drwxr-xr-x 3 root root 16 3月 27 2022 data drwxr-xr-x 2 root root 21 10月 22 22:25 key drwxr-xr-x 2 root root 45 3月 27 2022 logs -rw-r--r-- 1 root root 1486 3月 27 2022 mongod.conf [root@localhost ~]# ll /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/ 总用量 0 -rw-r--r-- 1 root root 0 10月 22 22:25 keyfile [root@localhost ~]#
3、通过Linux系统提供的密码工具集 openssl生成符合KeyFile文件标准的密钥并写入。
1 [root@Server01 ~]# openssl rand -out /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/keyfile -base64 756
4、查看密钥是否成功写入KeyFile文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@Server01 ~]# cat /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/keyfile CttwWzkCdt6BcgDG3xrc+B77hjOvG/kgnuohSfUGQArKRvtxiKHWpuRso5cVIKG2 LyI76Rvl+NE2NfUgOnMCMe86ID4ML6eVRZ/Rz8VsgckEo/v5uXCTLlRRHxWTScaX y+lX3S8FH2Zv3ecZi81/TTT2Wj6DS4MWnINx4MtEhwMp1lSIrtQ0pFjOn1pUUj5P 6wIDs65RFzSwIeNCr29s7ik9P0npN046FU8AOpapt9lh7wGQRctN6TsAqj+QtH7s HVs/rQtds1xBLW+Iwkw0cEl98RflrZanaWGLGjQgA/hkFyPUJtBASIJnna2uTfNe s6MBokQYRJv1eB8Iawe7sDNhAAmmfGh1y0p2p8UHYvuSHgRG7iqAdUKCXWQ4YIDC yT9PU3kFh0g4If+zGVayYRm6QPYtkHjWL3QKVSzOQziS7EjMeNpHHv59RCLLzMFQ L+Cehv+V83XiVKphb2YawTv3ik/xj/M8JUkfq82ugSgh/gRQmB5bqvobeV8fpDr/ wXMyYXcQU95HmfJEzjoMZZStCl4Uyfoyf9KPAR6VYj0zJVuhh2ym+UWG31iH8mll +iANEJ9gnYev9cVRX+vDhrKcqJyNcpKnDCVfkx4qZu1xNYUhm4Fg+AbUvCFJDWrW E4tMPEkqgeimGSJc0C5w8AnglqMiRGZzI8QtW568feKW7OdsoIDxOwy+DP7izZN2 LYlqtIp25qh6QWgN+XMDsttfl4ssKgY3udcxOCZhocQjt1NTRNXZVY/NL2MMaihU xebfHz8bQ4qdBFWk3u9XCwI683A9crbg8X2/+UUQXFuDadtYK48bSelAJ9YNhggo g+EqcE9TZTqgFx6DDmRLWTkxeNbqj73splZhF90Do2jFBd8J9qYtzTlbGBQ814Ef 33EjBJ19KvmAocc0ZAOlIXqjox/cMLLKVlec869OuhTQxAEtpEHdqOfxFURwqqIn jYCiYQURWp+J/Z9GJYMpGF6D1r6YZ8RrIHHwB62LsqtgxffU [root@Server01 ~]#
5、修改KeyFile文件权限为600,即只有当前用户拥有可读写权限。如不操作此步后续会因为KeyFile文件默认权限过大,无法启动安全认证的MongDB副本集。
1 2 3 4 5 6 [root@Server01 ~]# ll /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/keyfile -rw-r--r-- 1 root root 1024 10月 18 19:27 /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/keyfile [root@Server01 ~]# chmod 600 /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/keyfile [root@Server01 ~]# ll /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/keyfile -rw------- 1 root root 1024 10月 18 19:27 /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/keyfile [root@Server01 ~]#
6、为了保证副本集中各节点的KeyFile文件保持一致,需要将KeyFile文件(keyfile)拷贝到其它节点。
1 2 3 4 5 6 7 [root@localhost ~]# cp -r /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/keyfile /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/key/keyfile [root@localhost ~]# cp -r /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/keyfile /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/key/keyfile [root@localhost ~]# ll /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/key/keyfile -rw------- 1 root root 1024 10月 22 22:45 /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/key/keyfile [root@localhost ~]# ll /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/key/keyfile -rw------- 1 root root 1024 10月 22 22:45 /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/key/keyfile [root@localhost ~]#
7、开启安全认证后在不指定用户登录MongoDB客户端时,默认情况下我们是以访客身份登录没有任何操作的权限,也无法创建用户,这会导致开启了安全认证的副本集无法正常使用。因此,需要在没有开启安全认证的MongoDB副本集中添加全局管理用户。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 shihanshuors:PRIMARY> use admin switched to db admin shihanshuors:PRIMARY> db.createUser({user:"itcastAdmin" ,pwd :"123456" ,roles: [{role:"userAdminAnyDatabase" ,db:"admin" },{role:"readWriteAnyDatabase" , db:"admin" },{role:"dbAdminAnyDatabase" ,db:"admin" }]}) // - Run Shell Queries via Studio 3T for full access to query results // -------------------------------------------------------------------------- MongoDB shell version v4.2.14 Successfully added user: { "user" : "itcastAdmin" , "roles" : [ { "role" : "userAdminAnyDatabase" , "db" : "admin" }, { "role" : "readWriteAnyDatabase" , "db" : "admin" }, { "role" : "dbAdminAnyDatabase" , "db" : "admin" } ] }
8、验证用户是否创建成功。
1 shihanshuors:PRIMARY> db.auth("itcastAdmin" ,"123456" )
9、关闭副本集,即三台服务器的MongoDB服务(先副后主)。重新以安全认证模式启动副本集,分别编辑几个服务的mongod.conf文件修改配置文件指定keyfile。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 security: keyFile: /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/key/keyfile authorization: enabled ------------------------------------------------------------------ security: keyFile: /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/key/keyfile authorization: enabled ------------------------------------------------------------------ security: keyFile: /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/key/keyfile authorization: enabled
10、在服务器27017中MongoDB的目录下启动MongoDB服务。
1 2 3 4 [root@Server01 ~]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 4499 child process started successfully, parent exiting
11、在服务器27018中MongoDB的目录下启动MongoDB服务。
1 2 3 4 [root@Server01 ~]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 4569 child process started successfully, parent exiting
12、在服务器27019中MongoDB的目录下启动MongoDB服务。
1 2 3 4 [root@Server01 ~]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 4648 child process started successfully, parent exiting
验证安全认证是否成功启动 1、在服务器27017中MongoDB的目录下不指定用户登录MongoDB客户端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 [root@Server01 ~]# mongo --port=27017 MongoDB shell version v4.4.24 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("2d5d3792-c056-4408-9fc0-3334f2f513a1" ) } MongoDB server version: 4.4.24 shihanshuors:PRIMARY> shihanshuors:PRIMARY> use test shihanshuors:PRIMARY> db test shihanshuors:PRIMARY> db.user.find() Error: error: { "operationTime" : Timestamp(1697633203, 1), "ok" : 0, "errmsg" : "command find requires authentication" , "code" : 13, "codeName" : "Unauthorized" , "$clusterTime " : { "clusterTime" : Timestamp(1697633203, 1), "signature" : { "hash" : BinData(0,"Z41N4hnWgDlBQuTj9X9gKtTz7Nc=" ), "keyId" : NumberLong("7287562673762336773" ) } } } shihanshuors:PRIMARY> db.user.insert({"name" :"heima" }) WriteCommandError({ "operationTime" : Timestamp(1697633283, 1), "ok" : 0, "errmsg" : "command insert requires authentication" , "code" : 13, "codeName" : "Unauthorized" , "$clusterTime " : { "clusterTime" : Timestamp(1697633283, 1), "signature" : { "hash" : BinData(0,"bq2wHWqy5YuueLVW3gafs7DQ288=" ), "keyId" : NumberLong("7287562673762336773" ) } } }) shihanshuors:PRIMARY>
当我们不指定用户登录时,执行读入和写入操作就会出现类似“command XXXX requires authentication”的错误信息
2、切换到数据库admin,在该数据库下通过全局管理用户itcastAdmin进行身份验证,再次执行查看集合user中的文档并插入一条新的文档。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 shihanshuors:PRIMARY> use admin switched to db admin shihanshuors:PRIMARY> db admin shihanshuors:PRIMARY> db.auth("itcastAdmin" ,"12345" ) Error: Authentication failed. 0 shihanshuors:PRIMARY> db.auth("itcastAdmin" ,"123456" ) 1 shihanshuors:PRIMARY> use test switched to db test shihanshuors:PRIMARY> db.user.find() shihanshuors:PRIMARY> db.user.insert({"name" :"heima" }) WriteResult({ "nInserted" : 1 }) shihanshuors:PRIMARY> db.user.find () { "_id" : ObjectId("652fd56687384c473596440a" ), "name" : "heima" } shihanshuors:PRIMARY>
执行上述操作时,可以看出全局管理用户itcastAdmin进行身份验证后,可以正常对集合进行读取和写入操作。
3、开启安全认证后,副本集操作需要切换到具有root权限的用户去配置副本集,添加root权限用户命令如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 [root@Server01 ~]# mongo --port=27017 MongoDB shell version v4.4.24 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("4b281950-459c-4d58-bd76-4a2e1b5ad238" ) } MongoDB server version: 4.4.24 shihanshuors:PRIMARY> use admin switched to db admin shihanshuors:PRIMARY> db.auth("itcastAdmin" ,"123456" ) 1 shihanshuors:PRIMARY> db.createUser({user:"admin" ,pwd :"123456" ,roles:[{role:"root" ,db:"admin" }]}) Successfully added user: { "user" : "admin" , "roles" : [ { "role" : "root" , "db" : "admin" } ] } shihanshuors:PRIMARY> db.auth("admin" ,"123456" ) 1 shihanshuors:PRIMARY>
十三、MongoDB分片 分片概述 副本集的特点,不管我搭载多少个副本节点, 它存储的数据都是一样的。存储的数据一样就会带来一个问题了,数据只能存在一台服务器上面 。那完整的数据随着业务量非常大的时候,就会发生一台服务器已经存不下的情况,我们怎么办 ?
那我们就得用分片集群 的方式来解决问题。
分片(sharding)是一种跨多台机器分布数据的方法 , MongoDB使用分片来支持具有非常大的数据集 和高吞吐量操作 的部署。换句话说:分片(sharding)是指将数据拆分,将其分散存在不同的机器上的过程。有时也用分区(partitioning)来表示这个概念。将数据分散到不同的机器上,不需要功能强大的大型计算机就可以储存更多的数据,处理更多的负载。
分片与副本集主要区别在于,分片 是每个节点存储数据的不同片段,而副本集 是每个节点存储数据的相同副本。
所有数据库都可以进行手动分片(Manual Sharding) ,因此,分片并不是MongoDB特有的 。不同类型的数据均可以通过人为操作被分配到不同的数据库服务器上,然而,人工分片是需要编写相关代码来实现分片功能 ,并且还不容易维护(如集群中节点发生变动的情况)。MongoDB数据库可以实现自动分片,它内置了多种分片逻辑 ,使得MongoDB可以自动处理分片上数据的分布,也可以很容易的管理分片集群。
由于数据量太大,导致本地磁盘不足以存储的情况;
为了提高数据库性能,从而将海量数据存储在内存中,导致单个MongoDB数据库内存不足的情况;
若是出现数据请求量太大,导致单MongoDB机器不能满足读写数据的性能情况。
若是出现这三种情况,我们就可以使用MongoDB的分片技术来解决。
具有大型数据集或高吞吐量应用程序的数据库系统可以会挑战单个服务器的容量。例如,高查询率会耗尽服务器的CPU容量。工作集大小大于系统的RAM会强调磁盘驱动器的I / O容量。
有两种解决系统增长的方法:垂直扩展和水平扩展 。
垂直扩展意味着增加单个服务器的容量 ,例如使用更强大的CPU,添加更多RAM或增加存储空间量。可用技术的局限性可能会限制单个机器对于给定工作负载而言足够强大。此外,基于云的提供商基于可用的硬件配置具有硬性上限。结果,垂直缩放有实际的最大值。
水平扩展意味着划分系统数据集并加载多个服务器 ,添加其他服务器以根据需要增加容量。虽然单个机器的总体速度或容量可能不高,但每台机器处理整个工作负载的子集,可能提供比单个高速大容量服务器更高的效率。扩展部署容量只需要根据需要添加额外的服务器,这可能比单个机器的高端硬件的总体成本更低。权衡是基础架构和部署维护的复杂性增加。
MongoDB支持通过分片进行水平扩展。
分片策略 MongoDB之所以能够实现自动分片,这是因为其内置了分片策略。MongoDB通过分片键(Shard Key)将集合中的数据划分为多个块(Chunk)(默认大小为64MB,每个块均表示集合中数据的一部分),然后MongoDB根据分片策略将划分的块分发到分片集群中。需要注意,分片键可以是集合文档中的一个或多个字段。
MongoDB的分片策略主要包括范围分片 和哈希分片 两种,介绍如下:
范围分片
MongoDB根据分片键的值范围将数据划分为不同块,每个分片都包含了分片键在一定范围内的数据 。这样的话,若有文档写入时,MongoDB会根据该文档的分片键,从而交由指定分片服务器去处理。下面,通过一张图来介绍范围分片策略,具体如图所示。
从图中可以看出,
若文档分片键的值范围在[minKey,10)中,则该文档需要交由分片服务器A进行相关处理;
若文档分片键的值范围在[10,20)中,则该文档需要交由分片服务器B进行相关处理;
若文档分片键的值范围在[20,maxKey)中,则该文档需要交由分片服务器C进行相关处理。
使用基于范围分片时,拥有相近分片键 的文档会存储在同一个分片服务器中,从而提升范围查询的效率。但是,当插入批量文档时,分片键集中在一定范围内,就会导致数据分布不均匀,从而导致其中一个分片服务器负载过重。
哈希分片
哈希分片类似于范围分片,两者的区别在于范围分片是MongoDB根据分片键的值 直接进行范围划分,而哈希分片则先将分片键的值进行哈希计算后,然后对这些哈希值进行范围划分 ,从而使得每个分片都包含了哈希值在一定范围内的数据;范围分片可以支持复合分片键,而哈希分片只支持单个字段 作为分片键。哈希值的随机性,使得数据随机分布在分片集群中不同分片服务器上。下面,通过一张图介绍哈希分片策略,如图所示。
从图中可以看出,若文档分片键的哈希值为5,则该文档需要交由分片服务器A进行相关处理;若文档分片键的哈希值为12,则该文档需要交由分片服务器B进行相关处理;若文档分片键的哈希值为23,则该文档需要交由分片服务器C进行相关处理。 使用基于哈希分片时,拥有“相近”分片键的文档不会存储在同一个分片服务器中,这样的话,数据的分离性会更好,可以保证分片集群中数据分布均衡。但是,由于数据是通过哈希计算进行随机存放的,因此会降低查询性能。
注意:
分片键
(1)分片键一旦指定,后续则无法改变,并且只能拥有一个分片键。
(2)不允许在已分片的集合文档上插入没有分片键的文档。
(3)分片键的长度大小,不可超过512个字节。
(4)用于作分片键的字段必须创建索引,索引可以是分片键开头的复合索引。
块(chunk)大小
(1)小块可以均匀地分布数据,但会导致迁移很频繁,这样会增大路由服务器的开销。
(2)大块触发的迁移较少,但会导致数据分布不均匀。
(3)块的大小会影响要迁移块的最大文档数。
(4) 块的分片键值范围是(-∞,+∞),其中﹣0∞表示最小值(minKey),+∞表示最大值(maxKey)。
分片集群架构 在MongoDB分片集群中,只有各组件间的协同工作,才可使得分片集群正常运行。在学习分片集群的操作之前,有必要先来学习一下分片集群架构。下面,通过一张图来介绍分片集群架构,具体如图所示。
从图中可以看出,分片集群中主要由三个部分组成,即分片服务器(Shard)、路由服务器(Mongos)以及配置服务器(Config Server)组成 。其中,分片服务器有三个,即Shard1、Shard2、Shard3;路由服务器有两个,即Mongos1和Mongos2;配置服务器有三个,即主、副、副。下面,我们针对分片集群架构中的组成部分进行详细介绍,具体如下:
即MongoDB实例(即mongod,用Shard表示),分片服务器是实际存储数据的组件 ,持有完整数据集中的一部分,每个分片服务器都可以是一个MongoDB实例 ,也可是一组MongoDB实例组成的集群(副本集) 。从MongoDB 3.6开始,必须将分片部署为副本集,这样具有更好的容错性。
即mongos,路由服务器主要提供客户端应用程序与分片集群交互的接口,所有请求都需要通过路由服务器进行协调工作 。路由服务器实际上就是一个消息分发请求中心 ,它负责把客户端应用程序对应的数据请求转发到对应的分片服务器上。应用程序将查询、存储、更新等请求原封不动地发送给路由服务器。路由服务器询问配置服务器操作分片服务器需要获取哪些元数据,然后连接相应的分片服务器进行相关操作,最后将各个分片服务器的响应进行合并,返回给客户端应用程序。 生产环境中,一个分片集群通常会有多个 路由服务器,一方面可以解决多个客户端同时请求,从而达到负载均衡的效果;另一方面可以解决当路由服务器宕机时导致整个分片集群无法使用的问题。
即Config Server。在生产环境中,通常需要多个配置服务器,因为它存储了分片集群的元数据,并且这些数据是不允许丢失的 。因此,需要配置多个配置服务器以防止数据丢失,尽管其中一台分片服务器宕机,我们还有其它配置服务器,从而保证MongoDB分片集群依然能够正常工作。从MongoDB 3.4版本开始,配置服务器必须部署副本集,因此我们需要配置三个配置服务器组成的副本集。配置服务器存储着分片集群的持久化元数据 ,而路由服务器存储着分片集群的非持久化元数据 ,这些数据均为内存缓存的数据 。当路由服务器初次启动或关闭重启时,就会从配置服务器中加载分片集群的元数据。若是配置服务器的信息发生变化,则会通知所有路由服务器更新自己的状态,这样路由服务器就能继续准确的协调客户端与分片集群的交互工作。
部署分片集群 MongoDB分片群集包含以下组件:
分片(存储):每个分片包含分片数据的子集。 每个分片都可以部署为副本集。
mongos(路由):mongos充当查询路由器,在客户端应用程序和分片集群之间提供接口。
confifig servers(“调度”的配置):配置服务器存储群集的元数据和配置设置(即哪个分片存放哪个数据)。 从MongoDB 3.4开始,必须将配置服务器部署为副本集(CSRS)。
下图描述了分片集群中组件的交互:
两个分片节点副本集(3+3)+一个配置节点副本集(3)+两个路由节点(2),共11个服务节点。
2个路由是为了容灾,一个路由挂了之后,我另一个路由 还能用。但2个路由之间是相互独立的。
分片中有仲裁就是为了节省成本。而配置服务中只是为了存储配置信息,它的数据量不大。
所有的的配置文件都直接放到 sharded_cluster
的相应的子目录下面,默认配置文件名字:mongod.conf
在搭建服务架构之前,一定要确保系统是干净的可以使用 ps -ef
命令,查看是否又mongod相关的服务,有的话就把他们的进程 kill
掉,以此来确保你的系统中mongod的端口不被占用。
分片(存储)节点副本集的创建 1.第一套副本集 1 2 3 4 5 6 mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/log \ & mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/data/dbmkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/log \ & mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/data/dbmkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/log \ & mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/data/db
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/ 总用量 0 drwxr-xr-x 4 root root 29 10月 21 19:34 shihanshuoshardrs01_27018 drwxr-xr-x 4 root root 29 10月 21 19:34 shihanshuoshardrs01_27118 drwxr-xr-x 4 root root 29 10月 21 19:34 shihanshuoshardrs01_27218 [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/ 总用量 0 drwxr-xr-x 3 root root 16 10月 21 19:34 data drwxr-xr-x 2 root root 6 10月 21 19:34 log [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/ 总用量 0 drwxr-xr-x 3 root root 16 10月 21 19:34 data drwxr-xr-x 2 root root 6 10月 21 19:34 log [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/ 总用量 0 drwxr-xr-x 3 root root 16 10月 21 19:34 data drwxr-xr-x 2 root root 6 10月 21 19:34 log [root@localhost mongodb]#
27018的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 vi /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/log/mongod.log" logAppend: true storage: dbPath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/log/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27018 replication: replSetName: shihanshuoshardrs01 sharding: clusterRole: shardsvr
注意: 设置sharding.clusterRole需要mongod实例运行复制。 要将实例部署为副本集成员,请使用replSetName设置并指定副本集的名称。
27118的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 vi /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/log/mongod.log" logAppend: true storage: dbPath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/log/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27118 replication: replSetName: shihanshuoshardrs01 sharding: clusterRole: shardsvr
27218的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 vi /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/log/mongod.log" logAppend: true storage: dbPath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/log/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27218 replication: replSetName: shihanshuoshardrs01 sharding: clusterRole: shardsvr
启动第一套副本集 启动第一套副本集:一主一副本一仲裁 依次启动三个mongod服务,并查看服务是否启动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 7835 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 7884 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 7934 child process started successfully, parent exiting [root@localhost ~]# ps -ef | grep mongod root 7835 1 8 22:51 ? 00:00:02 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf root 7884 1 12 22:51 ? 00:00:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/mongod.conf root 7934 1 19 22:51 ? 00:00:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/mongod.conf root 7977 7599 0 22:51 pts/0 00:00:00 grep --color=auto mongod [root@localhost ~]#
初始化第一套副本集 (1)初始化副本集和创建主节点:使用客户端命令连接任意一个节点,但这里尽量要连接主节点:mongo --host=192.168.24.105 --port=27018
执行初始化副本集命令:rs.initiate()
查看副本集情况:rs.status()
(2)主节点配置查看:rs.conf()
(3)添加副本节点:rs.add("192.168.24.105:27118")
(4)添加仲裁节点:rs.addArb("192.168.24.105:27218")
查看副本集的配置情况:rs.status()
代码过程如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 [root@localhost ~]# mongo --host=192.168.24.105 --port=27018 MongoDB shell version v4.2.18 connecting to: mongodb://192.168.24.105:27018/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("f5e3d71c-235d-445e-8438-22ee42c3dd67" ) } MongoDB server version: 4.2.18 Server has startup warnings: 2022-04-02T22:51:26.943+0800 I CONTROL [initandlisten] 2022-04-02T22:51:26.943+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2022-04-02T22:51:26.943+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2022-04-02T22:51:26.943+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2022-04-02T22:51:26.943+0800 I CONTROL [initandlisten] 2022-04-02T22:51:26.943+0800 I CONTROL [initandlisten] 2022-04-02T22:51:26.943+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . 2022-04-02T22:51:26.943+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-04-02T22:51:26.943+0800 I CONTROL [initandlisten] 2022-04-02T22:51:26.944+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always' . 2022-04-02T22:51:26.944+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-04-02T22:51:26.944+0800 I CONTROL [initandlisten] --- Enable MongoDB's free cloud-based monitoring service, which will then receive and display metrics about your deployment (disk utilization, CPU, operation statistics, etc). The monitoring data will be available on a MongoDB website with a unique URL accessible to you and anyone you share the URL with. MongoDB may use this information to make product improvements and to suggest MongoDB products and deployment options to you. To enable free monitoring, run the following command: db.enableFreeMonitoring() To permanently disable this reminder, run the following command: db.disableFreeMonitoring() --- > rs.initiate() { "info2" : "no configuration specified. Using a default configuration for the set", "me" : "192.168.24.105:27018", "ok" : 1 } shihanshuoshardrs01:SECONDARY> shihanshuoshardrs01:PRIMARY> shihanshuoshardrs01:PRIMARY> rs.add("192.168.24.105:27118") { "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(1648912062, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1648912062, 1) } shihanshuoshardrs01:PRIMARY> rs.addArb("192.168.24.105:27218") { "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(1648912077, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1648912077, 1) } shihanshuoshardrs01:PRIMARY> rs.status() { "set" : "shihanshuoshardrs01", "date" : ISODate("2022-04-02T15:08:12.233Z"), "myState" : 1, "term" : NumberLong(1), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "heartbeatIntervalMillis" : NumberLong(2000), "majorityVoteCount" : 2, "writeMajorityCount" : 2, "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1648912091, 1), "t" : NumberLong(1) }, "lastCommittedWallTime" : ISODate("2022-04-02T15:08:11.986Z"), "readConcernMajorityOpTime" : { "ts" : Timestamp(1648912091, 1), "t" : NumberLong(1) }, "readConcernMajorityWallTime" : ISODate("2022-04-02T15:08:11.986Z"), "appliedOpTime" : { "ts" : Timestamp(1648912091, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1648912091, 1), "t" : NumberLong(1) }, "lastAppliedWallTime" : ISODate("2022-04-02T15:08:11.986Z"), "lastDurableWallTime" : ISODate("2022-04-02T15:08:11.986Z") }, "lastStableRecoveryTimestamp" : Timestamp(1648912091, 1), "lastStableCheckpointTimestamp" : Timestamp(1648912091, 1), "electionCandidateMetrics" : { "lastElectionReason" : "electionTimeout", "lastElectionDate" : ISODate("2022-04-02T15:07:11.929Z"), "electionTerm" : NumberLong(1), "lastCommittedOpTimeAtElection" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "lastSeenOpTimeAtElection" : { "ts" : Timestamp(1648912031, 1), "t" : NumberLong(-1) }, "numVotesNeeded" : 1, "priorityAtElection" : 1, "electionTimeoutMillis" : NumberLong(10000), "newTermStartDate" : ISODate("2022-04-02T15:07:11.973Z"), "wMajorityWriteAvailabilityDate" : ISODate("2022-04-02T15:07:12.031Z") }, "members" : [ { "_id" : 0, "name" : "192.168.24.105:27018", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1007, "optime" : { "ts" : Timestamp(1648912091, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2022-04-02T15:08:11Z"), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "could not find member to sync from", "electionTime" : Timestamp(1648912031, 2), "electionDate" : ISODate("2022-04-02T15:07:11Z"), "configVersion" : 3, "self" : true, "lastHeartbeatMessage" : "" }, { "_id" : 1, "name" : "192.168.24.105:27118", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 30, "optime" : { "ts" : Timestamp(1648912077, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1648912077, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2022-04-02T15:07:57Z"), "optimeDurableDate" : ISODate("2022-04-02T15:07:57Z"), "lastHeartbeat" : ISODate("2022-04-02T15:08:11.104Z"), "lastHeartbeatRecv" : ISODate("2022-04-02T15:08:10.653Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "192.168.24.105:27018", "syncSourceHost" : "192.168.24.105:27018", "syncSourceId" : 0, "infoMessage" : "", "configVersion" : 3 }, { "_id" : 2, "name" : "192.168.24.105:27218", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 15, "lastHeartbeat" : ISODate("2022-04-02T15:08:11.104Z"), "lastHeartbeatRecv" : ISODate("2022-04-02T15:08:11.151Z"), "pingMs" : NumberLong(1), "lastHeartbeatMessage" : "", "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "", "configVersion" : 3 } ], "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(1648912091, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1648912091, 1) } shihanshuoshardrs01:PRIMARY> exit bye [root@localhost ~]#
字段解释:
name是副本集节点的ip和端口信息
health表示副本集中该节点是否正常,0表示不正常,1表示正常
state表示节点的身份,0表示非主节点,1表示主节点
stateStr用于对节点身份进行字符描述,PRIMARY表示主节点,SECONDARY表示副节点
uptime 从成员可到达一直到现在经历的时间,单位是秒。
optimeDate 每个成员oplog最后一次操作发生的时间,这个时间是心跳报上来的,因此可能会存在延迟
lastHeartbeat 当前服务器最后一次收到其他成员心跳的时间,如果网络故障等可能这个时间会大于2秒
pinMs 心跳从当前服务器达到某个成员所花费的平均时间
syncingTo 当前服务器从哪个节点在做同步
self 这个信息出现在执行rs.status()函数的成员信息中
errmsg 成员在心跳请求中返回的状态信息,通过是一些状态信息,不全是错误信息。
health表示服务器是否可达,可达是1,不可达是0 optime与optimeDate表达的信息也是一样的,只是表示的方式不同,一个是用新纪元开始的毫秒数表示的,一个是用一种更容易阅读的方式表示。 由于rs.status()是从执行命令成员本身的角度得出的,由于网路等故障,这份报告可能不准确或者有些过时。
2.第二套副本集 所有的的配置文件都直接放到 sharded_cluster 的相应的子目录下面,默认配置文件名字:mongod.conf
1 2 3 4 5 6 mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27318/log \ & mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27318/data/dbmkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27418/log \ & mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27418/data/dbmkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27518/log \ & mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27518/data/db
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/ 总用量 0 drwxr-xr-x 4 root root 48 10月 21 19:36 shihanshuoshardrs01_27018 drwxr-xr-x 4 root root 48 10月 21 19:40 shihanshuoshardrs01_27118 drwxr-xr-x 4 root root 48 10月 21 19:40 shihanshuoshardrs01_27218 drwxr-xr-x 4 root root 29 10月 21 19:41 shihanshuoshardrs02_27318 drwxr-xr-x 4 root root 29 10月 21 19:41 shihanshuoshardrs02_27418 drwxr-xr-x 4 root root 29 10月 21 19:41 shihanshuoshardrs02_27518 [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27318/ 总用量 0 drwxr-xr-x 3 root root 16 10月 21 19:41 data drwxr-xr-x 2 root root 6 10月 21 19:41 log [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27418/ 总用量 0 drwxr-xr-x 3 root root 16 10月 21 19:41 data drwxr-xr-x 2 root root 6 10月 21 19:41 log [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27518/ 总用量 0 drwxr-xr-x 3 root root 16 10月 21 19:41 data drwxr-xr-x 2 root root 6 10月 21 19:41 log [root@localhost mongodb]#
27318的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 vi /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27318/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27318/log/mongod.log" logAppend: true storage: dbPath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27318/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27318/log/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27318 replication: replSetName: shihanshuoshardrs02 sharding: clusterRole: shardsvr
27418的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 vi /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27418/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27418/log/mongod.log" logAppend: true storage: dbPath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27418/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27418/log/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27418 replication: replSetName: shihanshuoshardrs02 sharding: clusterRole: shardsvr
27518的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 vi /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27518/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27518/log/mongod.log" logAppend: true storage: dbPath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27518/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27518/log/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27518 replication: replSetName: shihanshuoshardrs02 sharding: clusterRole: shardsvr
启动第二套副本集 依次启动三个mongod服务,并查看服务是否启动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27318/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8466 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27418/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8508 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27518/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8551 child process started successfully, parent exiting [root@localhost ~]# ps -ef | grep mongod root 7835 1 1 22:51 ? 00:00:06 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf root 7884 1 1 22:51 ? 00:00:06 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/mongod.conf root 7934 1 1 22:51 ? 00:00:05 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/mongod.conf root 8466 1 7 22:59 ? 00:00:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27318/mongod.conf root 8508 1 12 22:59 ? 00:00:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27418/mongod.conf root 8551 1 25 22:59 ? 00:00:02 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27518/mongod.conf root 8593 7599 0 22:59 pts/0 00:00:00 grep --color=auto mongod [root@localhost ~]#
初始化第二套副本集 (1)初始化副本集和创建主节点:使用客户端命令连接任意一个节点,但这里尽量要连接主节点:mongo --host=192.168.24.105 --port=27318
执行初始化副本集命令:rs.initiate()
查看副本集情况:rs.status()
(2)主节点配置查看:rs.conf()
(3)添加副本节点:rs.add("192.168.24.105:27418")
(4)添加仲裁节点:rs.addArb("192.168.24.105:27518")
查看副本集的配置情况:rs.status()
代码过程如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 [root@localhost ~]# mongo --host=192.168.24.105 --port=27318 MongoDB shell version v4.2.18 connecting to: mongodb://192.168.24.105:27318/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("1a927c47-bd43-47ad-8ed0-f98b2107e631" ) } MongoDB server version: 4.2.18 Server has startup warnings: 2022-04-02T22:59:38.644+0800 I CONTROL [initandlisten] 2022-04-02T22:59:38.644+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2022-04-02T22:59:38.644+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2022-04-02T22:59:38.644+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2022-04-02T22:59:38.644+0800 I CONTROL [initandlisten] 2022-04-02T22:59:38.644+0800 I CONTROL [initandlisten] 2022-04-02T22:59:38.645+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . 2022-04-02T22:59:38.645+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-04-02T22:59:38.645+0800 I CONTROL [initandlisten] 2022-04-02T22:59:38.645+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always' . 2022-04-02T22:59:38.645+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-04-02T22:59:38.645+0800 I CONTROL [initandlisten] --- Enable MongoDB's free cloud-based monitoring service, which will then receive and display metrics about your deployment (disk utilization, CPU, operation statistics, etc). The monitoring data will be available on a MongoDB website with a unique URL accessible to you and anyone you share the URL with. MongoDB may use this information to make product improvements and to suggest MongoDB products and deployment options to you. To enable free monitoring, run the following command: db.enableFreeMonitoring() To permanently disable this reminder, run the following command: db.disableFreeMonitoring() --- > rs.initiate() { "info2" : "no configuration specified. Using a default configuration for the set", "me" : "192.168.24.105:27318", "ok" : 1 } shihanshuoshardrs02:SECONDARY> shihanshuoshardrs02:PRIMARY> rs.add("192.168.24.105:27418") { "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(1648912357, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1648912357, 1) } shihanshuoshardrs02:PRIMARY> rs.addArb("192.168.24.105:27518") { "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(1648912368, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1648912368, 1) } shihanshuoshardrs02:PRIMARY> rs.status() { "set" : "shihanshuoshardrs02", "date" : ISODate("2022-04-02T15:13:00.198Z"), "myState" : 1, "term" : NumberLong(1), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "heartbeatIntervalMillis" : NumberLong(2000), "majorityVoteCount" : 2, "writeMajorityCount" : 2, "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1648912368, 1), "t" : NumberLong(1) }, "lastCommittedWallTime" : ISODate("2022-04-02T15:12:48.688Z"), "readConcernMajorityOpTime" : { "ts" : Timestamp(1648912368, 1), "t" : NumberLong(1) }, "readConcernMajorityWallTime" : ISODate("2022-04-02T15:12:48.688Z"), "appliedOpTime" : { "ts" : Timestamp(1648912368, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1648912368, 1), "t" : NumberLong(1) }, "lastAppliedWallTime" : ISODate("2022-04-02T15:12:48.688Z"), "lastDurableWallTime" : ISODate("2022-04-02T15:12:48.688Z") }, "lastStableRecoveryTimestamp" : Timestamp(1648912334, 5), "lastStableCheckpointTimestamp" : Timestamp(1648912334, 5), "electionCandidateMetrics" : { "lastElectionReason" : "electionTimeout", "lastElectionDate" : ISODate("2022-04-02T15:12:14.400Z"), "electionTerm" : NumberLong(1), "lastCommittedOpTimeAtElection" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "lastSeenOpTimeAtElection" : { "ts" : Timestamp(1648912334, 1), "t" : NumberLong(-1) }, "numVotesNeeded" : 1, "priorityAtElection" : 1, "electionTimeoutMillis" : NumberLong(10000), "newTermStartDate" : ISODate("2022-04-02T15:12:14.602Z"), "wMajorityWriteAvailabilityDate" : ISODate("2022-04-02T15:12:14.677Z") }, "members" : [ { "_id" : 0, "name" : "192.168.24.105:27318", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 803, "optime" : { "ts" : Timestamp(1648912368, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2022-04-02T15:12:48Z"), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "could not find member to sync from", "electionTime" : Timestamp(1648912334, 2), "electionDate" : ISODate("2022-04-02T15:12:14Z"), "configVersion" : 3, "self" : true, "lastHeartbeatMessage" : "" }, { "_id" : 1, "name" : "192.168.24.105:27418", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 22, "optime" : { "ts" : Timestamp(1648912368, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1648912368, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2022-04-02T15:12:48Z"), "optimeDurableDate" : ISODate("2022-04-02T15:12:48Z"), "lastHeartbeat" : ISODate("2022-04-02T15:12:58.706Z"), "lastHeartbeatRecv" : ISODate("2022-04-02T15:12:59.715Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "192.168.24.105:27318", "syncSourceHost" : "192.168.24.105:27318", "syncSourceId" : 0, "infoMessage" : "", "configVersion" : 3 }, { "_id" : 2, "name" : "192.168.24.105:27518", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 11, "lastHeartbeat" : ISODate("2022-04-02T15:12:58.706Z"), "lastHeartbeatRecv" : ISODate("2022-04-02T15:12:58.771Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "", "configVersion" : 3 } ], "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(1648912368, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1648912368, 1) } shihanshuoshardrs02:PRIMARY> exit bye [root@localhost ~]#
配置节点副本集的创建 1 2 3 4 5 6 7 mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27019/log \ & mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27019/data/dbmkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27119/log \ & mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27119/data/dbmkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27219/log \ & mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27219/data/db
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/ 总用量 0 drwxr-xr-x 4 root root 29 10月 21 19:44 shihanshuoconfigrs_27019 drwxr-xr-x 4 root root 29 10月 21 19:44 shihanshuoconfigrs_27119 drwxr-xr-x 4 root root 29 10月 21 19:44 shihanshuoconfigrs_27219 drwxr-xr-x 4 root root 48 10月 21 19:36 shihanshuoshardrs01_27018 drwxr-xr-x 4 root root 48 10月 21 19:40 shihanshuoshardrs01_27118 drwxr-xr-x 4 root root 48 10月 21 19:40 shihanshuoshardrs01_27218 drwxr-xr-x 4 root root 48 10月 21 19:43 shihanshuoshardrs02_27318 drwxr-xr-x 4 root root 48 10月 21 19:43 shihanshuoshardrs02_27418 drwxr-xr-x 4 root root 48 10月 21 19:44 shihanshuoshardrs02_27518 [1]+ 完成 mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27219/log \ [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27019/ 总用量 0 drwxr-xr-x 3 root root 16 10月 21 19:44 data drwxr-xr-x 2 root root 6 10月 21 19:44 log [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27219/ 总用量 0 drwxr-xr-x 3 root root 16 10月 21 19:44 data drwxr-xr-x 2 root root 6 10月 21 19:44 log [root@localhost mongodb]# ll /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27119/ 总用量 0 drwxr-xr-x 3 root root 16 10月 21 19:44 data drwxr-xr-x 2 root root 6 10月 21 19:44 log [root@localhost mongodb]#
27019的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 vi /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27019/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27019/log/mongod.log" logAppend: true storage: dbPath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27019/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27019/log/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27019 replication: replSetName: shihanshuoconfigrs sharding: clusterRole: configsvr
27119的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 vi /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27119/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27119/log/mongod.log" logAppend: true storage: dbPath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27119/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27119/log/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27119 replication: replSetName: shihanshuoconfigrs sharding: clusterRole: configsvr
27219的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 vi /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27219/mongod.conf systemLog: destination: file path: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27219/log/mongod.log" logAppend: true storage: dbPath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27219/data/db" journal: enabled: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27219/log/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27219 replication: replSetName: shihanshuoconfigrs sharding: clusterRole: configsvr
启动配置副本集 启动配置副本集:一主两副本 依次启动三个mongod服务,并查看服务是否启动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27019/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8882 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27119/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8932 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27219/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8982 child process started successfully, parent exiting [root@localhost ~]# ps -ef | grep mongod root 7835 1 1 22:51 ? 00:00:08 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf root 7884 1 1 22:51 ? 00:00:08 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/mongod.conf root 7934 1 1 22:51 ? 00:00:08 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/mongod.conf root 8466 1 1 22:59 ? 00:00:03 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27318/mongod.conf root 8508 1 1 22:59 ? 00:00:04 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27418/mongod.conf root 8551 1 1 22:59 ? 00:00:04 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27518/mongod.conf root 8882 1 7 23:04 ? 00:00:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27019/mongod.conf root 8932 1 13 23:04 ? 00:00:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27119/mongod.conf root 8982 1 24 23:04 ? 00:00:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27219/mongod.conf root 9032 7599 0 23:04 pts/0 00:00:00 grep --color=auto mongod [root@localhost ~]#
初始化配置节点副本集 (1)初始化副本集和创建主节点:使用客户端命令连接任意一个节点,但这里尽量要连接主节点:mongo --host=192.168.24.105 --port=27019
执行初始化副本集命令:rs.initiate()
查看副本集情况:rs.status()
(2)主节点配置查看:rs.conf()
(3)添加2个副本节点:rs.add("192.168.24.105:27119")
rs.add("192.168.24.105:27219")
查看副本集的配置情况:rs.status()
代码过程如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 [root@localhost ~]# mongo --host=192.168.24.105 --port=27019 MongoDB shell version v4.2.18 connecting to: mongodb://192.168.24.105:27019/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("1fbb4b8b-316f-48c1-aa8c-74e518713381" ) } MongoDB server version: 4.2.18 Server has startup warnings: 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always' . 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-04-02T23:04:14.789+0800 I CONTROL [initandlisten] --- Enable MongoDB's free cloud-based monitoring service, which will then receive and display metrics about your deployment (disk utilization, CPU, operation statistics, etc). The monitoring data will be available on a MongoDB website with a unique URL accessible to you and anyone you share the URL with. MongoDB may use this information to make product improvements and to suggest MongoDB products and deployment options to you. To enable free monitoring, run the following command: db.enableFreeMonitoring() To permanently disable this reminder, run the following command: db.disableFreeMonitoring() --- > rs.initiate() { "info2" : "no configuration specified. Using a default configuration for the set", "me" : "192.168.24.105:27019", "ok" : 1, "$gleStats" : { "lastOpTime" : Timestamp(1648912625, 1), "electionId" : ObjectId("000000000000000000000000") }, "lastCommittedOpTime" : Timestamp(0, 0) } shihanshuoconfigrs:OTHER> shihanshuoconfigrs:PRIMARY> rs.add("192.168.24.105:27119") { "ok" : 1, "$gleStats" : { "lastOpTime" : { "ts" : Timestamp(1648912664, 1), "t" : NumberLong(1) }, "electionId" : ObjectId("7fffffff0000000000000001") }, "lastCommittedOpTime" : Timestamp(1648912656, 1), "$clusterTime" : { "clusterTime" : Timestamp(1648912664, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1648912664, 1) } shihanshuoconfigrs:PRIMARY> rs.add("192.168.24.105:27219") { "ok" : 1, "$gleStats" : { "lastOpTime" : { "ts" : Timestamp(1648912676, 2), "t" : NumberLong(1) }, "electionId" : ObjectId("7fffffff0000000000000001") }, "lastCommittedOpTime" : Timestamp(1648912664, 2), "$clusterTime" : { "clusterTime" : Timestamp(1648912676, 2), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1648912676, 2) } shihanshuoconfigrs:PRIMARY> rs.status() { "set" : "shihanshuoconfigrs", "date" : ISODate("2022-04-02T15:18:11.941Z"), "myState" : 1, "term" : NumberLong(1), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "configsvr" : true, "heartbeatIntervalMillis" : NumberLong(2000), "majorityVoteCount" : 2, "writeMajorityCount" : 2, "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1648912676, 2), "t" : NumberLong(1) }, "lastCommittedWallTime" : ISODate("2022-04-02T15:17:56.999Z"), "readConcernMajorityOpTime" : { "ts" : Timestamp(1648912676, 2), "t" : NumberLong(1) }, "readConcernMajorityWallTime" : ISODate("2022-04-02T15:17:56.999Z"), "appliedOpTime" : { "ts" : Timestamp(1648912676, 2), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1648912676, 2), "t" : NumberLong(1) }, "lastAppliedWallTime" : ISODate("2022-04-02T15:17:56.999Z"), "lastDurableWallTime" : ISODate("2022-04-02T15:17:56.999Z") }, "lastStableRecoveryTimestamp" : Timestamp(1648912676, 2), "lastStableCheckpointTimestamp" : Timestamp(1648912676, 2), "electionCandidateMetrics" : { "lastElectionReason" : "electionTimeout", "lastElectionDate" : ISODate("2022-04-02T15:17:05.681Z"), "electionTerm" : NumberLong(1), "lastCommittedOpTimeAtElection" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "lastSeenOpTimeAtElection" : { "ts" : Timestamp(1648912625, 1), "t" : NumberLong(-1) }, "numVotesNeeded" : 1, "priorityAtElection" : 1, "electionTimeoutMillis" : NumberLong(10000), "newTermStartDate" : ISODate("2022-04-02T15:17:05.941Z"), "wMajorityWriteAvailabilityDate" : ISODate("2022-04-02T15:17:06.450Z") }, "members" : [ { "_id" : 0, "name" : "192.168.24.105:27019", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 838, "optime" : { "ts" : Timestamp(1648912676, 2), "t" : NumberLong(1) }, "optimeDate" : ISODate("2022-04-02T15:17:56Z"), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "could not find member to sync from", "electionTime" : Timestamp(1648912625, 2), "electionDate" : ISODate("2022-04-02T15:17:05Z"), "configVersion" : 3, "self" : true, "lastHeartbeatMessage" : "" }, { "_id" : 1, "name" : "192.168.24.105:27119", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 27, "optime" : { "ts" : Timestamp(1648912676, 2), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1648912676, 2), "t" : NumberLong(1) }, "optimeDate" : ISODate("2022-04-02T15:17:56Z"), "optimeDurableDate" : ISODate("2022-04-02T15:17:56Z"), "lastHeartbeat" : ISODate("2022-04-02T15:18:11.052Z"), "lastHeartbeatRecv" : ISODate("2022-04-02T15:18:10.126Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "192.168.24.105:27019", "syncSourceHost" : "192.168.24.105:27019", "syncSourceId" : 0, "infoMessage" : "", "configVersion" : 3 }, { "_id" : 2, "name" : "192.168.24.105:27219", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 14, "optime" : { "ts" : Timestamp(1648912676, 2), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1648912676, 2), "t" : NumberLong(1) }, "optimeDate" : ISODate("2022-04-02T15:17:56Z"), "optimeDurableDate" : ISODate("2022-04-02T15:17:56Z"), "lastHeartbeat" : ISODate("2022-04-02T15:18:11.053Z"), "lastHeartbeatRecv" : ISODate("2022-04-02T15:18:11.889Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "", "configVersion" : 3 } ], "ok" : 1, "$gleStats" : { "lastOpTime" : { "ts" : Timestamp(1648912676, 2), "t" : NumberLong(1) }, "electionId" : ObjectId("7fffffff0000000000000001") }, "lastCommittedOpTime" : Timestamp(1648912676, 2), "$clusterTime" : { "clusterTime" : Timestamp(1648912676, 2), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1648912676, 2) } shihanshuoconfigrs:PRIMARY> exit bye [root@localhost ~]#
路由节点的创建和操作 1.第一套路由节点的创建和操作 1 2 mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27017/log
路由节点的作用主要是分发,它 不需要存储具体的数据,因此不需要data目录。
27017的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 vi /opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27017/mongos.conf systemLog: destination: file path: "/opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27017/log/mongod.log" logAppend: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27017/log/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27017 sharding: configDB: shihanshuoconfigrs/192.168.24.105:27019,192.168.24.105:27119,192.168.24.105:27219
启动第一个路由mongos 提示:启动如果失败,可以查看log目录下的日志,查看失败原因。
1 2 3 4 5 [root@localhost ~]# mongos -f /opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27017/mongos.conf about to fork child process, waiting until server is ready for connections. forked process: 10482 child process started successfully, parent exiting [root@localhost ~]#
客户端登录mongos,此时,写不进去数据,如果写数据会报错:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 [root@localhost ~]# mongo --host=192.168.24.105 --port=27017 MongoDB shell version v4.2.18 connecting to: mongodb://192.168.24.105:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("5bd001ce-16ba-464b-993b-9cbd6fbcddaf" ) } MongoDB server version: 4.2.18 Server has startup warnings: 2022-04-02T23:24:19.966+0800 I CONTROL [main] 2022-04-02T23:24:19.966+0800 I CONTROL [main] ** WARNING: Access control is not enabled for the database. 2022-04-02T23:24:19.966+0800 I CONTROL [main] ** Read and write access to data and configuration is unrestricted. 2022-04-02T23:24:19.966+0800 I CONTROL [main] ** WARNING: You are running this process as the root user, which is not recommended. 2022-04-02T23:24:19.966+0800 I CONTROL [main] mongos> show dbs admin 0.000GB config 0.000GB mongos> use shihanshuo switched to db shihanshuo mongos> mongos> db.shi.insert({shi:"hanshuo" }) WriteCommandError({ "ok" : 0, "errmsg" : "unable to initialize targeter for write op for collection shihanshuo.aa :: caused by :: Database shihanshuo could not be created :: caused by :: No shards found" , "code" : 70, "codeName" : "ShardNotFound" , "operationTime" : Timestamp(1648913224, 2), "$clusterTime " : { "clusterTime" : Timestamp(1648913224, 2), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } } }) mongos>
原因:通过路由节点操作,现在只是连接了配置节点,还没有连接分片数据节点(caused by :: No shards found
),因此无法写入业务数据。
properties配置文件参考:
1 2 3 4 5 6 logpath=/mongodb/sharded_cluster/shihanshuomongos_27017/log/mongos.log logappend=true bind_ip_all=true port=27017 fork=true configdb=shihanshuoconfigrs/192.168.24.105:27019,192.168.24.105:27119,192.168.24.105:27219
2.在路由节点上进行分片配置操作 使用命令添加分片:
(1)添加分片 将第一套分片副本集添加进来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 mongos> sh.addShard("shihanshuoshardrs01/192.168.24.105:27018,192.168.24.105:27118,192.168.24.105:27218" ) { "shardAdded" : "shihanshuoshardrs01" , "ok" : 1, "operationTime" : Timestamp(1648913541, 6), "$clusterTime " : { "clusterTime" : Timestamp(1648913541, 6), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } } } mongos>
查看分片状态情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("624868f214f17e4ba54f23da" ) } shards: { "_id" : "shihanshuoshardrs01" , "host" : "shihanshuoshardrs01/192.168.24.105:27018,192.168.24.105:27118" , "state" : 1 } active mongoses: "4.2.18" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: No recent migrations databases: { "_id" : "config" , "primary" : "config" , "partitioned" : true } mongos>
继续将第二套分片副本集添加进来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 mongos> sh.addShard("shihanshuoshardrs02/192.168.24.105:27318,192.168.24.105:27418,192.168.24.105:27518" ) { "shardAdded" : "shihanshuoshardrs02" , "ok" : 1, "operationTime" : Timestamp(1648913689, 5), "$clusterTime " : { "clusterTime" : Timestamp(1648913689, 5), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } } }
查看分片状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("624868f214f17e4ba54f23da" ) } shards: { "_id" : "shihanshuoshardrs01" , "host" : "shihanshuoshardrs01/192.168.24.105:27018,192.168.24.105:27118" , "state" : 1 } { "_id" : "shihanshuoshardrs02" , "host" : "shihanshuoshardrs02/192.168.24.105:27318,192.168.24.105:27418" , "state" : 1 } active mongoses: "4.2.18" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: 4 : Success databases: { "_id" : "config" , "primary" : "config" , "partitioned" : true } config.system.sessions shard key: { "_id" : 1 } unique: false balancing: true chunks: shihanshuoshardrs01 1020 shihanshuoshardrs02 4 too many chunks to print , use verbose if you want to force print mongos>
提示:如果添加分片失败,需要先手动移除分片,检查添加分片的信息的正确性后,再次添加分片。
移除分片参考(了解):
1 2 use admin db.runCommand( { removeShard: "shihanshuoshardrs02" } )
注意:如果只剩下最后一个shard,是无法删除的移除时会自动转移分片数据,需要一个时间过程。
完成后,再次执行删除分片命令才能真正删除。
(2)开启分片功能 添加分片之后,还需要初始化才可以使用。(即在某一个库中开启分片功能)
sh.enableSharding("库名")
sh.shardCollection("库名.集合名",{"key":1})
在mongos上的articledb数据库配置sharding:
1 2 3 4 5 6 7 8 9 10 11 12 13 mongos> sh.enableSharding("articledb" ) { "ok" : 1, "operationTime" : Timestamp(1648914039, 11), "$clusterTime " : { "clusterTime" : Timestamp(1648914039, 12), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } } } mongos>
查看分片状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("624868f214f17e4ba54f23da" ) } shards: { "_id" : "shihanshuoshardrs01" , "host" : "shihanshuoshardrs01/192.168.24.105:27018,192.168.24.105:27118" , "state" : 1 } { "_id" : "shihanshuoshardrs02" , "host" : "shihanshuoshardrs02/192.168.24.105:27318,192.168.24.105:27418" , "state" : 1 } active mongoses: "4.2.18" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: yes Collections with active migrations: config.system.sessions started at Sat Apr 02 2022 23:42:03 GMT+0800 (CST) Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: 347 : Success databases: { "_id" : "articledb" , "primary" : "shihanshuoshardrs02" , "partitioned" : true , "version" : { "uuid" : UUID("c5a85211-06ac-46e4-bd29-47758191f460" ), "lastMod" : 1 } } { "_id" : "config" , "primary" : "config" , "partitioned" : true } config.system.sessions shard key: { "_id" : 1 } unique: false balancing: true chunks: shihanshuoshardrs01 676 shihanshuoshardrs02 348 too many chunks to print , use verbose if you want to force print mongos>
(3)集合分片 对集合分片,你必须使用 sh.shardCollection() 方法指定集合和分片键。
sh.shardCollection(namespace, key, unique)
对集合进行分片时,你需要选择一个 片键(Shard Key) , shard key 是每条记录都必须包含的,且建立了索引的单个字段或复合字段,MongoDB按照片键将数据划分到不同的 数据块中,并将 数据块均衡地分布到所有分片中.为了按照片键划分数据块,MongoDB使用 基于哈希的分片方式(随机平均分配)或者基于范围的分片方式(数值大小分配)。
用什么字段当片键都可以,如:nickname作为片键,但一定是必填字段。
分片规则一:哈希策略 对于 基于哈希的分片 ,MongoDB计算一个字段的哈希值,并用这个哈希值来创建数据块.
在使用基于哈希分片的系统中,拥有”相近”分片键的文档很可能不会存储在同一个数据块中,因此数据的分离性更好一些.
先开启库的分片功能,再开启分片规则,最后查看分片状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 mongos> sh.enableSharding("articledb" ) { "ok" : 1, "operationTime" : Timestamp(1648914317, 10), "$clusterTime " : { "clusterTime" : Timestamp(1648914317, 17), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } } } mongos> sh.shardCollection("articledb.comment" ,{"nickname" :"hashed" }) { "collectionsharded" : "articledb.comment" , "collectionUUID" : UUID("d9e4283f-fa83-48d4-9dac-ea30a05c8356" ), "ok" : 1, "operationTime" : Timestamp(1648914330, 28), "$clusterTime " : { "clusterTime" : Timestamp(1648914330, 28), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } } } mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("624868f214f17e4ba54f23da" ) } shards: { "_id" : "shihanshuoshardrs01" , "host" : "shihanshuoshardrs01/192.168.24.105:27018,192.168.24.105:27118" , "state" : 1 } { "_id" : "shihanshuoshardrs02" , "host" : "shihanshuoshardrs02/192.168.24.105:27318,192.168.24.105:27418" , "state" : 1 } active mongoses: "4.2.18" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: 512 : Success databases: { "_id" : "articledb" , "primary" : "shihanshuoshardrs02" , "partitioned" : true , "version" : { "uuid" : UUID("c5a85211-06ac-46e4-bd29-47758191f460" ), "lastMod" : 1 } } articledb.comment shard key: { "nickname" : "hashed" } unique: false balancing: true chunks: shihanshuoshardrs01 2 shihanshuoshardrs02 2 { "nickname" : { "$minKey " : 1 } } -->> { "nickname" : NumberLong("-4611686018427387902" ) } on : shihanshuoshardrs01 Timestamp(1, 0) { "nickname" : NumberLong("-4611686018427387902" ) } -->> { "nickname" : NumberLong(0) } on : shihanshuoshardrs01 Timestamp(1, 1) { "nickname" : NumberLong(0) } -->> { "nickname" : NumberLong("4611686018427387902" ) } on : shihanshuoshardrs02 Timestamp(1, 2) { "nickname" : NumberLong("4611686018427387902" ) } -->> { "nickname" : { "$maxKey " : 1 } } on : shihanshuoshardrs02 Timestamp(1, 3) { "_id" : "config" , "primary" : "config" , "partitioned" : true } config.system.sessions shard key: { "_id" : 1 } unique: false balancing: true chunks: shihanshuoshardrs01 512 shihanshuoshardrs02 512 too many chunks to print , use verbose if you want to force print mongos>
依据不同的规则放在分片1和分片2
分片规则二:范围策略 对于 基于范围的分片 ,MongoDB按照片键的范围把数据分成不同部分.假设有一个数字的片键:想象一个从负无穷到正无穷的直线,每一个片键的值都在直线上画了一个点.MongoDB把这条直线划分为更短的不重叠的片段,并称之为 数据块 ,每个数据块包含了片键在一定范围内的数据.
在使用片键做范围划分的系统中,拥有”相近”片键的文档很可能存储在同一个数据块中,因此也会存储在同一个分片中.
注意:mongodb只能根据集合当中的一个分片键执行分片规则,以此这里不能再次使用comment。使用新的集合author
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 mongos> sh.shardCollection("articledb.author" ,{"age" :1}) { "collectionsharded" : "articledb.author" , "collectionUUID" : UUID("995c2443-16a2-4412-82e3-64b2c2b8aa28" ), "ok" : 1, "operationTime" : Timestamp(1648914908, 12), "$clusterTime " : { "clusterTime" : Timestamp(1648914908, 12), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA=" ), "keyId" : NumberLong(0) } } } mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("624868f214f17e4ba54f23da" ) } shards: { "_id" : "shihanshuoshardrs01" , "host" : "shihanshuoshardrs01/192.168.24.105:27018,192.168.24.105:27118" , "state" : 1 } { "_id" : "shihanshuoshardrs02" , "host" : "shihanshuoshardrs02/192.168.24.105:27318,192.168.24.105:27418" , "state" : 1 } active mongoses: "4.2.18" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: 512 : Success databases: { "_id" : "articledb" , "primary" : "shihanshuoshardrs02" , "partitioned" : true , "version" : { "uuid" : UUID("c5a85211-06ac-46e4-bd29-47758191f460" ), "lastMod" : 1 } } articledb.author shard key: { "age" : 1 } unique: false balancing: true chunks: shihanshuoshardrs02 1 { "age" : { "$minKey " : 1 } } -->> { "age" : { "$maxKey " : 1 } } on : shihanshuoshardrs02 Timestamp(1, 0) articledb.comment shard key: { "nickname" : "hashed" } unique: false balancing: true chunks: shihanshuoshardrs01 2 shihanshuoshardrs02 2 { "nickname" : { "$minKey " : 1 } } -->> { "nickname" : NumberLong("-4611686018427387902" ) } on : shihanshuoshardrs01 Timestamp(1, 0) { "nickname" : NumberLong("-4611686018427387902" ) } -->> { "nickname" : NumberLong(0) } on : shihanshuoshardrs01 Timestamp(1, 1) { "nickname" : NumberLong(0) } -->> { "nickname" : NumberLong("4611686018427387902" ) } on : shihanshuoshardrs02 Timestamp(1, 2) { "nickname" : NumberLong("4611686018427387902" ) } -->> { "nickname" : { "$maxKey " : 1 } } on : shihanshuoshardrs02 Timestamp(1, 3) { "_id" : "config" , "primary" : "config" , "partitioned" : true } config.system.sessions shard key: { "_id" : 1 } unique: false balancing: true chunks: shihanshuoshardrs01 512 shihanshuoshardrs02 512 too many chunks to print , use verbose if you want to force print mongos>
范围规则中,此实验环境中数据的存储会默认存放在shihanshuoshardrs02中,根据数据的大小(age索引)来进行自动的分片。
注意的是:
1)一个集合只能指定一个片键,否则报错。
2)一旦对一个集合分片,分片键和分片值就不可改变。 如:不能给集合选择不同的分片键、不能更新分片键的值。
3)根据age索引进行分配数据。
基于范围的分片方式与基于哈希的分片方式性能对比: 基于范围的分片方式提供了更高效的范围查询,给定一个片键的范围,分发路由可以很简单地确定哪个数据块存储了请求需要的数据,并将请求转发到相应的分片中.
不过,基于范围的分片会导致数据在不同分片上的不均衡,有时候,带来的消极作用会大于查询性能的积极作用.比如,如果片键所在的字段是线性增长的,一定时间内的所有请求都会落到某个固定的数据块中,最终导致分布在同一个分片中.在这种情况下,一小部分分片承载了集群大部分的数据,系统并不能很好地进行扩展.
与此相比,基于哈希的分片方式以范围查询性能的损失为代价,保证了集群中数据的均衡.哈希值的随机性使数据随机分布在每个数据块中,因此也随机分布在不同分片中.但是也正由于随机性,一个范围查询很难确定应该请求哪些分片,通常为了返回需要的结果,需要请求所有分片.
如无特殊情况,一般推荐使用 Hash Sharding。而使用 _id 作为片键是一个不错的选择,因为它是必有的,你可以使用数据文档 _id 的哈希作为片键。
这个方案能够是的读和写都能够平均分布,并且它能够保证每个文档都有不同的片键所以数据块能够很精细。
似乎还是不够完美,因为这样的话对多个文档的查询必将命中所有的分片。虽说如此,这也是一种比较好的方案了。理想化的 shard key 可以让 documents 均匀地在集群中分布:
显示集群的详细信息:
1 mongos> db.printShardingStatus()
查看均衡器是否工作(需要重新均衡时系统才会自动启动,不用管它):
1 2 mongos> sh.isBalancerRunning() false
查看当前Balancer状态:
1 2 mongos> sh.getBalancerState() true
3.分片后插入数据测试 测试一(哈希规则): 登录mongs后,向comment循环插入1000条数据做测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 mongos> use articledb switched to db articledb mongos> for (var i=1;i<=1000;i++){db.comment.insert({_id:i+"" ,nickname:"BoBo" +i})} WriteResult({ "nInserted" : 1 }) mongos> show collections author comment mongos> show dbs admin 0.000GB articledb 0.000GB config 0.003GB mongos> db.comment.count() 1000 mongos>
提示:js的语法,因为mongo的shell是一个JavaScript的shell。
注意:从路由上插入的数据,必须包含片键,否则无法插入。
分别登陆两个片的主节点,统计文档数量
第一个分片副本集:
1 2 3 4 5 6 7 8 9 10 [root@localhost ~]# mongo --host=192.168.24.105 --port=27018 MongoDB shell version v4.2.18 connecting to: mongodb://192.168.24.105:27018/? --- shihanshuoshardrs01:PRIMARY> use articledb switched to db articledb shihanshuoshardrs01:PRIMARY> db.comment.count() 507 shihanshuoshardrs01:PRIMARY>
第二个分片副本集:
1 2 3 4 5 6 7 8 9 10 [root@localhost ~]# mongo --host=192.168.24.105 --port=27318 MongoDB shell version v4.2.18 connecting to: mongodb://192.168.24.105:27318/? --- shihanshuoshardrs02:PRIMARY> use articledb switched to db articledb shihanshuoshardrs02:PRIMARY> db.comment.count() 493 shihanshuoshardrs02:PRIMARY>
可以看到,1000条数据近似均匀的分布到了2个shard上。是根据片键的哈希值分配的。
这种分配方式非常易于水平扩展:一旦数据存储需要更大空间,可以直接再增加分片即可,同时提升了性能。
使用db.comment.stats()查看单个集合的完整情况,mongos执行该命令可以查看该集合的数据分片的情况。
使用sh.status()查看本库内所有集合的分片信息。
测试二(范围规则): 提示:
如果查看状态发现没有分片,则可能是由于以下原因造成了:
1)系统繁忙,正在分片中。
2)数据块(chunk)没有填满,默认的数据块尺寸(chunksize)是64M,填满后才会考虑向其他片的数据块填充数据,因此,为了测试,可以将其改小 ,这里改为1M,操作如下:
1 2 3 4 5 mongos> use config switched to db config mongos> db.settings.save( { _id:"chunksize" , value: 1 } ) WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "chunksize" }) mongos>
登录mongs后,向comment循环插入20000条数据做测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 mongos> use articledb switched to db articledb mongos> for (var i=1;i<=20000;i++){db.author.save({"name" :"BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo" +i,"age" :NumberInt(i%120)})} WriteResult({ "nInserted" : 1 }) mongos> db.author.count() 20118 mongos> db.author.remove({}) WriteResult({ "nRemoved" : 20118 }) mongos> db.author.count() 0 mongos> for (var i=1;i<=20000;i++){db.author.save({"name" :"BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo" +i,"age" :NumberInt(i%120)})} WriteResult({ "nInserted" : 1 }) mongos> db.author.count() 20000 mongos>
插入失败:
1)不在articledb库中
2)集合中由其他数据 可以使用 db.author.remove({})
命令来情况当前集合中所有的文档
插入成功后,仍然要分别查看两个分片副本集的数据情况。
分片效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 shihanshuoshardrs01:PRIMARY> db.author.count() 166 shihanshuoshardrs02:PRIMARY> db.author.count() 19834 shihanshuoshardrs02:PRIMARY> db.author.find () { "_id" : ObjectId("6248785b60db80fa633b9c15" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo1" , "age" : 1 } { "_id" : ObjectId("6248785b60db80fa633b9c16" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo2" , "age" : 2 } { "_id" : ObjectId("6248785b60db80fa633b9c17" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo3" , "age" : 3 } { "_id" : ObjectId("6248785b60db80fa633b9c18" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo4" , "age" : 4 } { "_id" : ObjectId("6248785b60db80fa633b9c19" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo5" , "age" : 5 } { "_id" : ObjectId("6248785b60db80fa633b9c1a" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo6" , "age" : 6 } { "_id" : ObjectId("6248785b60db80fa633b9c1b" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo7" , "age" : 7 } { "_id" : ObjectId("6248785b60db80fa633b9c1c" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo8" , "age" : 8 } { "_id" : ObjectId("6248785b60db80fa633b9c1d" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo9" , "age" : 9 } { "_id" : ObjectId("6248785b60db80fa633b9c1e" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo10" , "age" : 10 } { "_id" : ObjectId("6248785b60db80fa633b9c1f" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo11" , "age" : 11 } { "_id" : ObjectId("6248785b60db80fa633b9c20" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo12" , "age" : 12 } { "_id" : ObjectId("6248785b60db80fa633b9c21" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo13" , "age" : 13 } { "_id" : ObjectId("6248785b60db80fa633b9c22" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo14" , "age" : 14 } { "_id" : ObjectId("6248785b60db80fa633b9c23" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo15" , "age" : 15 } { "_id" : ObjectId("6248785b60db80fa633b9c24" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo16" , "age" : 16 } { "_id" : ObjectId("6248785b60db80fa633b9c25" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo17" , "age" : 17 } { "_id" : ObjectId("6248785b60db80fa633b9c26" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo18" , "age" : 18 } { "_id" : ObjectId("6248785b60db80fa633b9c27" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo19" , "age" : 19 } { "_id" : ObjectId("6248785b60db80fa633b9c28" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo20" , "age" : 20 } Type "it" for more shihanshuoshardrs02:PRIMARY> it { "_id" : ObjectId("6248785b60db80fa633b9c29" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo21" , "age" : 21 } { "_id" : ObjectId("6248785b60db80fa633b9c2a" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo22" , "age" : 22 } { "_id" : ObjectId("6248785b60db80fa633b9c2b" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo23" , "age" : 23 } { "_id" : ObjectId("6248785b60db80fa633b9c2c" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo24" , "age" : 24 } { "_id" : ObjectId("6248785b60db80fa633b9c2d" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo25" , "age" : 25 } { "_id" : ObjectId("6248785b60db80fa633b9c2e" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo26" , "age" : 26 } { "_id" : ObjectId("6248785b60db80fa633b9c2f" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo27" , "age" : 27 } { "_id" : ObjectId("6248785b60db80fa633b9c30" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo28" , "age" : 28 } { "_id" : ObjectId("6248785b60db80fa633b9c31" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo29" , "age" : 29 } { "_id" : ObjectId("6248785b60db80fa633b9c32" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo30" , "age" : 30 } { "_id" : ObjectId("6248785b60db80fa633b9c33" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo31" , "age" : 31 } { "_id" : ObjectId("6248785b60db80fa633b9c34" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo32" , "age" : 32 } { "_id" : ObjectId("6248785b60db80fa633b9c35" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo33" , "age" : 33 } { "_id" : ObjectId("6248785b60db80fa633b9c36" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo34" , "age" : 34 } { "_id" : ObjectId("6248785b60db80fa633b9c37" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo35" , "age" : 35 } { "_id" : ObjectId("6248785b60db80fa633b9c38" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo36" , "age" : 36 } { "_id" : ObjectId("6248785b60db80fa633b9c39" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo37" , "age" : 37 } { "_id" : ObjectId("6248785b60db80fa633b9c3a" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo38" , "age" : 38 } { "_id" : ObjectId("6248785b60db80fa633b9c3b" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo39" , "age" : 39 } { "_id" : ObjectId("6248785b60db80fa633b9c3c" ), "name" : "BoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBoBo40" , "age" : 40 } Type "it" for more
测试完改回来:
1 2 3 4 5 mongos> use config switched to db config mongos> db.settings.save( { _id:"chunksize" , value: 64 } ) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) mongos>
注意:要先改小,再设置分片。测试过程中操作不当引起的错误,可以先删除集合,重新建立集合的分片策略,再插入数据测试即可。
4.再增加一个路由节点 第二套路由节点的创建和操作 1 2 mkdir -p /opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27117/log
27117的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 vi /opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27117/mongos.conf systemLog: destination: file path: "/opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27117/log/mongod.log" logAppend: true processManagement: fork: true pidFilePath: "/opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27117/log/mongod.pid" net: bindIp: localhost,192.168.24.105 port: 27117 sharding: configDB: shihanshuoconfigrs/192.168.24.105:27019,192.168.24.105:27119,192.168.24.105:27219
启动第二个路由mongos 提示:启动如果失败,可以查看log目录下的日志,查看失败原因。
1 2 3 4 5 [root@localhost ~]# mongos -f /opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27117/mongos.conf about to fork child process, waiting until server is ready for connections. forked process: 16986 child process started successfully, parent exiting [root@localhost ~]#
客户端登录mongos 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 [root@localhost ~]# mongo --host=192.168.24.105 --port=27117 MongoDB shell version v4.2.18 connecting to: mongodb://192.168.24.105:27117/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("2a6d91dd-aa04-457f-b1af-7190386fceff" ) } MongoDB server version: 4.2.18 Server has startup warnings: 2022-04-03T00:35:33.115+0800 I CONTROL [main] 2022-04-03T00:35:33.115+0800 I CONTROL [main] ** WARNING: Access control is not enabled for the database. 2022-04-03T00:35:33.115+0800 I CONTROL [main] ** Read and write access to data and configuration is unrestricted. 2022-04-03T00:35:33.115+0800 I CONTROL [main] ** WARNING: You are running this process as the root user, which is not recommended. 2022-04-03T00:35:33.115+0800 I CONTROL [main] mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("624868f214f17e4ba54f23da" ) } shards: { "_id" : "shihanshuoshardrs01" , "host" : "shihanshuoshardrs01/192.168.24.105:27018,192.168.24.105:27118" , "state" : 1 } { "_id" : "shihanshuoshardrs02" , "host" : "shihanshuoshardrs02/192.168.24.105:27318,192.168.24.105:27418" , "state" : 1 } active mongoses: "4.2.18" : 2 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: 514 : Success databases: { "_id" : "articledb" , "primary" : "shihanshuoshardrs02" , "partitioned" : true , "version" : { "uuid" : UUID("c5a85211-06ac-46e4-bd29-47758191f460" ), "lastMod" : 1 } } articledb.author shard key: { "age" : 1 } unique: false balancing: true chunks: shihanshuoshardrs01 2 shihanshuoshardrs02 2 { "age" : { "$minKey " : 1 } } -->> { "age" : 0 } on : shihanshuoshardrs01 Timestamp(2, 0) { "age" : 0 } -->> { "age" : 59 } on : shihanshuoshardrs02 Timestamp(3, 2) { "age" : 59 } -->> { "age" : 119 } on : shihanshuoshardrs02 Timestamp(3, 3) { "age" : 119 } -->> { "age" : { "$maxKey " : 1 } } on : shihanshuoshardrs01 Timestamp(3, 0) articledb.comment shard key: { "nickname" : "hashed" } unique: false balancing: true chunks: shihanshuoshardrs01 2 shihanshuoshardrs02 2 { "nickname" : { "$minKey " : 1 } } -->> { "nickname" : NumberLong("-4611686018427387902" ) } on : shihanshuoshardrs01 Timestamp(1, 0) { "nickname" : NumberLong("-4611686018427387902" ) } -->> { "nickname" : NumberLong(0) } on : shihanshuoshardrs01 Timestamp(1, 1) { "nickname" : NumberLong(0) } -->> { "nickname" : NumberLong("4611686018427387902" ) } on : shihanshuoshardrs02 Timestamp(1, 2) { "nickname" : NumberLong("4611686018427387902" ) } -->> { "nickname" : { "$maxKey " : 1 } } on : shihanshuoshardrs02 Timestamp(1, 3) { "_id" : "config" , "primary" : "config" , "partitioned" : true } config.system.sessions shard key: { "_id" : 1 } unique: false balancing: true chunks: shihanshuoshardrs01 512 shihanshuoshardrs02 512 too many chunks to print , use verbose if you want to force print mongos>
使用mongo客户端登录27117,发现,第二个路由无需配置,因为分片配置都保存到了配置服务器中了。
可视化工具连接 直接连接到路由节点即可。
SpringDataMongoDB连接分片集群 1.启动mongod和mongos服务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/mongod.conf child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/mongod.conf root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27318/mongod.conf [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27418/mongod.conf [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs02_27518/mongod.conf [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27019/mongod.conf [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27119/mongod.conf [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoconfigrs_27219/mongod.conf [root@localhost ~]# mongos -f /opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27017/mongos.conf [root@localhost ~]# mongos -f /opt/module/mongodb/sharded_shihanshuo/shihanshuomongos_27117/mongos.conf
2.启动idea项目 打开idea项目中的application.yml
文件,改写一下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 spring: #数据源配置 data: mongodb: # 主机地址 host: 192.168 .24 .105 # 数据库 database: articledb # 默认端口是27017 port: 27017 #也可以使用uri连接 #uri: mongodb: #连接路由字符串 uri: mongodb:
打开测试类文件CommentServiceTest.java
mongod 无法启动 warning:千万不能使用kill -9 ,因为MongoDB使用mmap方式进行数据文件管理,也就是说写操作基本是在内存中进行,写操作会被每隔60秒(syncdelay设定)的flush到磁盘里。如果在这60秒内flush处于停止事情我们进行kill -9那么从上次flush之后的写入数据将会全部丢失。 如果在flush操作进行时执行kill -9则会造成文件混乱,可能导致数据全丢了,启动时加了repair也无法恢复。
解决方案: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 //删除db目录里面的/mongod.lock ,否则下面的命令是运行不成功的 rm -rf db目录//mongod.lock//删除db目录里面的storage.bson rm -rf db目录/storage.bson//修复数据 mongod --dbpath db目录 --repair //以修复方式启动mongodb mongod -f 配置文件路径 --repair //然后接着在启动一次 mongod -f 配置文件路径 --repair //查看进程是否运行 ps aux|grep mongo
具体操作示例: 1、服务器重启之后,或者非法操作关闭节点之后,导致mongod服务无法正常启动。 1 2 3 4 5 6 7 [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 7494 ^Z [1]+ 已停止 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf [root@localhost ~]#
2、依次启动其他服务发现,配置节点和路由节点服务启动正常,因此只需要修复2个分片节点的副本集。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 [root@localhost ~]# ps aux|grep mongo root 7492 0.0 1.2 155900 23264 pts/0 T 19:10 0:00 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf root 7493 0.0 0.6 155900 12856 ? Ss 19:10 0:00 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf root 7494 1.0 4.2 1521920 78376 ? Sl 19:10 0:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf root 7560 0.0 0.0 112828 992 pts/0 S+ 19:11 0:00 grep --color=auto mongo [root@localhost ~]# kill -9 7494 7493 7492 [root@localhost ~]# ps aux|grep mongo root 7562 0.0 0.0 112828 992 pts/0 R+ 19:12 0:00 grep --color=auto mongo [1]+ 已杀死 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinconfigrs_27019/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 7573 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinconfigrs_27119/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 7645 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinconfigrs_27219/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 7714 child process started successfully, parent exiting [root@localhost ~]# mongos -f /opt/module/mongodb/sharded_shihanshuo/cbinmongos_27017/mongos.conf about to fork child process, waiting until server is ready for connections. forked process: 7818 child process started successfully, parent exiting [root@localhost ~]# mongos -f /opt/module/mongodb/sharded_shihanshuo/cbinmongos_27117/mongos.conf about to fork child process, waiting until server is ready for connections. forked process: 7867 child process started successfully, parent exiting [root@localhost ~]# ps aux|grep mongo root 7573 2.7 6.0 1842432 111864 ? Sl 19:13 0:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinconfigrs_27019/mongod.conf root 7645 2.9 5.2 1903924 97812 ? Sl 19:13 0:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinconfigrs_27119/mongod.conf root 7714 3.0 5.1 1800584 95308 ? Sl 19:13 0:00 mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinconfigrs_27219/mongod.conf root 7818 0.5 1.3 326012 24312 ? Sl 19:13 0:00 mongos -f /opt/module/mongodb/sharded_shihanshuo/cbinmongos_27017/mongos.conf root 7867 1.0 1.2 326012 23124 ? Sl 19:13 0:00 mongos -f /opt/module/mongodb/sharded_shihanshuo/cbinmongos_27117/mongos.conf root 7906 0.0 0.0 112832 992 pts/0 S+ 19:13 0:00 grep --color=auto mongo [root@localhost ~]#
3、在本次运行环境下,只需修复分片节点的数据。因此删除db目录里面的/mongod.lock 和 删除db目录里面的storage.bson 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/data/db/mongod.lock [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/data/db/mongod.lock [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/data/db/mongod.lock [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27318/data/db/mongod.lock [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27418/data/db/mongod.lock [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27518/data/db/mongod.lock [root@localhost ~]# [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/data/db/storage.bson [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/data/db/storage.bson [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/data/db/storage.bson [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27318/data/db/storage.bson [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27418/data/db/storage.bson [root@localhost ~]# rm -rf /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27518/data/db/storage.bson [root@localhost ~]#
4、修复数据,依次修复27018–27518的数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [root@localhost ~]# mongod --dbpath /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/data/db/ --repair 2022-10-30T19:21:15.919+0800 I CONTROL [main] Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none' 2022-10-30T19:21:15.921+0800 W ASIO [main] No TransportLayer configured during NetworkInterface startup 2022-10-30T19:21:15.921+0800 I CONTROL [initandlisten] MongoDB starting : pid=8362 port=27017 dbpath=/opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/data/db/ 64-bit host=localhost.localdomain 2022-10-30T19:21:15.921+0800 I CONTROL [initandlisten] db version v4.2.18 2022-10-30T19:21:16.738+0800 I STORAGE [initandlisten] shutdown: removing fs lock... 2022-10-30T19:21:16.738+0800 I - [initandlisten] Dropping the scope cache for shutdown 2022-10-30T19:21:16.738+0800 I CONTROL [initandlisten] now exiting 2022-10-30T19:21:16.738+0800 I CONTROL [initandlisten] shutting down with code:0 [root@localhost ~]# [root@localhost ~]# mongod --dbpath /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/data/db/ --repair [root@localhost ~]# mongod --dbpath /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/data/db/ --repair [root@localhost ~]# mongod --dbpath /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27318/data/db/ --repair [root@localhost ~]# mongod --dbpath /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27418/data/db/ --repair [root@localhost ~]# mongod --dbpath /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27518/data/db/ --repair
5、先以修复方式启动mongodb,再接着正常启动一次 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf --repair about to fork child process, waiting until server is ready for connections. forked process: 8791 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8861 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/mongod.conf --repair about to fork child process, waiting until server is ready for connections. forked process: 8949 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8980 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/mongod.conf --repair about to fork child process, waiting until server is ready for connections. forked process: 9100 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 9131 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27318/mongod.conf --repair about to fork child process, waiting until server is ready for connections. forked process: 9188 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27318/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 9220 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27418/mongod.conf --repair about to fork child process, waiting until server is ready for connections. forked process: 9308 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27418/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 9339 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27518/mongod.conf --repair about to fork child process, waiting until server is ready for connections. forked process: 9440 child process started successfully, parent exiting [root@localhost ~]# mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27518/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 9494 child process started successfully, parent exiting [root@localhost ~]# [root@localhost ~]# ps aux|grep mongo root 7573 1.1 7.9 1892652 148920 ? Sl 19:13 0:11 mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinconfigrs_27019/mongod.conf root 7645 1.1 7.3 1950664 137032 ? Sl 19:13 0:11 mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinconfigrs_27119/mongod.conf root 7714 1.0 7.0 1863676 130932 ? Sl 19:13 0:10 mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinconfigrs_27219/mongod.conf root 7818 0.3 1.2 328116 22868 ? Sl 19:13 0:03 mongos -f /opt/module/mongodb/sharded_shihanshuo/cbinmongos_27017/mongos.conf root 7867 0.3 1.1 328116 22216 ? Sl 19:13 0:03 mongos -f /opt/module/mongodb/sharded_shihanshuo/cbinmongos_27117/mongos.conf root 8861 1.2 5.7 1809956 106216 ? Sl 19:26 0:02 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27018/mongod.conf root 8980 1.2 5.4 1889740 101928 ? Sl 19:26 0:02 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27118/mongod.conf root 9131 0.8 4.5 1594008 84064 ? Sl 19:27 0:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/shihanshuoshardrs01_27218/mongod.conf root 9220 1.3 5.7 1889224 106920 ? Sl 19:27 0:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27318/mongod.conf root 9339 1.2 5.1 1866144 96680 ? Sl 19:27 0:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27418/mongod.conf root 9494 0.9 4.2 1594008 78768 ? Sl 19:27 0:01 mongod -f /opt/module/mongodb/sharded_shihanshuo/cbinshardrs02_27518/mongod.conf root 9687 0.0 0.0 112832 992 pts/0 S+ 19:29 0:00 grep --color=auto mongo [root@localhost ~]#
十四、MongoDB GridFS 在之前的学习中,我们学习了MongoDB存储数据的形式并通过实际操作完成数据的存储。默认情况下,MongoDB受BSON文件大小的限制,存储的文件大小不可超过16M,但是在实际系统开发中,上传的图片或者文件会很大。为了满足这种需求,MongoDB提供了GridFS框架,而GridFS框架可以更好的存储大于16M的文件。
GridFS概述 GridFS 用于存储和恢复那些超过16M (BSON文件限制)的文件(如:图片、音频、视频等)。
GridFS是MongoDB的一个子模块,使用GridFS可以基于MongoDB来持久化文件,并且支持分布式应用(即文件分布存储和读取)。GridFS也是文件存储的一种方式,它不会将文件存储在单个文档中,而是将文件分为多个块(chunk),并将每个块存储为单独的文档。 默认情况下,GridFS使用的块大小为255KB。也就是说,GridFS将文件分成多个大小为255KB的块,每个chunk将作为MongoDB的一个文档(document)被存储在chunks集合中。
当查询GridFS文件时,GridFS驱动程序将根据查询需求重新组装块,形成完整文件。在查询时还可以指定查询范围,访问文件中的任意部分信息,例如跳转到视频或音频的某个时间点 查看。
在某些情况下, MongoDB数据库中存储大型文件可能比系统级文件系统(如:Windows系统、Linux系统)存储效率更高。举例列出一些GridFS常见的应用场景:
文件系统限制了一个目录可包含的文件数,可以使用GridFS存储任意数量的文件。
希望文件和元数据自动同步,并使用MongoDB副本集将文件存储到多个系统中。
可以使用GridFS获取文件的部分内容加载到内存中查看想要的信息,而不需要加载整个大文件到内存中去查找。
这里需要注意的是,如果文件大小小于16MB的限制,那么使用单个文档存储文件即可,最好不使用GridFS 。可以在文档中使用BinData数据类型存储二进制数据。
GridFS存储结构 GridFS将上传的文件存储在两个集合中。下面,通过一张图介绍一下GridFS存储结构,具体如下所示。
文件通过GridFS驱动上传到GridFS中进行存储,GridFS将文件分别存储到集合fs.chunks和fs.files中。
针对GridFS中存储文件的两个集合进行详细介绍,具体如下:
fs.chunks:
GridFS将文件切分为多个大小为255KB的二进制数据块(即文件原始数据),将这些数据块存储在fs.chunks集合中。
fs.files:
存储文件的元数据(meta data),元数据是关于数据的组织、数据域及其关系的信息。简言之,元数据就是描述文件信息的数据,算是一种电子目录,用来记录文件命、文件大小、文件块存储位置等数据。
GridFS规范定义了一些fs.files中文档必需的键,具体如下:
_id:文件唯一的id,默认使用ObjectId对象,用户也可以自定义其类型。与fs.chunks集合中数据块的files_id键相对应。
Length:文件大小,以字节为单位。
chunkSize:每块的大小,以字节为单位。默认是261120b(255kb),必要时可以调整。
uploadDate:文件上传时间。
filename:文件名称。
metadata:文件的其它信息,默认内容为空,用户可以自己定义。
GridFS规范定义了一些fs.chunks中文档必需的键,具体如下:
_id:和其它MongoDB文档一样,块也有自己唯一的标记,默认使用ObjectId对象,用户也可以自定义其类型。
_files_id:文件id,对应fs.files集合中文件元数据中的_id键。
n:表示块编号,也就是这个块在原文件中的顺序编号。
data:数据块中的二进制数据。
当客户端在GridFS中查询文件时,MongoDB将首先从集合fs.files中获取该文件的元数据信息,然后根据获取的元数据信息在集合fs.chunks查找符合要求的块(即files_id与元数据中_id相同的块),最后将这些块从新组装后返回给客户端。
GridFS基本操作 MongoDB提供了与GridFS交互的命令行工具mongofiles,通过Shell命令可以很方便地操作GridFS,例如上传文件、下载文件和查询文件等相关操作。
下面,通过两张表来分别介绍一下mongofiles工具常用的options选项和commands命令以及其相关说明。mongofiles工具常用的options选项及相关说明,具体如下所示。
options
相关说明
–help
返回有关mongofiles中所有options的用法信息
–host=<:port>
指定MongoDB数据库的主机名(或IP)和端口号,默认情况下,mongofiles尝试连接localhost:27017的主机名和端口号
–port=
指定MongoDB数据库的端口号
–username=或-u=
指定用户名,主要用于MongoDB数据库开启了权限认证
–password=或-p=
指定密码(用于MongoDB数据库开启了权限认证)
–db=或-d=
指定GridFS存储数据库名称,默认使用MongoDB中test数据库。如数据库名称不存在则创建
–local=或-l=
指定用于获取和存储操作的文件名称
–replace,-r
替换GridFS中已存在的对象(文件名相同),与put用法类似,区别是put不会覆盖已存在的对象
–authenticationDatabase=
指定GridFS存储的身份认证数据库名称(用于MongoDB数据库开启了权限认证)
–db=或-d=
指定GridFS存储数据库名称,默认使用MongoDB中test数据库。如数据库名称不存在则创建
mongofiles工具常用的commands命令及相关说明,具体如下所示。
commands
相关说明
list
列出GridFS存储中的所有文件。prefix为指定的字符串,这样返回的文件列表限制为以该字符串开头的所有文件,为可选参数
search
列出GridFS存储中名称与指定字符串string匹配的文件
put
将指定的文件从本地文件系统复制到GridFS存储中。可以和–local选项一起使用以获取指定路径下的文件,如local指定的文件名为a.txt,在put中可重命名为b.txt
get
将指定的文件从GridFS存储复制到本地文件系统。如果将获取的文件重命名存储在本地或者指定文件的存储路径,可以和–local选项一起使用
delete
从GridFS存储中删除指定的文件
get_id “<_id>”
将指定_id的文件从GridFS存储复制到本地文件系统
delete_id “<_id>”
从GridFS存储中删除指定_id的文件
本章针对GridFS的操作以开启权限认证的MongoDB副本集为环境基础且副本集的主节点为服务器nosql01。如果读者使用MongoDB分片集群为环境基础操作GridFS,则需要设置fs.chunks集合开启分片功能(通常情况下fs.files集合较小,不需要进行分片处理)。
在执行mongofiles命令行工具前,确保使用user_mongo用户启动MongoDB副本集,如系统中没有user_mongo用户可参考第3章内容进行创建。
上传本地系统文件到GridFS 通过XShell远程连接工具连接服务器,在目录“/opt/servers/mongo_demo/”下创建“/gridfs/datafile/”目录,用于存放要上传到GridFS中的文件,具体命令如下:
1 [root@Server01 ~]# mkdir -p /opt/servers/mongodb_demo/shihanshuo_gridfs/datafile
执行命令“cd /opt/servers/mongodb_demo/shihanshuo_gridfs/datafile”进入该目录后,再通过执行“rz”命令,将文件从Windows系统上传到服务器nosql01中的/opt/servers/mongodb_demo/shihanshuo_gridfs/datafile目录下。
待文件上传完成后,可在/opt/servers/mongodb_demo/shihanshuo_gridfs/datafile目录下执行“ll”命令验证文件是否上传成功,效果如图所示。
1 2 3 4 5 6 7 8 9 [root@Server01 ~]# cd /opt/servers/mongodb_demo/shihanshuo_gridfs/datafile [root@Server01 datafile]# rz [root@Server01 datafile]# cp -a /opt/mongodb-linux-x86_64-rhel80-4.2.24.tgz . [root@Server01 datafile]# ll -h 总用量 128M -rw-r--r-- 1 root root 231 12月 19 2022 mongodb-linux-x86_64-rhel80-4..tgz -rw-r--r-- 1 root root 128M 11月 1 22:42 mongodb-linux-x86_64-rhel80-4.2.24.tgz [root@Server01 datafile]#
通过mongofiles命令行工具将文件mongodb.tgz从Linux本地文件系统上传到MongoDB GridFS存储系统中,具体命令如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@localhost datafile]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27017/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8232 child process started successfully, parent exiting [root@localhost datafile]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27018/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8292 child process started successfully, parent exiting [root@localhost datafile]# mongod -f /opt/module/mongodb/shihanshuo_replica_sets/shihanshuors_27019/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 8355 child process started successfully, parent exiting [root@Server01 datafile]# mongofiles --port=27017 -d testfiles -l /opt/servers/mongodb_demo/shihanshuo_gridfs/datafile/mongodb-linux-x86_64-rhel80-4..tgz put mongodb.tgz 2024-04-27T20:13:50.638+0800 connected to: mongodb://localhost:27017/ 2024-04-27T20:13:55.394+0800 added gridFile: mongodb.tgz [root@Server01 datafile]#
将/opt/servers/mongodb_demo/shihanshuo_gridfs/datafile/目录下的mongodb-linux-x86_64-rhel80-4..tgz文件上传到MongoDB副本集中GridFS下的testfiles数据库中,并指定上传到GridFS中的文件名称为mongodb.tgz。
待文件上传完成后,查看控制台返回的信息,若出现“added gridFile: mongodb.tgz”信息,则说明我们成功将文件上传至GridFS中。
查看GridFS集合 GridFS 默认将上传的文件存储在两个集合中。接下来,我们将演示如何在MongoDB副本集中查看这两个集合。
在MongoDB副本集主节点(服务器nosql01)登陆MongoDB客户端,具体命令如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 [root@localhost datafile]# mongo --port=27017 MongoDB shell version v4.2.18 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("aea70697-f6e0-45a2-af89-6be725669087" ) } MongoDB server version: 4.2.18 Server has startup warnings: 2022-10-31T20:07:14.191+0800 I CONTROL [initandlisten] 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always' . 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] 2022-10-31T20:07:14.217+0800 I REPL [replexec-0] 2022-10-31T20:07:14.217+0800 I REPL [replexec-0] ** WARNING: This replica set has a Primary-Secondary-Arbiter architecture, but readConcern:majority is enabled 2022-10-31T20:07:14.217+0800 I REPL [replexec-0] ** for this node. This is not a recommended configuration. Please see 2022-10-31T20:07:14.217+0800 I REPL [replexec-0] ** https://dochub.mongodb.org/core/psa-disable-rc-majority 2022-10-31T20:07:14.217+0800 I REPL [replexec-0] --- Enable MongoDB's free cloud-based monitoring service, which will then receive and display metrics about your deployment (disk utilization, CPU, operation statistics, etc). The monitoring data will be available on a MongoDB website with a unique URL accessible to you and anyone you share the URL with. MongoDB may use this information to make product improvements and to suggest MongoDB products and deployment options to you. To enable free monitoring, run the following command: db.enableFreeMonitoring() To permanently disable this reminder, run the following command: db.disableFreeMonitoring() --- shihanshuors:PRIMARY> show dbs admin 0.000GB articledb 0.000GB config 0.000GB local 0.000GB testfiles 0.000GB # 切换到上传文件时指定的GridFS数据库testfiles,查看当前数据库下的所有集合,具体命令如下: shihanshuors:PRIMARY> use testfiles switched to db testfiles shihanshuors:PRIMARY> show collections fs.chunks fs.files shihanshuors:PRIMARY>
执行查看所有集合命令后,从客户端返回的信息中可以看出数据库testfiles下包含两个集合分别为fs.chunks和fs.files。
下面,演示查看集合fs.files中文件的元数据信息,具体命令如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 shihanshuors:PRIMARY> use testfiles shihanshuors:PRIMARY> db.getCollection('fs.files' ).find().pretty () { "_id" : ObjectId("662cebfecd4641d8a99bc522" ), "length" : NumberLong(133445425), "chunkSize" : 261120, "uploadDate" : ISODate("2024-04-27T12:13:55.251Z" ), "filename" : "mongodb.tgz" , "metadata" : { } } shihanshuors:PRIMARY> db.fs.files.find().pretty () { "_id" : ObjectId("662cebfecd4641d8a99bc522" ), "length" : NumberLong(133445425), "chunkSize" : 261120, "uploadDate" : ISODate("2024-04-27T12:13:55.251Z" ), "filename" : "mongodb.tgz" , "metadata" : { } }
执行查看GridFS中文件的元数据信息命令后,从客户端返回的信息中可以看出, GridFS中包含一个文件的元数据信息,即已上传的文件mongodb.tgz的元数据信息。
下面,演示查看文件mongodb.tgz被分割后存储在集合fs.chunks中的总块数,具体命令如下:
1 2 3 shihanshuors:PRIMARY> db.getCollection('fs.chunks' ).find({files_id:{$in :[ObjectId("662cebfecd4641d8a99bc522" )]}}).count() 512 shihanshuors:PRIMARY>
上述命令中,统计在集合fs.chunks中mongodb.tgz的总块数,通过在find()方法中指定files_id为ObjectId(“662cebfecd4641d8a99bc522”(在6.2小节中有所说明,文件块中的files_id与文件元数据信息中的_id相对应),查询出集合fs.chunks中文件mongodb.tgz的总块数为512。因为此时文件是133445425
133445425/1024/255=511.05,因此使用512个chunks
查看GridFS中的文件 查看GridFS中数据库为testfiles下的所有文件,执行如下命令。
1 2 3 4 [root@Server01 datafile]# mongofiles --port=27017 -d testfiles list 2024-04-27T20:24:48.624+0800 connected to: mongodb://localhost:27017/ mongodb.tgz 133445425 [root@Server01 datafile]#
上述命令中,list表示查看GridFS中的所有文件,执行完上述命令后,会返回有关文件的基本信息
条件查询GridFS中数据库为testfiles下的指定文件
1 2 3 4 [root@Server01 datafile]# mongofiles --port=27017 -d testfiles search "mon" 2024-04-27T20:26:04.167+0800 connected to: mongodb://localhost:27017/ mongodb.tgz 133445425 [root@Server01 datafile]#
上述命令中 search”mon” 表示检索数据库中文件名包含”mon”的文件,执行完上述命令后,会返回符合检索条件文件的基本信息,即文件名“mongodb.tgz”和文件大小“133445425”。
下载GridFS中的文件 将GridFS中存储的文件下载到本地文件系统中
1 2 3 4 5 6 7 8 9 [root@Server01 datafile]# mongofiles --port=27017 -d testfiles get mongodb.tgz -l /opt/servers/mongodb_demo/shihanshuo_gridfs/datafile/local_shihanshuo.tgz 2024-04-27T20:27:15.247+0800 connected to: mongodb://localhost:27017/ 2024-04-27T20:27:15.459+0800 finished writing to /opt/servers/mongodb_demo/shihanshuo_gridfs/datafile/local_shihanshuo.tgz [root@Server01 datafile]# ll 总用量 260640 -rw-r--r-- 1 root root 133445425 4月 27 20:27 local_shihanshuo.tgz -rw-r--r-- 1 root root 133445425 4月 27 19:55 mongodb-linux-x86_64-rhel80-4..tgz [root@Server01 datafile]#
上述命令中,get参数用于指定要下载GridFS中的文件名;-l 参数用于指定将文件下载到本地文件系统的目录并将文件名修改 为local_shihanshuo.tgz。如不指定“-l”选项则默认将文件保存到当前目录下,并且名称不变。
执行完上述命令后,会返回文件下载后存储在本地文件系统的目录信息,即“finished writing to……”。
删除GridFS中的文件 通过指定GridFS中的文件名删除对应文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 [root@Server01 datafile]# mongofiles --port=27017 -d testfiles delete mongodb.tgz 2024-04-27T20:28:11.558+0800 connected to: mongodb://localhost:27017/ 2024-04-27T20:28:11.620+0800 successfully deleted all instances of 'mongodb.tgz' from GridFS [root@Server01 datafile]# ll 总用量 260640 -rw-r--r-- 1 root root 133445425 4月 27 20:27 local_shihanshuo.tgz -rw-r--r-- 1 root root 133445425 4月 27 19:55 mongodb-linux-x86_64-rhel80-4..tgz [root@Server01 datafile]# [root@Server01 datafile]# mongofiles --port=27017 -d testfiles search "mongo" 2024-04-27T20:28:55.247+0800 connected to: mongodb://localhost:27017/ [root@Server01 datafile]# mongofiles --port=27017 -d testfiles list 2024-04-27T20:29:08.518+0800 connected to: mongodb://localhost:27017/ [root@Server01 datafile]# [root@localhost datafile]# mongo --port=27017 MongoDB shell version v4.2.18 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("aea70697-f6e0-45a2-af89-6be725669087" ) } MongoDB server version: 4.2.18 Server has startup warnings: 2022-10-31T20:07:14.191+0800 I CONTROL [initandlisten] 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always' . 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-10-31T20:07:14.192+0800 I CONTROL [initandlisten] 2022-10-31T20:07:14.217+0800 I REPL [replexec-0] 2022-10-31T20:07:14.217+0800 I REPL [replexec-0] ** WARNING: This replica set has a Primary-Secondary-Arbiter architecture, but readConcern:majority is enabled 2022-10-31T20:07:14.217+0800 I REPL [replexec-0] ** for this node. This is not a recommended configuration. Please see 2022-10-31T20:07:14.217+0800 I REPL [replexec-0] ** https://dochub.mongodb.org/core/psa-disable-rc-majority 2022-10-31T20:07:14.217+0800 I REPL [replexec-0] --- Enable MongoDB's free cloud-based monitoring service, which will then receive and display metrics about your deployment (disk utilization, CPU, operation statistics, etc). The monitoring data will be available on a MongoDB website with a unique URL accessible to you and anyone you share the URL with. MongoDB may use this information to make product improvements and to suggest MongoDB products and deployment options to you. To enable free monitoring, run the following command: db.enableFreeMonitoring() To permanently disable this reminder, run the following command: db.disableFreeMonitoring() --- shihanshuors:PRIMARY> show dbs admin 0.000GB articledb 0.000GB config 0.000GB local 0.000GB testfiles 0.000GB shihanshuors:PRIMARY> use testfiles switched to db testfiles shihanshuors:PRIMARY> show collections fs.chunks fs.files shihanshuors:PRIMARY> db.getCollection(' fs.files').find().pretty() shihanshuors:PRIMARY>
使用Java操作MongoDB GridFS 1. 创建Maven项目 单击“Create New Project”→“Maven”,选择创建一个Maven项目,命名为GridFS。
2. 导入依赖。 在项目中配置pom.xml文件,也就是引入MongoDB相关的依赖和单元测试的依赖。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > com.shihanshuo</groupId > <artifactId > nosql_chapter06</artifactId > <version > 1.0-SNAPSHOT</version > <dependencies > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.12</version > <scope > test</scope > </dependency > <dependency > <groupId > org.mongodb</groupId > <artifactId > mongo-java-driver</artifactId > <version > 3.12.11</version > </dependency > </dependencies > <properties > <maven.compiler.source > 8</maven.compiler.source > <maven.compiler.target > 8</maven.compiler.target > </properties > </project >
3. 创建资源文件 指定MongoDB相关参数。在项目GridFS的目录/src/main/resources下创建一个名为mongodb.properties文件,该文件用于存储连接MongoDB中GridFS所需要的参数。
1 2 3 host=192.168 .24 .105 port=27017 dbname=Shihanshuofiles
4. 创建Java工具类 连接MongoDB副本集中的GridFS。在项目GridFS目录/src/main/java下创建一个名为com.shihanshuo.mongodb包,并在该包下创建MongoUtils.java文件,该文件用于编写Java连接MongoDB副本集中GridFS的工具类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 package com.shihanshuo.mongodb;import com.mongodb.MongoClientSettings;import com.mongodb.MongoCredential;import com.mongodb.ServerAddress;import com.mongodb.client.MongoClient;import com.mongodb.client.MongoClients;import com.mongodb.client.MongoDatabase;import com.mongodb.client.gridfs.GridFSBucket;import com.mongodb.client.gridfs.GridFSBuckets;import java.io.IOException;import java.io.InputStream;import java.util.Arrays;import java.util.Properties;public class MongoUtils { private static Properties properties; private static InputStream stream = null ; private static String host; private static String port; private static String dbname; static { if (properties == null ) { properties = new Properties (); } try { stream = MongoUtils.class.getClassLoader().getResourceAsStream ("mongodb.properties" ); properties.load(stream); } catch (IOException e) { e.printStackTrace(); } host = properties.getProperty("host" ); port = properties.getProperty("port" ); dbname = properties.getProperty("dbname" ); } public static MongoClient getMongoClient () { MongoClient mongoClient = MongoClients.create( MongoClientSettings.builder() .applyToClusterSettings(builder -> builder.hosts( Arrays.asList( new ServerAddress ("192.168.24.105" , 27017 ) ))) .build()); return mongoClient; } public static GridFSBucket getGridFSConn () { MongoClient mongoClient = getMongoClient(); MongoDatabase mongoDatabase = mongoClient.getDatabase(dbname); GridFSBucket gridFSBucket = GridFSBuckets.create(mongoDatabase); return gridFSBucket; } }
5. 创建Java测试类 操作GridFS。在项目目录/src/test/java下创建一个名为com.shihanshuo.mongodb包,并在该包下创建TestGridFS.java的文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 package com.shihanshuo.mongodb;import com.shihanshuo.mongodb.MongoUtils;import com.mongodb.Block;import com.mongodb.client.gridfs.GridFSBucket;import com.mongodb.client.gridfs.GridFSDownloadStream;import com.mongodb.client.gridfs.GridFSUploadStream;import com.mongodb.client.gridfs.model.GridFSFile;import com.mongodb.client.gridfs.model.GridFSUploadOptions;import org.bson.BsonObjectId;import org.bson.Document;import org.bson.types.ObjectId;import org.junit.Test;import java.io.*;import java.nio.charset.StandardCharsets;import java.nio.file.Files;public class ShihanshuoTestGridFS { @Test public void getFiles () { GridFSBucket gridFSBucket = MongoUtils.getGridFSConn(); gridFSBucket.find().forEach( new Block <GridFSFile>() { public void apply (final GridFSFile gridFSFile) { System.out.println( "文件名:" +gridFSFile.getFilename()+" " +"文件大小:" +gridFSFile.getLength()+" " +"文件id:" +gridFSFile.getObjectId().toHexString()); } }); } @Test public void uploadFile () { GridFSBucket gridFSBucket = MongoUtils.getGridFSConn(); try { GridFSUploadOptions options = new GridFSUploadOptions () .chunkSizeBytes(358400 ); GridFSUploadStream uploadStream = gridFSBucket.openUploadStream("mongodb.tgz" , options); byte [] data = Files.readAllBytes(new File ("C:\\Users\\s2032\\Desktop\\mongodb-linux-x86_64-rhel80-4.2.24.tgz" ).toPath()); uploadStream.write(data); uploadStream.close(); System.out.println("文件id为: " + uploadStream.getObjectId().toHexString()); } catch (IOException e){ } } @Test public void downlodFile () { GridFSBucket gridFSBucket = MongoUtils.getGridFSConn(); try { FileOutputStream streamToDownloadTo = new FileOutputStream ("C:\\Users\\s2032\\Desktop\\down_mongodb.tgz" ); gridFSBucket.downloadToStream( new ObjectId ("662e26e70244657c5eeeb434" ), streamToDownloadTo); streamToDownloadTo.close(); } catch (IOException e) { } } @Test public void renameFile () { GridFSBucket gridFSBucket = MongoUtils.getGridFSConn(); gridFSBucket.rename( new ObjectId ("662e26e70244657c5eeeb434" ),"GridFS_NEW_mongodb.tgz" ); } @Test public void delFile () { GridFSBucket gridFSBucket = MongoUtils.getGridFSConn(); gridFSBucket.delete(new ObjectId ("662e26e70244657c5eeeb434" )); } }
(1)上传文件
验证是否上传成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 [root@localhost datafile]# mongofiles --port=27017 -d shihanshuofiles list 2022-11-09T15:22:01.119+0800 connected to: mongodb://localhost:27017/ GridFS.mp4 47780752 [root@localhost datafile]# [root@localhost ~]# mongo --port=27017 MongoDB shell version v4.2.18 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("4f5e348d-0551-431a-bd11-0da3ef37bcaa" ) } MongoDB server version: 4.2.18 Server has startup warnings: 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always' . 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] --- Enable MongoDB's free cloud-based monitoring service, which will then receive and display metrics about your deployment (disk utilization, CPU, operation statistics, etc). The monitoring data will be available on a MongoDB website with a unique URL accessible to you and anyone you share the URL with. MongoDB may use this information to make product improvements and to suggest MongoDB products and deployment options to you. To enable free monitoring, run the following command: db.enableFreeMonitoring() To permanently disable this reminder, run the following command: db.disableFreeMonitoring() --- > show dbs admin 0.000GB articledb 0.000GB config 0.000GB cuibindb 0.000GB local 0.000GB testfiles 0.039GB > use testfiles switched to db testfiles > db.getCollection(' fs.files').find().pretty() { "_id" : ObjectId("636b54a92f0ddd638f185e8e"), "filename" : "GridFS.mp4", "length" : NumberLong(47780752), "chunkSize" : 358400, "uploadDate" : ISODate("2022-11-09T07:20:10.709Z"), "md5" : "8c36ca6ecc0065ca1ec5278b1ad0ccd6" } >
(2)下载文件
验证是否下载成功
(3)重命名
验证是否更名成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 [root@localhost datafile]# mongofiles --port=27017 -d testfiles list 2022-11-09T15:34:10.802+0800 connected to: mongodb://localhost:27017/ GridFS_new.mp4 47780752 [root@localhost datafile]# [root@Server01 ~]# mongofiles --port=27017 -d testfiles search "mon" 2024-04-28T18:38:46.546+0800 connected to: mongodb://localhost:27017/ GridFS_NEW_mongodb.tgz 133445425 [root@Server01 ~]# mongofiles --port=27018 -d testfiles search "mon" 2024-04-28T18:38:51.861+0800 connected to: mongodb://localhost:27018/ GridFS_NEW_mongodb.tgz 133445425 [root@Server01 ~]# [root@localhost ~]# mongo --port=27017 MongoDB shell version v4.2.18 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("7441b7ce-b624-4374-9a9a-4b126319dbe2" ) } MongoDB server version: 4.2.18 Server has startup warnings: 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always' . 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] --- Enable MongoDB's free cloud-based monitoring service, which will then receive and display metrics about your deployment (disk utilization, CPU, operation statistics, etc). The monitoring data will be available on a MongoDB website with a unique URL accessible to you and anyone you share the URL with. MongoDB may use this information to make product improvements and to suggest MongoDB products and deployment options to you. To enable free monitoring, run the following command: db.enableFreeMonitoring() To permanently disable this reminder, run the following command: db.disableFreeMonitoring() --- > use testfiles switched to db testfiles > db.getCollection(' fs.files').find().pretty() { "_id" : ObjectId("636b54a92f0ddd638f185e8e"), "filename" : "GridFS_new.mp4", "length" : NumberLong(47780752), "chunkSize" : 358400, "uploadDate" : ISODate("2022-11-09T07:20:10.709Z"), "md5" : "8c36ca6ecc0065ca1ec5278b1ad0ccd6" } >
(4)删除文件
验证是否删除成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 [root@localhost datafile]# mongofiles --port=27017 -d testfiles list 2022-11-09T15:36:52.141+0800 connected to: mongodb://localhost:27017/ [root@localhost datafile]# [root@localhost ~]# mongo --port=27017 MongoDB shell version v4.2.18 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("7441b7ce-b624-4374-9a9a-4b126319dbe2" ) } MongoDB server version: 4.2.18 Server has startup warnings: 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always' . 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2022-11-09T11:13:31.877+0800 I CONTROL [initandlisten] --- Enable MongoDB's free cloud-based monitoring service, which will then receive and display metrics about your deployment (disk utilization, CPU, operation statistics, etc). The monitoring data will be available on a MongoDB website with a unique URL accessible to you and anyone you share the URL with. MongoDB may use this information to make product improvements and to suggest MongoDB products and deployment options to you. To enable free monitoring, run the following command: db.enableFreeMonitoring() To permanently disable this reminder, run the following command: db.disableFreeMonitoring() --- > use testfiles switched to db testfiles > db.getCollection(' fs.files').find().pretty() >
十五、键值对存储数据库Redis Redis的概述 Redis简介 Re mote Di ctionary S erver,简称Redis,即远程字典服务器 ,它是一个开源的、高性能的、基于键值对 的缓存与存储数据库,并且通过提供多种键值数据结构来适应不同场景下的缓存与存储需求。是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。免费和开源!
Redis能干什么? 1、内存存储、持久化,内存中是断电即失、所以说持久化很重要(两种持久化策略:rdb、aof) 2、效率高,可以用于高速缓存 3、发布订阅系统 4、地图信息分析 5、计时器、计数器(浏览量!) 6、……..
学习中需要用到的东西 1、官网:https://redis.io 2、 3、中文网:http://www.redis.cn/ 4、下载地址:通过官网下载即可!
Redis推荐都是在Linux服务器上搭建的,我们是基于Linux学习!
Redis支持的数据结构 Redis数据库提供了多种数据结构,其中最常见的数据结构(五大数据类型,放在安装redis环境之后讲)有String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset/Sorted Sets(有序集合)。
我们会在7.4 使用redis-cli操作五大数据类型中具体讲解。
Redis的部署 基于Linux平台 1、拷贝或下载安装包! redis-6.2.6.tar.gz
2、解压Redis的安装包!
1 2 3 4 5 6 7 8 [root@localhost ~]# cd /opt/ [root@localhost opt]# ll 总用量 132800 drwxr-xr-x 3 root root 135 3月 4 15:21 mongodb-linux-x86_64-rhel70-4.2.18 -rw-r--r-- 1 root root 133508918 2月 22 10:13 mongodb-linux-x86_64-rhel70-4.2.18.tgz -rw-r--r-- 1 root root 2476542 2月 22 10:06 redis-6.2.6.tar.gz drwxr-xr-x. 3 root root 26 2月 21 22:25 rh [root@localhost opt]# tar -zxvf redis-6.2.6.tar.gz
3、进入解压后的文件,可以看到我们redis的配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 [root@localhost opt]# cd redis-6.2.6/ [root@localhost redis-6.2.6]# ll 总用量 236 -rw-rw-r-- 1 root root 33624 10月 4 2021 00-RELEASENOTES -rw-rw-r-- 1 root root 51 10月 4 2021 BUGS -rw-rw-r-- 1 root root 5026 10月 4 2021 CONDUCT -rw-rw-r-- 1 root root 3384 10月 4 2021 CONTRIBUTING -rw-rw-r-- 1 root root 1487 10月 4 2021 COPYING drwxrwxr-x 7 root root 145 10月 4 2021 deps -rw-rw-r-- 1 root root 11 10月 4 2021 INSTALL -rw-rw-r-- 1 root root 151 10月 4 2021 Makefile -rw-rw-r-- 1 root root 6888 10月 4 2021 MANIFESTO -rw-rw-r-- 1 root root 21567 10月 4 2021 README.md -rw-rw-r-- 1 root root 93724 10月 4 2021 redis.conf -rwxrwxr-x 1 root root 275 10月 4 2021 runtest -rwxrwxr-x 1 root root 279 10月 4 2021 runtest-cluster -rwxrwxr-x 1 root root 1079 10月 4 2021 runtest-moduleapi -rwxrwxr-x 1 root root 281 10月 4 2021 runtest-sentinel -rw-rw-r-- 1 root root 13768 10月 4 2021 sentinel.conf drwxrwxr-x 3 root root 4096 10月 4 2021 src drwxrwxr-x 11 root root 182 10月 4 2021 tests -rw-rw-r-- 1 root root 3055 10月 4 2021 TLS.md drwxrwxr-x 9 root root 4096 10月 4 2021 utils
4、基本的环境安装
1 2 3 4 5 6 7 8 9 10 11 [root@Server01 ~]# gcc -v Using built-in specs. COLLECT_GCC=gcc OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-redhat-linux Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/opt/rh/gcc-toolset-11/root/usr --mandir=/opt/rh/gcc-toolset-11/root/usr/share/man --infodir=/opt/rh/gcc-toolset-11/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-linux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) [root@Server01 ~]#
如果gcc的版本比较低,则安装新版本的gcc
(注意:联网情况下最后升级到最新版本、如果使用本地yum源,安装redis6以上版本必须升级gcc)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 [root@Server01 ~]# yum install gcc-c++ [root@Server01 ~]# gcc -v 使用内建 specs。 COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 目标:x86_64-redhat-linux 配置为:../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux 线程模型:posix gcc 版本 8.5.0 20210514 (Red Hat 8.5.0-4) (GCC) 1.更新yum源为阿里云的源 [root@Server01 opt]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo --2023-08-30 22:56:18-- http://mirrors.aliyun.com/repo/Centos-8.repo 正在解析主机 mirrors.aliyun.com (mirrors.aliyun.com)... 121.29.38.206, 220.194.69.111, 119.188.91.238, ... 正在连接 mirrors.aliyun.com (mirrors.aliyun.com)|121.29.38.206|:80... 已连接。 已发出 HTTP 请求,正在等待回应... 200 OK 长度:2590 (2.5K) [application/octet-stream] 正在保存至: “/etc/yum.repos.d/CentOS-Base.repo” /etc/yum.repos.d/CentOS-Base.repo 100%[=======================================================================================================>] 2.53K --.-KB/s 用时 0s 2023-08-30 22:56:18 (192 MB/s) - 已保存 “/etc/yum.repos.d/CentOS-Base.repo” [2590/2590]) 2.centos8下,和centos7不同的是,devtoolset改为了gcc-toolset,这里使用gcc-toolset 1)查看可用的gcc-toolset列表 [root@Server01 opt]# yum list | grep gcc-toolset 2)安装gcc-toolset-11 [root@Server01 opt]# yum -y install gcc-toolset-11-gcc gcc-toolset-11-gcc-c++ gcc-toolset-11-binutils 上次元数据过期检查:0:02:19 前,执行于 2023年08月30日 星期三 22时56分38秒。 软件包 gcc-toolset-11-gcc-11.2.1-1.2.el8_5.x86_64 已安装。 软件包 gcc-toolset-11-gcc-c++-11.2.1-1.2.el8_5.x86_64 已安装。 软件包 gcc-toolset-11-binutils-2.36.1-1.el8_5.1.x86_64 已安装。 依赖关系解决。 无需任何处理。 完毕! [root@Server01 opt]# gcc -v 使用内建 specs。 COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/8/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 目标:x86_64-redhat-linux 配置为:../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --disable-libmpx --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux 线程模型:posix gcc 版本 8.5.0 20210514 (Red Hat 8.5.0-4) (GCC) [root@Server01 opt]# scl enable gcc-toolset-11 bash [root@Server01 opt]# gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/opt/rh/gcc-toolset-11/root/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-redhat-linux Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/opt/rh/gcc-toolset-11/root/usr --mandir=/opt/rh/gcc-toolset-11/root/usr/share/man --infodir=/opt/rh/gcc-toolset-11/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-linux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC) 3) 使用gcc11版本(需要注意的是scl命令启用只是临时的,退出shell或重启就会恢复原系统gcc版本。) echo "source /opt/rh/gcc-toolset-11/enable" >>/etc/profile 这样退出shell重新打开就是新版的gcc了
5、在redis-6.2.6目录下再次执行make命令(make 是用来编译的,它从Makefile中读取指令,然后编译。需要运行一些时间,等待即可。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@localhost redis-6.2.6]# make cd src && make allmake[1]: 进入目录“/opt/redis-6.2.6/src” CC Makefile.dep make[1]: 离开目录“/opt/redis-6.2.6/src” make[1]: 进入目录“/opt/redis-6.2.6/src” …… LINK redis-server INSTALL redis-sentinel CC redis-cli.o CC cli_common.o LINK redis-cli CC redis-benchmark.o LINK redis-benchmark INSTALL redis-check-rdb INSTALL redis-check-aof Hint: It's a good idea to run ' make test ' ;) make[1]: 离开目录“/opt/redis-6.2.6/src” [root@localhost redis-6.2.6]#
注意:如果没有准备好C语言编译环境,make 会报错—Jemalloc/jemalloc.h:没有那个文件;解决方案:运行make distclean后,再次执行make
6、跳过make test 继续执行: make install;redis的默认安装路径 /usr/local/bin
这里我们可以加上选项 PREFIX=/usr/local/redis 来指定具体的安装路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@localhost redis-6.2.6]# make install PREFIX=/usr/local/redis cd src && make installmake[1]: 进入目录“/opt/redis-6.2.6/src” CC Makefile.dep make[1]: 离开目录“/opt/redis-6.2.6/src” make[1]: 进入目录“/opt/redis-6.2.6/src” Hint: It's a good idea to run ' make test ' ;) INSTALL redis-server INSTALL redis-benchmark INSTALL redis-cli make[1]: 离开目录“/opt/redis-6.2.6/src” [root@localhost redis-6.2.6]# ll /usr/local/redis/bin/ 总用量 24988 -rwxr-xr-x 1 root root 6563376 4月 14 23:25 redis-benchmark lrwxrwxrwx 1 root root 12 4月 14 23:25 redis-check-aof -> redis-server lrwxrwxrwx 1 root root 12 4月 14 23:25 redis-check-rdb -> redis-server -rwxr-xr-x 1 root root 6805528 4月 14 23:25 redis-cli lrwxrwxrwx 1 root root 12 4月 14 23:25 redis-sentinel -> redis-server -rwxr-xr-x 1 root root 12211832 4月 14 23:25 redis-server
7、将redis配置文件。复制到我们当前目录下在创建一个自定义目录用于存储redis配置文件
1 2 3 4 5 6 7 [root@localhost redis-6.2.6]# mkdir /usr/local/redis/etc/ [root@localhost redis-6.2.6]# cp /opt/redis-6.2.6/redis.conf /usr/local/redis/etc/ [root@localhost redis-6.2.6]# cd /usr/local/redis/etc/ [root@localhost etc]# ll 总用量 92 -rw-r--r-- 1 root root 93724 4月 14 23:30 redis.conf [root@localhost etc]#
8、我们之后就使用这个配置文件进行启动,注意redis默认不是后台启动的,后台启动设置daemonize no改成yes。 vi修改配置文件!
1 [root@localhost etc]# vi redis.conf
连接外网首先有在redis.conf改几个设置
1.配置redis为后台启动:将daemonize no 改成daemonize yes
2.注释 bind 127.0.0.1
3.配置远程访问:将protected-mode yes 改为 no。关闭protected-mode模式,此时外部网络可以直接访问。
其次看一下自己防火墙对端口号开没开放
1 2 [root@localhost etc]# firewall-cmd --query-port=6379/tcp FirewallD is not running
9、启动Redis服务,并查看redis的进程是否开启!
此时未配置环境变量,因此会出现bash: redis-server: 未找到命令…的现象。需要使用绝对路径+命令来执行操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 [root@Server01 bin]# cd /usr/local/redis/bin/ [root@Server01 bin]# ll 总用量 23720 -rwxr-xr-x 1 root root 6069712 8月 30 23:04 redis-benchmark lrwxrwxrwx 1 root root 12 8月 30 23:04 redis-check-aof -> redis-server lrwxrwxrwx 1 root root 12 8月 30 23:04 redis-check-rdb -> redis-server -rwxr-xr-x 1 root root 6311024 8月 30 23:04 redis-cli lrwxrwxrwx 1 root root 12 8月 30 23:04 redis-sentinel -> redis-server -rwxr-xr-x 1 root root 11903144 8月 30 23:04 redis-server [root@Server01 bin]# cd .. [root@Server01 redis]# ll 总用量 0 drwxr-xr-x 2 root root 134 8月 30 23:04 bin drwxr-xr-x 2 root root 24 8月 30 23:10 etc [root@Server01 redis]# cd etc/ [root@Server01 etc]# ll 总用量 92 -rw-r--r-- 1 root root 93725 8月 30 23:10 redis.conf [root@Server01 etc]# cd /usr/local/redis/bin/ [root@Server01 bin]# ll 总用量 23720 -rwxr-xr-x 1 root root 6069712 8月 30 23:04 redis-benchmark lrwxrwxrwx 1 root root 12 8月 30 23:04 redis-check-aof -> redis-server lrwxrwxrwx 1 root root 12 8月 30 23:04 redis-check-rdb -> redis-server -rwxr-xr-x 1 root root 6311024 8月 30 23:04 redis-cli lrwxrwxrwx 1 root root 12 8月 30 23:04 redis-sentinel -> redis-server -rwxr-xr-x 1 root root 11903144 8月 30 23:04 redis-server [root@Server01 bin]# redis-server /usr/local/redis/etc/redis.conf bash: redis-server: 未找到命令... 安装软件包“redis”以提供命令“redis-server”? [N/y] n [root@Server01 bin]# /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf [root@Server01 bin]# ps -ef | grep redis root 8353 1 0 23:14 ? 00:00:00 /usr/local/redis/bin/redis-server *:6379 root 8367 3744 0 23:14 pts/0 00:00:00 grep --color=auto redis [root@Server01 bin]#
10、使用redis-cli 进行连接测试!
由于每次执行脚本都要到指定目录,很麻烦,所以可以配置环境变量,后面需要使用redis命令就可以全局操作。具体步骤如下:
编辑环境变量配置文件: vim /etc/profile 按 i 进入编辑模式 光标移至最后一行 开始添加 如下所示
编辑完成之后按 ESC 输入 wq 保存并退出 刷新配置信息: source /etc/profile
1 2 3 4 5 6 7 [root@localhost bin]# vi /etc/profile export REDIS_HOME=/usr/local/redisexport PATH=$PATH :$REDIS_HOME /bin[root@localhost bin]# [root@localhost bin]# source /etc/profile
此时在任意目录下 都可以执行redis相关命令
1 2 3 4 5 6 7 8 [root@localhost bin]# cd [root@localhost ~]# redis-cli -p 6379 127.0.0.1:6379> 127.0.0.1:6379> ping PONG 127.0.0.1:6379> keys * (empty array) 127.0.0.1:6379>
11、如何关闭Redis服务呢? shutdown
1 2 3 4 127.0.0.1:6379> SHUTDOWN not connected> not connected> exit [root@localhost ~]#
12、再次查看进程是否存在
1 2 [root@localhost ~]# ps -ef | grep redis root 13365 7546 0 00:12 pts/0 00:00:00 grep --color=auto redis
13、redis-benchmark 是一个压力测试工具!官方自带的性能测试工具!redis-benchmark 命令参数!
测试:100个并发连接 100000请求 启动服务,另开一个终端,键入以下指令做测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 [root@localhost ~]# redis-server /usr/local/redis/etc/redis.conf [root@localhost ~]# ps -ef | grep redis root 13574 1 0 00:22 ? 00:00:00 redis-server *:6379 root 13590 7546 0 00:22 pts/0 00:00:00 grep --color=auto redis [root@localhost ~]# redis-benchmark -h localhost -p 6379 -c 100 -n 100000 …… …… …… ====== SET ====== 100000 requests completed in 3.24 seconds 100 parallel clients 3 bytes payload keep alive: 1 host configuration "save" : 3600 1 300 100 60 10000 host configuration "appendonly" : no multi-thread: no Latency by percentile distribution: 0.000% <= 0.279 milliseconds (cumulative count 3) 50.000% <= 1.791 milliseconds (cumulative count 50717) 75.000% <= 2.007 milliseconds (cumulative count 75563) 87.500% <= 2.175 milliseconds (cumulative count 87538) 93.750% <= 2.431 milliseconds (cumulative count 93750) 96.875% <= 2.775 milliseconds (cumulative count 96921) 98.438% <= 3.231 milliseconds (cumulative count 98441) 99.219% <= 3.639 milliseconds (cumulative count 99228) 99.609% <= 4.215 milliseconds (cumulative count 99614) 99.805% <= 4.799 milliseconds (cumulative count 99806) 99.902% <= 6.687 milliseconds (cumulative count 99903) 99.951% <= 8.071 milliseconds (cumulative count 99952) 99.976% <= 8.839 milliseconds (cumulative count 99976) 99.988% <= 9.287 milliseconds (cumulative count 99988) 99.994% <= 9.679 milliseconds (cumulative count 99994) 99.997% <= 9.823 milliseconds (cumulative count 99997) 99.998% <= 9.911 milliseconds (cumulative count 99999) 99.999% <= 9.951 milliseconds (cumulative count 100000) 100.000% <= 9.951 milliseconds (cumulative count 100000) Cumulative distribution of latencies: 0.000% <= 0.103 milliseconds (cumulative count 0) 0.014% <= 0.303 milliseconds (cumulative count 14) 0.100% <= 0.407 milliseconds (cumulative count 100) 0.140% <= 0.503 milliseconds (cumulative count 140) 0.207% <= 0.607 milliseconds (cumulative count 207) 0.325% <= 0.703 milliseconds (cumulative count 325) 0.451% <= 0.807 milliseconds (cumulative count 451) 0.772% <= 0.903 milliseconds (cumulative count 772) 1.542% <= 1.007 milliseconds (cumulative count 1542) 3.306% <= 1.103 milliseconds (cumulative count 3306) 7.964% <= 1.207 milliseconds (cumulative count 7964) 15.719% <= 1.303 milliseconds (cumulative count 15719) 24.654% <= 1.407 milliseconds (cumulative count 24654) 30.889% <= 1.503 milliseconds (cumulative count 30889) 36.521% <= 1.607 milliseconds (cumulative count 36521) 42.625% <= 1.703 milliseconds (cumulative count 42625) 52.428% <= 1.807 milliseconds (cumulative count 52428) 63.709% <= 1.903 milliseconds (cumulative count 63709) 75.563% <= 2.007 milliseconds (cumulative count 75563) 83.583% <= 2.103 milliseconds (cumulative count 83583) 98.112% <= 3.103 milliseconds (cumulative count 98112) 99.563% <= 4.103 milliseconds (cumulative count 99563) 99.829% <= 5.103 milliseconds (cumulative count 99829) 99.877% <= 6.103 milliseconds (cumulative count 99877) 99.916% <= 7.103 milliseconds (cumulative count 99916) 99.953% <= 8.103 milliseconds (cumulative count 99953) 99.982% <= 9.103 milliseconds (cumulative count 99982) 100.000% <= 10.103 milliseconds (cumulative count 100000) Summary: throughput summary: 30826.14 requests per second latency summary (msec): avg min p50 p95 p99 max 1.779 0.272 1.791 2.535 3.495 9.951
使用redis-cli操作Redis 基础知识 redis默认有16个数据库
默认使用的是第0个可以使用 select 进行切换数据库!
清除当前数据库 flushdb
清除全部数据库的内容 FLUSHALL
Redis 是单线程 的!
明白Redis是很快的,官方表示,Redis是基于内存操作 ,CPU不是Redis性能瓶颈,Redis的瓶颈 是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了!
Redis 是C 语言写的,官方提供的数据为 100000+ 的QPS,完全不比同样是使用 key-vale的Memecache差!
Redis 为什么单线程还这么快?
误区1:高性能的服务器一定是多线程的?
误区2:多线程(CPU上下文会切换!)一定比单线程效率高!
先去CPU>内存>硬盘的速度要有所了解!
核心:redis 是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换:耗时的操作!!!),对于内存系统来说,如果没有上下文切换效率就是最高的! 多次读写都是在一个CPU上的,在内存情况下,这个就是最佳的方案!
五大数据类型
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件MQ。 它支持多种类型的数据结构,如 字符串 (strings), 散列 (hashes), 列表 (lists), 集合 (sets), 有序集合 (sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。
Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(high availability)。
我们现在讲解的所有命令大家一定要全部记住,后面我们使用SpringBoot、Jedis,所有的方法就是这些命令!
0 操作键 Redis键操作是Redis数据库中非常重要和常用的操作。下面,通过一张表来介绍一下常用的Redis键操作命令及相关说明,具体如表所示。
操作命令
相关说明
SET
为指定键设置值
MSET
为多个键设置值
KEYS
查找所有符合给定模式pattern(正则表达式)的键
GET
获取指定键的值
MGET
获取多个键的对应值
DUMP
序列化指定的键,并返回被序列化的值
EXISTS
判断指定键是否存在
TYPE
查看指定键的类型
RENAME
删除指定键的值
EXPIRE
设置指定键的生存时间,以秒计
TTL
返回指定键的剩余生存时间
PERSIST
移除键的生存时间
DEL
在键存在时,删除key
Redis-key
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 [root@localhost ~]# redis-server /usr/local/redis/etc/redis.conf [root@localhost ~]# ps -ef | grep redis root 7670 1 1 20:20 ? 00:00:00 redis-server *:6379 root 7687 7602 0 20:20 pts/0 00:00:00 grep --color=auto redis [root@localhost ~]# redis-cli 127.0.0.1:6379> ping PONG 127.0.0.1:6379> set company itcast OK 127.0.0.1:6379> set company0 itcast0 EX 20 OK 127.0.0.1:6379> ttl company0 18 127.0.0.1:6379> ttl company0 7 127.0.0.1:6379> ttl company0 -2 127.0.0.1:6379> get company itcast 127.0.0.1:6379> MSET brand1 "heima" brand2 "chuanzhihui" brand3 "kudingyu" brand4 "boxuegu" brand5 "czzxxy" brand6 "yuanxiaobang" OK 127.0.0.1:6379> keys * company brand1 brand2 brand4 brand6 brand5 brand3 127.0.0.1:6379> MGET brand1 brand2 brand3 brand heima chuanzhihui kudingyu (nil) 127.0.0.1:6379> dump company "\x00\x06itcast\t\x00\x05\x99\x0bu\x97\x8d\xd4\xc1" 127.0.0.1:6379> EXISTS brand6 (integer ) 1 127.0.0.1:6379> EXISTS brand7 (integer ) 0 127.0.0.1:6379> type company string 127.0.0.1:6379> rename company newcompany OK 127.0.0.1:6379> keys * 1) "brand1" 2) "brand2" 3) "brand4" 4) "brand6" 5) "newcompany" 6) "brand5" 7) "brand3" 127.0.0.1:6379> expire brand6 30 (integer ) 1 127.0.0.1:6379> ttl brand6 (integer ) 12 127.0.0.1:6379> ttl brand6 (integer ) -2 127.0.0.1:6379> keys * 1) "brand1" 2) "brand2" 3) "brand4" 4) "newcompany" 5) "brand5" 6) "brand3" 127.0.0.1:6379> expire brand5 60 (integer ) 1 127.0.0.1:6379> ttl brand5 (integer ) 56 127.0.0.1:6379> persist brand5 (integer ) 1 127.0.0.1:6379> ttl brand5 (integer ) -1 127.0.0.1:6379> DEL brand5 (integer ) 1 127.0.0.1:6379> keys * 1) "brand1" 2) "brand2" 3) "brand4" 4) "newcompany" 5) "brand3"
后面如果遇到不会的命令,可以在官网查看帮助文档!https://www.redis.net.cn/order/
1 操作String字符串 String字符串是Redis中最基本也是最简单的数据结构,其值是二进制安全的,值的数据类型可以为数字、文本、图片、视频或者序列化的对象等,值的最大长度不能超过512M。
将图中的Bookid看作是编程语言中的字符串变量名,那么100020就是该变量名的值。
操作命令
相关说明
SET
为指定字符串键设置值
MSET
为多个字符串键设置值
GET
获取指定字符串key中的值
MGET
获取多个字符串键的对应值
GETSET
获取指定字符串键的旧值并设置新值
STRLEN
获取字符串值的字节长度
GETRANGE
获取字符串键指定索引范围的值内容
SETRANGE
为字符串键的指定索引位置设置值
APPEND
追加新内容到值的末尾
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 127.0.0.1:6379> set website "www.itcast.cn" OK 127.0.0.1:6379> setnx mykey "redis" (integer ) 1 127.0.0.1:6379> set mykey "mongodb" OK 127.0.0.1:6379> get mykey "mongodb" 127.0.0.1:6379> setnx mykey "HBase" (integer ) 0 127.0.0.1:6379> get mykey "mongodb" 127.0.0.1:6379> 127.0.0.1:6379> mset website1 "www.itheima.com" website2 "www.boxuegu.com" website3 "www.ityxb.com" OK 127.0.0.1:6379> get website "www.itcast.cn" 127.0.0.1:6379> mget website1 website2 website3 website5 1) "www.itheima.com" 2) "www.boxuegu.com" 3) "www.ityxb.com" 4) (nil) 127.0.0.1:6379> mset name "xiaoming" age "18" id "123456789" OK 127.0.0.1:6379> mget name age id 1) "xiaoming" 2) "18" 3) "123456789" 127.0.0.1:6379> msetnx name "xiaoming" grade "A" (integer ) 0 127.0.0.1:6379> msetnx class "21.19" grade "B" (integer ) 1 127.0.0.1:6379> mget name age id class grade 1) "xiaoming" 2) "18" 3) "123456789" 4) "20.18" 5) "A" 127.0.0.1:6379> 127.0.0.1:6379> getset website4 "www.kudingyu.com" (nil) 127.0.0.1:6379> getset website4 "www.itczh.com" "www.kudingyu.com" 127.0.0.1:6379> get website4 "www.itczh.com" 127.0.0.1:6379> strlen website4 (integer ) 13 127.0.0.1:6379> getrange website 4 9 "itcast" 127.0.0.1:6379> get website "www.itcast.cn" 127.0.0.1:6379> setrange website 4 "nosql" (integer ) 13 127.0.0.1:6379> get website "www.nosqlt.cn" 127.0.0.1:6379> append website "itcast" (integer ) 19 127.0.0.1:6379> get website "www.nosqlt.cnitcast" 127.0.0.1:6379> set user:1 {name:zhangsan,age:3,id :6789} OK 127.0.0.1:6379> get user:1 "{name:zhangsan,age:3,id:6789}" 127.0.0.1:6379> MSET user:2:name xiaoming user:2:age 3 user:2:id 1234 OK 127.0.0.1:6379> get user:2 (nil) 127.0.0.1:6379> get user:2:name "xiaoming" 127.0.0.1:6379> get user:2:age "3" 127.0.0.1:6379> get user:2:id "1234" 127.0.0.1:6379>
现在学习的key,相当于以后的方法
String类似的使用场景:value除了是我们的字符串还可以是我们的数字!
计数器
统计多单位的数量
粉丝数
对象缓存存储!
比如:设置过期时间,相当于定期持久化
2 操作List列表 List列表是由若干个字符串元素组成的集合,并且每个字符串元素都是按照插入顺序排序的。我们也可以将列表理解为多个字符串组成一个集合对象,并按照链表(Link List)的插入顺序排序,在读写操作时只能从其头部或尾部开始,而不能从中间开始。
LBookid为列表的键名,100020、100021、100022、100022均为列表中键的值,这些值均按照插入顺序排列,其中100020是列表中的第一个字符串元素、100021是列表中的第二个元素、100022是列表中的第三个元素、100022是列表中的第四个元素(也是尾部元素)。由于List列表中允许出现重复的元素 ,因此List列表中的第三个元素和第四个元素均为100022。
List列表是一种线性的有序结构,Redis为List列表提供了相关的操作命令。下面,通过一张表来介绍一下常用的List操作命令及相关说明,具体如表所示。
操作命令
相关说明
RPUSH
将一个或多个元素推入到列表的右端
LPUSH
将一个或多个元素推入到列表的左端
LRANGE
获取列表指定索引范围内的元素
LINDEX
获取列表指定索引位置上的元素
RPOP
弹出列表最右端的元素
LPOP
弹出列表最左端的元素
LLEN
获取指定列表的长度
LREM
移除列表中的指定元素
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边) 或者尾部(右边)
一个列表最多可以包含 2 32 - 1 个元素 (4294967295, 每个列表超过40亿个元素,2的32次方-1也就是大概四亿键值对)。
在redis里面,我们可以把list玩成 ,
头进尾出,就是栈;
头进头出,就是队列;
两边都打开,都可进可取,就是阻塞队列!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 127.0.0.1:6379> rpush color "blue" (integer ) 1 127.0.0.1:6379> rpush color "green" (integer ) 2 127.0.0.1:6379> rpush color "purple" (integer ) 3 127.0.0.1:6379> rpush color "red" (integer ) 4 127.0.0.1:6379> rpush color "white" (integer ) 5 127.0.0.1:6379> lrange color 0 -1 1) "blue" 2) "green" 3) "purple" 4) "red" 5) "white" 127.0.0.1:6379> lpush color "apple" (integer ) 6 127.0.0.1:6379> lpush color "banana" (integer ) 7 127.0.0.1:6379> lpush color "mango" (integer ) 8 127.0.0.1:6379> lrange color 0 -1 1) "mango" 2) "banana" 3) "apple" 4) "blue" 5) "green" 6) "purple" 7) "red" 8) "white" 127.0.0.1:6379> lrange color 0 7 1) "mango" 2) "banana" 3) "apple" 4) "blue" 5) "green" 6) "purple" 7) "red" 8) "white" 127.0.0.1:6379> lindex color 3 "blue" 127.0.0.1:6379> rpop color "white" 127.0.0.1:6379> lrange color 0 -1 1) "mango" 2) "banana" 3) "apple" 4) "blue" 5) "green" 6) "purple" 7) "red" 127.0.0.1:6379> lpop color "mango" 127.0.0.1:6379> lrange color 0 -1 1) "banana" 2) "apple" 3) "blue" 4) "green" 5) "purple" 6) "red" 127.0.0.1:6379> llen color (integer ) 6 127.0.0.1:6379> rpush mycolor "hello" "hello" "world" "hello" (integer ) 4 127.0.0.1:6379> lrange mycolor 0 -1 1) "hello" 2) "hello" 3) "world" 4) "hello" 127.0.0.1:6379> lrem mycolor -2 hello (integer ) 2 127.0.0.1:6379> lrange mycolor 0 -1 1) "hello" 2) "world" 127.0.0.1:6379> lrange color 0 -1 1) "banana" 2) "apple" 3) "blue" 4) "green" 5) "purple" 6) "red" 127.0.0.1:6379> LTRIM color 1 4 OK 127.0.0.1:6379> lrange color 0 -1 1) "apple" 2) "blue" 3) "green" 4) "purple" 127.0.0.1:6379> LPUSH order zhangsan (integer ) 1 127.0.0.1:6379> LPUSH order lisi (integer ) 2 127.0.0.1:6379> LPUSH order wangwu (integer ) 3 127.0.0.1:6379> LPUSH order zhaoliu (integer ) 4 127.0.0.1:6379> LRANGE order 0 -1 1) "zhaoliu" 2) "wangwu" 3) "lisi" 4) "zhangsan" 127.0.0.1:6379> RPOPLPUSH order paylist "zhangsan" 127.0.0.1:6379> LRANGE paylist 0 -1 1) "zhangsan" 127.0.0.1:6379> 127.0.0.1:6379> EXISTS mycolor (integer ) 1 127.0.0.1:6379> lrange mycolor 0 -1 1) "hello" 2) "world" 127.0.0.1:6379> LPUSH mycolor value (integer ) 3 127.0.0.1:6379> lrange mycolor 0 -1 1) "value" 2) "hello" 3) "world" 127.0.0.1:6379> LSET mycolor 0 newvalue OK 127.0.0.1:6379> lrange mycolor 0 -1 1) "newvalue" 2) "hello" 3) "world" 127.0.0.1:6379> LSET mycolor 4 newworld (error) ERR index out of range 127.0.0.1:6379> LSET mycolor 2 newworld OK 127.0.0.1:6379> lrange mycolor 0 -1 1) "newvalue" 2) "hello" 3) "newworld" 127.0.0.1:6379> 127.0.0.1:6379> lrange mycolor 0 -1 1) "newvalue" 2) "hello" 3) "newworld" 127.0.0.1:6379> LINSERT mycolor before newworld my (integer ) 4 127.0.0.1:6379> LINSERT mycolor after newworld welcome (integer ) 5 127.0.0.1:6379> lrange mycolor 0 -1 1) "newvalue" 2) "hello" 3) "my" 4) "newworld" 5) "welcome"
小结:
实际上是一个双向链表,before Node after , left,right 都可以插入值
如果 key 不存在,插入即可创建新的链表
如果 key 存在,插入即可新增内容
如果移除了所有值,就是空链表,也就是没有节点,也代表不存在!
在两边插入或者改动值,效率最高! 如果链表很长,你要操作中间元素,相对来说效率会低一点~(更适合分布式)
消息排队!消息队列 (Lpush Rpop), 栈( Lpush Lpop)!
3 操作Sets集合 Set集合由不重复且无序 的字符串元素组成的,其中,**不重复 意味着一个集合中的所有字符串都是唯一的,这是与List列表的第一个区别; 无序 **意味着所有字符串的读写是任意位置的,而List列表中元素的读写必须要从头部或尾部开始操作,因此,这是与List列表的第二个区别。
SBookid为集合的键名,100021、100022、100020、100023均为集合中键的值。由于Set集合中不允许出现重复的元素,因此Set集合中的元素均是唯一的,并且元素都是无序的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 127.0.0.1:6379> sadd databases "redis" "mongodb" "hbase" (integer ) 3 127.0.0.1:6379> scard databases (integer ) 3 127.0.0.1:6379> smembers databases 1) "hbase" 2) "mongodb" 3) "redis" 127.0.0.1:6379> sismember databases redis (integer ) 1 127.0.0.1:6379> srem databases hbase (integer ) 1 127.0.0.1:6379> smembers databases 1) "mongodb" 2) "redis" 127.0.0.1:6379> sadd databasesNew "mysql" (integer ) 1 127.0.0.1:6379> SMOVE databases databasesNew redis (integer ) 1 127.0.0.1:6379> SMEMBERS databasesNew 1) "mysql" 2) "redis" 127.0.0.1:6379> SMEMBERS databases 1) "mongodb" 127.0.0.1:6379> 127.0.0.1:6379> sadd myroom zhangsan lisi wangwu zhaoliu (integer ) 4 127.0.0.1:6379> SMEMBERS myroom 1) "lisi" 2) "zhaoliu" 3) "wangwu" 4) "zhangsan" 127.0.0.1:6379> SRANDMEMBER myroom "zhaoliu" 127.0.0.1:6379> SRANDMEMBER myroom "zhangsan" 127.0.0.1:6379> SRANDMEMBER myroom "lisi" 127.0.0.1:6379> SRANDMEMBER myroom 2 1) "lisi" 2) "zhangsan" 127.0.0.1:6379> SRANDMEMBER myroom 2 1) "wangwu" 2) "zhaoliu" 127.0.0.1:6379> SMEMBERS myroom 1) "lisi" 2) "zhaoliu" 3) "wangwu" 4) "zhangsan" 127.0.0.1:6379> sadd myroom tom jacky john (integer ) 3 127.0.0.1:6379> SMEMBERS myroom 1) "zhangsan" 2) "zhaoliu" 3) "lisi" 4) "jacky" 5) "john" 6) "wangwu" 7) "tom" 127.0.0.1:6379> spop myroom "zhangsan" 127.0.0.1:6379> spop myroom 3 1) "jacky" 2) "lisi" 3) "tom" 127.0.0.1:6379> SMEMBERS myroom 1) "zhaoliu" 2) "john" 3) "wangwu" 127.0.0.1:6379> sadd zhoujielun "zhangsan" "lisi" "wangwu" (integer ) 3 127.0.0.1:6379> sadd chenyixun "lisi" "wangwu" "zhaoliu" (integer ) 3 127.0.0.1:6379> SMEMBERS zhoujielun 1) "lisi" 2) "wangwu" 3) "zhangsan" 127.0.0.1:6379> SMEMBERS chenyixun 1) "lisi" 2) "zhaoliu" 3) "wangwu" 127.0.0.1:6379> sdiff zhoujielun chenyixun 1) "zhangsan" 127.0.0.1:6379> sdiff chenyixun zhoujielun 1) "zhaoliu" 127.0.0.1:6379> sinter zhoujielun chenyixun 1) "lisi" 2) "wangwu" 127.0.0.1:6379> sunion zhoujielun chenyixun 1) "lisi" 2) "zhaoliu" 3) "wangwu" 4) "zhangsan"
4 操作Hash散列 Hash散列可以存储多个键值对之间的映射,属于无序的一种数据集合与字符串类似,Hash散列存储键的类型必须为字符串 ,而值的类型既可以是字符串也可以是数字,但是值必须是唯一的,不可重复。Hash散列的键之间可以采用“:”符号隔开,增加用户的可阅读性,并为用户提供更多的信息。
“Book:name”、“Book:id”、“Book:author”以及“Book:price”为散列的键名,“《格局》”、“100022”、“wujun”以及“45”均为散列中键对应的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 127.0.0.1:6379> hset article title "greeting" (integer ) 1 127.0.0.1:6379> hmset article content "Hello World" author "peter" OK 127.0.0.1:6379> hget article title "greeting" 127.0.0.1:6379> hmget article content author 1) "Hello World" 2) "peter" 127.0.0.1:6379> hgetall article 1) "title" 2) "greeting" 3) "content" 4) "Hello World" 5) "author" 6) "peter" 127.0.0.1:6379> hkeys article 1) "title" 2) "content" 3) "author" 127.0.0.1:6379> hvals article 1) "greeting" 2) "Hello World" 3) "peter" 127.0.0.1:6379> hdel article title (integer ) 1 127.0.0.1:6379> hgetall article 1) "content" 2) "Hello World" 3) "author" 4) "peter" 127.0.0.1:6379> hgetall article 1) "content" 2) "Hello World" 3) "author" 4) "peter" 127.0.0.1:6379> hlen article (integer ) 2 127.0.0.1:6379> HEXISTS article author (integer ) 1
5 操作Zset / Sorted Sets有序集合 Sorted Sets有序集合和散列类似,主要区别是有序集合是按照值进行自动排序的,而散列中的值是不排序的;有序集合可以直接对值进行操作,而散列是通过键来查找值。有序集合中的键必须是唯一的,但是值可以是重复的,而散列的值是唯一的。
有序集合是按照值的大小进行排序的,其中,“Book:id04”、“Book:id02”、“Book:id03”以及“Book:id01”为有序集合的键名,100021、100022、100023以及100023均为有序集合中键对应的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 127.0.0.1:6379> zadd salary 5000 "Peter" 3500 "Tom" 6000 "Jack" (integer ) 3 127.0.0.1:6379> zcard salary (integer ) 3 127.0.0.1:6379> zcount salary 2000 5000 (integer ) 2 127.0.0.1:6379> zrange salary 0 1 1) "Tom" 2) "Peter" 127.0.0.1:6379> zscore salary "Peter" "5000" 127.0.0.1:6379> zrem salary "Jack" (integer ) 1 127.0.0.1:6379> zrange salary 0 -1 1) "Tom" 2) "Peter" 127.0.0.1:6379> zadd 2022salary 5000 "zhangsan" 3500 "lisi" 6000 "wangwu" (integer ) 3 127.0.0.1:6379> zcard 2022salary (integer ) 3 127.0.0.1:6379> zrange 2022salary 0 -1 1) "lisi" 2) "zhangsan" 3) "wangwu" 127.0.0.1:6379> zcount 2022salary 1000 5000 (integer ) 2 127.0.0.1:6379> zrangebyscore 2022salary -inf +inf 1) "lisi" 2) "zhangsan" 3) "wangwu" 127.0.0.1:6379> zrevrange 2022salary 0 -1 1) "wangwu" 2) "zhangsan" 3) "lisi" 127.0.0.1:6379> zrangebyscore 2022salary -inf +inf withscores 1) "lisi" 2) "3500" 3) "zhangsan" 4) "5000" 5) "wangwu" 6) "6000" 127.0.0.1:6379> ZRANGEBYSCORE salary -inf 5000 withscores 1) "lisi" 2) "3500" 3) "zhangsan" 4) "5000" 127.0.0.1:6379> ZRANGEBYSCORE salary 5000 +inf withscores 1) "zhangsan" 2) "5000" 3) "wangwu" 4) "6000" 127.0.0.1:6379>
不同的是每个元素都会关联一个double类型的分数(score)。redis正是通过分数来为集合中的成员进行从小到大的排序。
score相同:按字典顺序排序
有序集合的成员是唯一的,但分数(score)却可以重复。
案例思路:set 多了一个排序,set能做的原则上zset都可以做。
1、存储班级成绩表,工资表排序!
2、带权重进行判断,普通消息标1, 重要消息 标2!
3、排行榜应用实现,比如B站,所有的播放量、评分全部放到有序集合中,然后进行遍历,设置每天凌晨刷新一次,取Top N 测试!
三种特殊数据类型 1 Geospatial(地理位置) 朋友的定位,附近的人,打车距离计算?
Redis 的 Geo 在Redis3.2 版本就推出了! 这个功能可以推算地理位置的信息,两地之间的距离,方圆几里的人
只有 六个命令:
官方文档:GEOADD | Redis
中文 :https://www.redis.net.cn/order/3685.html
使用经纬度定位地理坐标并用一个有序集合zset保存 ,所以zset命令也可以使用
命令
描述
geoadd key longitud(经度) latitude(纬度) member [..]
将具体经纬度的坐标存入一个有序集合
geopos key member [member..]
获取集合中的一个/多个成员坐标
geodist key member1 member2 [unit]
返回两个给定位置之间的距离。默认以米作为单位。
`georadius key longitude latitude radius m
km
GEORADIUSBYMEMBER key member radius...
功能与GEORADIUS相同,只是中心位置不是具体的经纬度,而是使用结合中已有的成员作为中心点。
geohash key member1 [member2..]
返回一个或多个位置元素的Geohash表示。使用Geohash位置52点整数编码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 ----------------geoadd--------------------- 规则:地球两极无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入! 有效的经度从-180度到180度。 有效的纬度从-85.05112878度到85.05112878度。 (error) ERR invalid longitude,latitude pair 39.900000,116.400000 127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing (integer ) 1 127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai (integer ) 1 127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian (integer ) 2 127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen (integer ) 2 ----------------geopos--------------------- 127.0.0.1:6379> GEOPOS china:city beijing 1) 1) "116.39999896287918091" 2) "39.90000009167092543" 127.0.0.1:6379> GEOPOS china:city beijing chongqing 1) 1) "116.39999896287918091" 2) "39.90000009167092543" 2) 1) "106.49999767541885376" 2) "29.52999957900659211" ----------------geodist--------------------- 指定单位的参数 **unit** 必须是以下单位的其中一个: m 表示单位为米。 km 表示单位为千米。 mi 表示单位为英里。 ft 表示单位为英尺。 127.0.0.1:6379> GEODIST china:city beijing shanghai km "1067.3788" 127.0.0.1:6379> GEODIST china:city beijing chongqing km "1464.0708" ----------------georadius--------------------- 我附近的人? (获得所有附近的人的地址,定位!)通过半径来查询! 获得指定数量的人,200 所有数据应该都录入:china:city ,才会让结果更加请求! withcoord:带上坐标; withdist:带上距离,单位与半径单位相同; COUNT n : 只显示前n个(按距离递增排序) 127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km 1) "chongqing" 2) "xian" 3) "shengzhen" 4) "hangzhou" 127.0.0.1:6379> GEORADIUS china:city 110 30 500 km 1) "chongqing" 2) "xian" 127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist 1) 1) "chongqing" 2) "341.9374" 2) 1) "xian" 2) "483.8340" 127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withcoord 1) 1) "chongqing" 2) 1) "106.49999767541885376" 2) "29.52999957900659211" 2) 1) "xian" 2) 1) "108.96000176668167114" 2) "34.25999964418929977" 127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist withcoord count 1 1) 1) "chongqing" 2) "341.9374" 3) 1) "106.49999767541885376" 2) "29.52999957900659211" 127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withdist withcoord count 2 1) 1) "chongqing" 2) "341.9374" 3) 1) "106.49999767541885376" 2) "29.52999957900659211" 2) 1) "xian" 2) "483.8340" 3) 1) "108.96000176668167114" 2) "34.25999964418929977" ----------------georadiusbymember--------------------- 127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km 1) "beijing" 2) "xian" 127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 400 km 1) "hangzhou" 2) "shanghai" 127.0.0.1:6379> ----------------geohash--------------------- 127.0.0.1:6379> geohash china:city beijing chongqing shanghai xian 1) "wx4fbxxfke0" 2) "wm5xzrybty0" 3) "wtw3sj5zbj0" 4) "wqj6zky6bn0" 127.0.0.1:6379> ZRANGE china:city 0 -1 1) "chongqing" 2) "xian" 3) "shengzhen" 4) "hangzhou" 5) "shanghai" 6) "beijing" 127.0.0.1:6379> ZREM china:city beijing
2 Hyperloglog(基数统计) 什么是基数?
A {1,3,5,7,8,7} B {1,3,5,7,8}
基数(不重复的元素) = 5,可以接受误差!0.81%错误率
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。
花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。如果用set存储用户ID,对服务器的负载太大。
因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
其底层使用string数据类型
什么是基数?
数据集中不重复的元素的个数。
应用场景:
网页的访问量(UV):页面访问量。一个用户多次访问,也只能算作一个人。
传统实现,set 保存用户的id, 然后每次进行比较。(垃圾代码)当用户变多之后这种方式及其浪费空间,而我们的目的只是计数 。
Hyperloglog就能帮助我们利用最小的空间完成。
命令
描述
PFADD key element1 [elememt2..]
添加指定元素到 HyperLogLog 中
PFCOUNT key [key]
返回给定 HyperLogLog 的基数估算值。
PFMERGE destkey sourcekey [sourcekey..]
将多个 HyperLogLog 合并为一个 HyperLogLog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ----------PFADD--PFCOUNT--------------------- 127.0.0.1:6379> PFADD myelemx a b c d e f g h i j k (integer ) 1 127.0.0.1:6379> type myelemx string 127.0.0.1:6379> PFCOUNT myelemx (integer ) 11 127.0.0.1:6379> PFADD myelemy i j k z m c b v p q s (integer ) 1 127.0.0.1:6379> PFCOUNT myelemy (integer ) 11 ----------------PFMERGE----------------------- 127.0.0.1:6379> PFMERGE myelemz myelemx myelemy OK 127.0.0.1:6379> PFCOUNT myelemz (integer ) 17
如果允许容错,那么一定可以使用Hyperloglog !
如果不允许容错,就使用set或者自己的数据类型即可 !
3 BitMaps(位图)
使用位存储,信息状态只有 0 和 1
Bitmap是一串连续的2进制数字(0或1),每一位所在的位置为偏移(offset),在bitmap上可执行AND,OR,XOR,NOT以及其它位操作。
应用场景
签到统计、状态统计
为什么其他教程都不喜欢讲这些?这些在生活中或者开发中,都有十分多的应用场景,学习了,就是就是多一个思路!
位存储
统计用户信息,活跃or不活跃! 登录or未登录! 点赞orXXX!公告已读or未读! 两个状态的,且不需要延迟保存的,都可以使用Bitmaps!这样数据库不会臃肿
统计疫情感染人数: 0 0 0 0 1 0 0(感染的用1 没有感染的用0),就可以快速的取出一个差值
Bitmap 位图,数据结构! 都是操作二进制位来进行记录,就只有0 和 1 两个状态!
365 天 = 365 bit 1字节 = 8bit 46 个字节左右!
使用bitmap 来记录 周一到周日的打卡!周一:1 周二:0 周三:0 周四:1 ……(java for循环可以搞定)
命令
描述
setbit key offset value
为指定key的offset位设置值
getbit key offset
获取offset位的值
bitcount key [start end]
统计字符串被设置为1的bit数,也可以指定统计范围按字节
bitop operration destkey key[key..]
对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
BITPOS key bit [start] [end]
返回字符串里面第一个被设置为1或者0的bit位。start和end只能按字节,不能按位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ------------setbit--getbit-------------- 使用bitmap 来记录 周一到周日的打卡! 周一:1 周二:0 周三:0 周四:1 ......(java for 循环可以搞定) 127.0.0.1:6379> setbit sign 0 1 (integer ) 0 127.0.0.1:6379> setbit sign 1 0 (integer ) 0 127.0.0.1:6379> setbit sign 2 0 (integer ) 0 127.0.0.1:6379> setbit sign 3 1 (integer ) 0 127.0.0.1:6379> setbit sign 4 1 (integer ) 0 127.0.0.1:6379> setbit sign 5 0 (integer ) 0 127.0.0.1:6379> setbit sign 6 0 (integer ) 0 127.0.0.1:6379> getbit sign 3 (integer ) 1 127.0.0.1:6379> getbit sign 6 (integer ) 0 --------------------bitcount------------------- 127.0.0.1:6379> bitcount sign (integer ) 3
使用Java操作Redis 创建项目 1、打开IDEA,新建一个project,可以选择Java项目或者Maven项目(推荐)。并添加项目名称并制定项目的存储路径。
下图为选择maven的设置
文件 pom.xml 参考代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion>4.0 .0 </modelVersion> <groupId>com.itcast.redis</groupId> <artifactId>nosql_chapter07</artifactId> <version>1.0 -SNAPSHOT</version> <!--导入jedis的包--> <dependencies> <!-- https: <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.2 .0 </version> </dependency> <!-- https: <dependency> <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> <version>1.6 </version> </dependency> <!-- https: <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> <version>1.3 </version> <scope>test</scope> </dependency> <!-- https: <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12 </version> <scope>test</scope> </dependency> <!-- https: <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2 .75 </version> </dependency> </dependencies> <properties> <maven.compiler.source>8 </maven.compiler.source> <maven.compiler.target>8 </maven.compiler.target> </properties> </project>
2、检查或修改该项目中Project和Modules的jdk版本,此处使用1.8版本
3、点击Settings-javac,检查或修改版本为8
1 2 3 4 5 6 7 8 <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!--修改Language level--> <maven.compiler.source>1.8</maven.compiler.source> <!--修改Java Compiler--> <maven.compiler.target>1.8</maven.compiler.target> </properties>
4、在项目pom.xml文件中导入对应的依赖jedis、fastjson、commons-pool、hamcrest-core、junit并选择对应的版本 可访问Maven网站进行查询https://mvnrepository.com/,例如jedis
或者复制代码后 联网重载maven
5、新建测试类
1 2 3 4 5 6 7 8 9 10 连接外网首先有在redis.conf改几个设置 1.daemonize yes 2.注释 bind 127.0.0.1 3.protected-mode no 其次看一下自己防火墙对端口号开没开放 firewall-cmd --query-port=6379/tcp 如果是yes 就是开放的 然后 redis-server etc/redis.conf redis-cli -h 自己外网端口号 -p 6379 最后ping一下如果pong就成功了
测试类Testping.java参考文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import redis.clients.jedis.Jedis;public class Testping { public static void main (String[] args) { Jedis jedis = new Jedis ("192.168.24.105" ,6379 ); String response = jedis.ping(); System.out.println("服务启动..." + response); jedis.flushDB(); jedis.set("name" ,"FeiBaobao" ); jedis.set("age" ,"28" ); System.out.println("当前数据库中的成员是:" + jedis.get("name" )); System.out.println("当前数据库中的成员的年龄是:" + jedis.get("age" )); } }
操作键 在test包下创建TestKeyOperate.java文件,该文件用于编写java操作Redis键的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 import org.junit.Test;import redis.clients.jedis.Jedis;import java.util.Iterator;import java.util.List;import java.util.Set;public class TestKeyOperate { private static Jedis jedis = new Jedis ("192.168.24.105" , 6379 ); public static void main (String[] args) { System.out.println("服务启动..." + jedis.ping()); jedis.flushDB(); } @Test public void setTest () { String key = jedis.set("company" , "itcast" ); System.out.println(key); } @Test public void msetTest () { String manyKey = jedis.mset("brand1" , "heima" , "brand2" , "chuanzhihui" , "brand3" , "kudingyu" ,"brand4" ,"boxuegu" ,"brand5" ,"czzxxy" ,"brand6" ,"yuanxiaobang" ); System.out.println(manyKey); } @Test public void keysTest () { Set<String> keys = jedis.keys("*" ); Iterator<String> itKeys = keys.iterator(); while (itKeys.hasNext()){ String key = itKeys.next(); System.out.println(key); } } @Test public void mgetTest () { List<String> values = jedis.mget("brand1" , "brand3" , "brand" ); for (String value : values) { System.out.println(value); } } @Test public void existTest () { Boolean result1 = jedis.exists("company" ); Boolean result2 = jedis.exists("brand0" ); System.out.println(result1+"------------" +result2); } @Test public void renameTest () { String rename = jedis.rename("company" , "companyNew" ); System.out.println(rename); } @Test public void delTest () { Long result = jedis.del("companyNew" ); System.out.println(result); } }
操作字符串 在test包下创建TestStringOperate.java文件,该文件用于编写java操作Redis字符串的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 import org.junit.Test;import redis.clients.jedis.Jedis;public class TestStringOperate { private static Jedis jedis = new Jedis ("192.168.24.105" , 6379 ); public static void main (String[] args) { System.out.println("服务启动..." + jedis.ping()); } @Test public void getsetTest () { String oldValue = jedis.getSet("brand1" , "itcast" ); System.out.println(oldValue); } @Test public void strlenTest () { Long valueLen = jedis.strlen("brand6" ); System.out.println(valueLen); } @Test public void getrangeTest () { String value = jedis.getrange("brand6" , 4 , 7 ); System.out.println(value); } @Test public void appendTest () { Long len = jedis.append("brand1" , "heima" ); System.out.println(len); } }
操作列表 在test包下创建TestListOperate.java文件,该文件用于编写java操作Redis字符串的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 import org.junit.Test;import redis.clients.jedis.Jedis;import java.util.List;public class TestListOperate { private static Jedis jedis = new Jedis ("192.168.24.105" , 6379 ); public static void main (String[] args) { System.out.println("服务启动..." + jedis.ping()); } @Test public void rpushAndLpushTest () { Long rpush = jedis.rpush("color" , "blue" , "green" , "purple" , "red" , "white" ); Long lpush = jedis.lpush("color" , "black" ,"pink" ); System.out.println(rpush+"-----" +lpush); } @Test public void lrangeTest () { List<String> values = jedis.lrange("color" , 0 , -1 ); for (String value : values) { System.out.println(value); } } @Test public void lindexTest () { String value = jedis.lindex("color" , 5 ); System.out.println(value); } @Test public void lpopTest () { String value = jedis.lpop("color" ); System.out.println(value); } @Test public void llenTest () { Long len = jedis.llen("color" ); System.out.println(len); } @Test public void lremTest () { Long result = jedis.lrem("color" , 1 , "red" ); System.out.println(result); } }
作业: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 package com.itcast.redis;import org.junit.Test;import redis.clients.jedis.Jedis;import redis.clients.jedis.ListPosition;import java.util.List;public class TestStrL { private static Jedis jedis=new Jedis ("192.168.24.105" ,6379 ); public static void main (String[] args) { String ping = jedis.ping(); System.out.println("数据库正在连接:" +jedis.ping()); System.out.println("数据库正在清空:" +jedis.flushDB()); System.out.println("查看当前数据库:" +jedis.keys("*" )); } @Test public void testKey () { String key = jedis.set("name" , "张楚岚" ); System.out.println(key); System.out.println("判断键“name”是否存在:" +jedis.exists("name" )); } @Test public void testMsetnx () { Long manykey = jedis.msetnx("age" , "20" , "stuNo" , "123456789" ); System.out.println(manykey); } @Test public void testMget () { List<String> mget = jedis.mget("name" , "age" , "stuNo" ); for (String mkey : mget){ System.out.println(mkey); } } @Test public void testGetSet () { String key = jedis.getSet("name" , "www.itczh.com" ); System.out.println(key); System.out.println("当前name的值:" +jedis.get("name" )); } @Test public void testAppend () { Long append = jedis.append("name" , "张楚岚" ); System.out.println(append); System.out.println("当前name的值:" +jedis.get("name" )); } @Test public void testRpush () { Long rpush = jedis.rpush("dorm" , "肖自在" , "黑管儿" , "高二壮" , "老孟" , "王震球" ); System.out.println(rpush); } @Test public void testLpush () { Long lpush = jedis.lpush("dorm" , "张楚岚" , "冯宝宝" , "陈朵" ); System.out.println(lpush); } @Test public void testLrange () { List<String> list = jedis.lrange("dorm" , 0 , -1 ); for (String l : list){ System.out.println(l); } } @Test public void testLtrim () { String ltrim = jedis.ltrim("dorm" , 2 , 5 ); System.out.println(ltrim); } @Test public void testLset () { String lset = jedis.lset("dorm" , 3 , "张三" ); System.out.println(lset); System.out.println("列表中指定下标[3]的值:" +jedis.lindex("dorm" ,3 )); } @Test public void testLinsert () { Long linsert = jedis.linsert("dorm" , ListPosition.BEFORE, "张三" , "大数据" ); System.out.println(linsert); System.out.println("列表中指定下标[3]的值:" +jedis.lindex("dorm" ,3 )); System.out.println("列表中指定下标[4]的值:" +jedis.lindex("dorm" ,4 )); } @Test public void testShutdown () { String shutdown = jedis.shutdown(); System.out.println(shutdown); } }
操作集合 操作散列 操作有序集合 十六、列式存储数据库HBase
列式存储数据库也是NoSQL数据库的一种类型。顾名思义,列式存储数据库中的数据是基于列进行存储的。常见的列式存储数据库有HBase、Cassandra、Riak以及HyperTable。由于HBase数据库基于Hadoop生态系统,利用HBase集群可在多台廉价PC Server上实现结构化数据的分布式数据存储,从而处理海量的数据。
HBase的概述 Hbase的来源 2006年Google技术人员Fay Chang发布了一篇文章Bigtable: ADistributed Storage System for Structured Data
。该文章向世人介绍了一种分布式的数据库,这种数据库可以在局部几台服务器崩溃的情况下继续提供高性能的服务。
2007年Powerset公司的工作人员基于此文研发了BigTable的Java开源版本 ,即HBase。刚开始它只是Hadoop的一部分。
2008年HBase成为了Apache的顶级项目 。HBase几乎实现了BigTable的所有特性。它被称为一个开源的非关系型分布式数据库。
2010 年HBase的开发速度打破了一直以来跟Hadoop版本一致的惯例,因为HBase的版本发布速度已经超越了Hadoop 。它的版本号一下从0.20.x跳跃到了0.89.x。其Logo也进行了更换!
HBase定义 Apache HBase – Apache HBase™ Home
HBase是一个基于Java、开源的、高可靠性、高性能、面向列、可伸缩的列式非关系型数据库,也可以称为列式分布式数据库(简称HBase分布式数据库)。
Hbase面向列存储,构建于Hadoop之上,类似于Google的BigTable,提供一个十亿级行百万级列级别的表存储,对表中的数据提供实时的随机读写操作!
(1)HBase支持随机写
① HBase的读写操作还是借助HDFS完成,要完成随机写,根本上还是需要符合HDFS的特性!
② HDFS只支持追加写!
③ 随机的操作: Update+Delete 借助 追加写+时间戳(版本号)
④ 只允许客户端查询时返回时间戳最新的数据!
(2)HBase支持海量数据的实时读写
①分布式
②索引,LSM树(MySQL B+Tree 多路平衡查找树)
③kv
④吃内存
⑤列式存储
⑥布隆过滤器(查询)
HBase的特点 1)海量存储
HBase适合存储PB级别的海量数据,在PB级别的数据以及采用廉价PC存储的情况下,能在几十到百毫秒内返回数据。这与HBase的极易扩展性息息相关。正式因为HBase良好的扩展性,才为海量数据的存储提供了便利。
2)列式存储
这里的列式存储其实说的是列族存储,HBase是根据列族来存储数据的。列族下面可以有非常多的列,列族在创建表的时候就必须指定。
3)极易扩展
HBase的扩展性主要体现在两个方面,一个是基于上层处理能力(RegionServer)的扩展,一个是基于存储的扩展(HDFS)。
通过横向添加RegionSever的机器,进行水平扩展,提升HBase上层的处理能力,提升Hbsae服务更多Region的能力。
4)高并发
由于目前大部分使用HBase的架构,都是采用的廉价PC,因此单个IO的延迟其实并不小,一般在几十到上百ms之间。这里说的高并发,主要是在并发的情况下,HBase的单个IO延迟下降并不多。能获得高并发、低延迟的服务。
5)稀疏
稀疏主要是针对HBase列的灵活性,在列族中,你可以指定任意多的列,在列数据为空的情况下,是不会占用存储空间的。
Hbase的优点 ①HDFS有高容错,高扩展的特点,而Hbase基于HDFS实现数据的存储,因此Hbase拥有与生俱来的超强的扩展性和吞吐量。
②HBase采用的是Key/Value的存储方式,这意味着,即便面临海量数据的增长,也几乎不会导致查询性能下降。
③HBase是一个列式数据库,相对于于传统的行式数据库而言。当你的单张表字段很多的时候,可以将相同的列(以regin为单位)存在到不同的服务实例上,分散负载压力。
Hbase的缺点 ①架构设计复杂,且使用HDFS作为分布式存储,因此只是存储少量数据,它也不会很快。在大数据量时,它慢的不会很明显!
②Hbase不支持表的关联操作,因此数据分析是HBase的弱项。常见的 group by或order by只能通过编写MapReduce来实现!
③Hbase部分支持了ACID
HBase作为一种数据库,它与传统数据库相比有很大区别,下面从存储模式、表字段以及可延伸性这三个方面分别进行介绍。
存储模式
传统数据库中是基于行存储的,而HBase是基于列进行存储的。
表字段
传统数据库中的表字段不能超过30个,而HBase的表字段不作限制。
可延伸性
传统数据库中的列是固定的,需要先确定列有多少才会增加数据去存储,而HBase是根据数据存储的大小去动态的增加列,列是不固定的,但是列族是固定的。
HBase的数据模型 HBase分布式数据库的数据存储在行列式的表格中,它是一个多维度的映射模型,其数据模型如图所示。
逻辑上,HBase的数据模型同关系型数据库很类似,数据存储在一张表中,有行有列。但从HBase的底层物理存储结构(K-V)来看,HBase更像是一个multi-dimensional map。
HBase逻辑结构
HBase物理存储结构
HBase的架构 HBase构建在Hadoop分布式文件系统(HDFS)之上,HDFS为HBase提供了高可靠的底层存储支持,Hadoop分布式计算框架(MapReduce)为HBase提供了高性能的计算能力,分布式协作框架(Zookeeper)为HBase提供了稳定服务和容错机制。下面,通过一张图介绍一下HBase的整体架构,具体如图所示。
HBase中存储在HDFS中的数据是通过Zookeeper协调处理的。由于HBase存在单点故障的问题,因此,可以通过Zookeeper部署一个高可用的HBase集群解决。下面,以三台服务器为例(nosql01、nosql02和nosql03),讲解如何安装部署HBase高可用集群。HBase高可用集群的规划方式如图所示。
HBase高可用集群中的nosql01和nosql02是主节点,nosql02和nosql03是从节点。这里之所以将nosql02既部署为主节点也部署为从节点,其目的是为了避免HBase集群主节点宕机导致单点故障问题。
HBase的部署 安装JDK 1 上传软件包 jdk-8u211-linux-x64.tar.gz 1 2 3 4 5 6 7 8 9 10 11 [root@Server01 ~]# cd /opt/ [root@Server01 opt]# ll 总用量 0 drwxr-xr-x 3 root root 21 3月 4 21:09 module drwxr-xr-x 3 root root 28 8月 28 2023 rh drwxr-xr-x 2 root root 52 3月 4 21:09 soft [root@Server01 opt]# cd soft/ [root@Server01 soft]# ll 总用量 130320 -rw-r--r-- 1 root root 133445425 11月 1 2023 mongodb-linux-x86_64-rhel80-4.2.24.tgz [root@Server01 soft]#
把安装包上传至服务器该路径下
2 解压软件包 jdk-8u211-linux-x64.tar.gz 解压安装包,并移动到 /opt/software/下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 [root@Server01 soft]# mkdir /opt/module/jvm [root@Server01 soft]# tar -zxvf jdk-8u211-linux-x64.tar.gz jdk1.8.0_211/ jdk1.8.0_211/lib/ ...... jdk1.8.0_211/COPYRIGHT [root@Server01 soft]# mv jdk1.8.0_211 /opt/module/jvm/ [root@Server01 soft]# ll /opt/module/jvm/jdk1.8.0_211/ 总用量 25984 drwxr-xr-x 2 10 143 4096 4月 2 2019 bin -r--r--r-- 1 10 143 3244 4月 2 2019 COPYRIGHT drwxr-xr-x 3 10 143 132 4月 2 2019 include -rw-r--r-- 1 10 143 5213268 3月 14 2019 javafx-src.zip drwxr-xr-x 5 10 143 185 4月 2 2019 jre drwxr-xr-x 5 10 143 245 4月 2 2019 lib -r--r--r-- 1 10 143 44 4月 2 2019 LICENSE drwxr-xr-x 4 10 143 47 4月 2 2019 man -r--r--r-- 1 10 143 159 4月 2 2019 README.html -rw-r--r-- 1 10 143 424 4月 2 2019 release -rw-r--r-- 1 10 143 21105019 4月 2 2019 src.zip -rw-r--r-- 1 10 143 112748 3月 14 2019 THIRDPARTYLICENSEREADME-JAVAFX.txt -r--r--r-- 1 10 143 149725 4月 2 2019 THIRDPARTYLICENSEREADME.txt [root@Server01 soft]# cd
3 添加环境变量 1 2 3 4 5 6 7 8 9 10 11 12 [root@Server01 ~]# vi /etc/profile export JAVA_HOME=/opt/module/jvm/jdk1.8.0_211/export PATH=$PATH :$JAVA_HOME /bin[root@Server01 ~]# source /etc/profile [root@Server01 ~]# jps -v 4909 Jps -Dapplication.home=/opt/module/jvm/jdk1.8.0_211 -Xms8m [root@Server01 ~]#
安装Hadoop(伪分布式) 0 完全分布式集群(了解) hadoop的初衷是采用大量的廉价机器,组成一个集群!完成大数据的存储和计算!
HDFS(框架):负责大数据的存储
YARN(框架): 负责大数据的资源调度
MR(编程模型): 使用Hadoop制定的编程要求,编写程序,完成大数据的计算!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #################### 规划 ############################ Hadoop中的进程在多台机器运行! HDFS: 1 个nn+N个DN n个2 nn YARN: 1 个RM+N个NM 避免单点故障,NN和RM建议分散到多台机器! 注意负载均衡 hadoop101 hadoop102 hadoop103 DN DN DN NM NM NM NN RM 2 NN ##################################################### # HDFS 负责大数据的存储 核心进程: 必须进程: Namenode (1 个): 负责文件,名称等元数据(属性信息)的存储! 文件名,大小,文件切分了多少块(block),创建和修改时间等! 职责: 接受客户端的请求! 接受DN的请求! 向DN分配任务! Datanode (N个): 负责文件中数据的存储! 职责: 负责接受NM分配的任务! 负责数据块(block)的管理(读,写)! 可选进程: SecondaryNamenode (N个): 负责辅助NameNode工作! # YARN YARN负责集群中所有计算资源的管理和调度! 常见进程: ResourceManager (1 个): 负责整个集群所有资源的管理! 职责: 负责接受客户端的提交Job的请求! 负责向NM分配任务! 负责接受NM上报的信息! NodeManager (N个): 负责单台计算机所有资源的管理! 职责: 负责和RM进行通信,上报本机中的可用资源! 负责领取RM分配的任务! 负责为Job中的每个Task分配计算资源!
1 准备工作(至少4G内存): 安装软件,在一台机器安装,再将这台机器的软件复制到其他机器
(1)验证是否安装JDK:Hadoop运行的前提是本机已经安装了JDK,配置JAVA_HOME变量 1 2 3 [root@Server01 ~]# jps 3055 Jps [root@Server01 ~]#
(2)验证是否host映射:在Hadoop中启动多种不同类型的进程 例如NN,DN,RM,NM,这些进程需要进行通信! 在通信时,常用主机名进行通信!
在192.168.24.105机器上的DN进程,希望访问 192.168.24.105 机器的NN进程! 需要在集群的每台机器上,配置集群中所有机器的host映射!
Linux: /etc/hosts Windows: C:\Windows\System32\drivers\etc\hosts
配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 [root@Server01 ~]# hostname Server01 [root@Server01 ~]# hostnamectl set-hostname nosql100 [root@Server01 ~]# hostname nosql100 [root@Server01 ~]# vim /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.24.105 nosql100 [root@Server01 ~]# exit 注销 Connection closed. Disconnected from remote host(NoSQL) at 22:41:07. Type `help ' to learn how to use Xshell prompt. [C:\~]$ Connecting to 192.168.24.105:22... Connection established. To escape to local shell, press ' Ctrl+Alt+]'. Activate the web console with: systemctl enable --now cockpit.socket Last login: Tue May 28 22:23:52 2024 from 192.168.10.1 [root@nosql100 ~]# [root@nosql100 ~]# nmcli device show ens160 GENERAL.DEVICE: ens160 GENERAL.TYPE: ethernet GENERAL.HWADDR: 00:0C:29:29:B7:CD GENERAL.MTU: 1500 GENERAL.STATE: 100(已连接) GENERAL.CONNECTION: ens160 GENERAL.CON-PATH: /org/freedesktop/NetworkManager/ActiveConnection/1 WIRED-PROPERTIES.CARRIER: 开 IP4.ADDRESS[1]: 192.168.24.105/24 IP4.GATEWAY: 192.168.10.254 IP4.ROUTE[1]: dst = 192.168.10.0/24, nh = 0.0.0.0, mt = 100 IP4.ROUTE[2]: dst = 0.0.0.0/0, nh = 192.168.10.254, mt = 100 IP4.DNS[1]: 192.168.10.254 IP6.ADDRESS[1]: fe80::20c:29ff:fe29:b7cd/64 IP6.GATEWAY: -- IP6.ROUTE[1]: dst = fe80::/64, nh = ::, mt = 100 [root@nosql100 ~]#
此时虚拟机IP为 192.168.24.105
重启
(3)注意权限创建并使用普通用户操作 hadoop框架在运行需要产生很多数据(日志),数据的保存目录,必须让当前启动hadoop进程的用户拥有写权限!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 [root@nosql100 ~]# useradd nosql [root@nosql100 ~]# passwd nosql 更改用户 nosql 的密码 。 新的 密码: 无效的密码: 密码少于 8 个字符 重新输入新的 密码: passwd:所有的身份验证令牌已经成功更新。 [root@nosql100 ~]# [root@nosql100 ~]# vim /etc/sudoers 【此处省略...】 99 100 root ALL=(ALL) ALL 101 nosql ALL=(ALL) NOPASSWD: ALL 102 103 104 105 106 107 %wheel ALL=(ALL) ALL 108 109 110 【此处省略...】 :wq! [root@nosql100 ~]# su nosql [nosql@nosql100 root]$ cd [nosql@nosql100 ~]$ ll /opt/ 总用量 0 drwxr-xr-x 4 root root 32 5月 28 22:30 module drwxr-xr-x 3 root root 28 8月 28 2023 rh drwxr-xr-x 2 root root 174 5月 28 22:31 soft [nosql@nosql100 ~]$ [nosql@nosql100 ~]$ sudo chown -R nosql:nosql /opt/module /opt/soft [nosql@nosql100 ~]$ ll /opt/ 总用量 0 drwxr-xr-x 4 nosql nosql 32 5月 28 22:30 module drwxr-xr-x 3 root root 28 8月 28 2023 rh drwxr-xr-x 2 nosql nosql 174 5月 28 22:31 soft [nosql@nosql100 ~]$
(4)关闭防火墙,关闭selinux,设置开机不自启动(学习用) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 systemctl status firewalld.service systemctl stop firewalld.service systemctl disable firewalld.service vim /etc/selinux/config SELINUX=disabled
(5)设置XShell
2 测试连通性 改IP、改主机名后用ping测试连通性
1 2 3 4 5 6 7 8 9 10 11 [nosql@nosql100 ~]$ ping nosql100 -c 4 PING nosql100 (192.168.24.105) 56(84) bytes of data. 64 bytes from nosql100 (192.168.24.105): icmp_seq=1 ttl=64 time=0.051 ms 64 bytes from nosql100 (192.168.24.105): icmp_seq=2 ttl=64 time=0.055 ms 64 bytes from nosql100 (192.168.24.105): icmp_seq=3 ttl=64 time=0.057 ms 64 bytes from nosql100 (192.168.24.105): icmp_seq=4 ttl=64 time=0.060 ms --- nosql100 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3099ms rtt min/avg/max/mdev = 0.051/0.055/0.060/0.009 ms [nosql@nosql100 ~]$
3 免密登录 免输入密码登录,借助SSH实现
举例: A机器的a用户,希望在A机器上,使用b用户的身份登录到B机器! 实现步骤: ①A机器的a用户,在A机器上生成一对密钥 ssh-keygen -t rsa ②密钥分为公钥和私钥,a用户需要将公钥拷贝到B机器上b用户的家目录下的 authorithxxxx_keys a)使用b用户登录到B机器 b)编辑authorithxxxx_keys,将公钥的内容进行添加 在A机器,使用a用户执行以下命令: ssh-copy-id b@B ③A机器的a用户,可以使用 ssh b@B进行登录! 注意: 如果使用ssh 直接登录 主机名 默认使用当前用户对目标主机进行登录!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 [nosql@nosql100 ~]$ ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/nosql/.ssh/id_rsa): Created directory '/home/nosql/.ssh' . Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/nosql/.ssh/id_rsa. Your public key has been saved in /home/nosql/.ssh/id_rsa.pub. The key fingerprint is: SHA256:azXxjsyKqj0eLD4DsEYZnOv0TEmFKDL07lZAroWedHc nosql@nosql100 The key's randomart image is: +---[RSA 3072]----+ |o.o.o. | |+==o | |o+=*.. E . | |+=*oo . o | |==+. . S o . | |oo.+. = + | |...oo o + . | | .+o.. o . | | o=+o. . | +----[SHA256]-----+ [nosql@nosql100 ~]$ cd .ssh/ [nosql@nosql100 .ssh]$ cat id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCdazKvml0Xv8flwDd6gdhrwfPGOGrnQF/4cj2OTETIdQZWj6f7WQKyFzgvE7t4Fc9DxLNlK3zuHfFeg4Q6hWkvG+lONSLeoGiJG6fGLLN7hyV2QbdJMwvAyLESFDpX1PVn8VvJ7dAWdS6/04iQ3ybFu+hyj8j+KZzjWPW+BiG1Amf4G96RJsWAaOVHX7jbquRpFNPawzcr1l3KyKRfL43dlL8KnbFxqeNSehIZalDmLcZV7NvJGr/iJRFNdTPO76Iopl0xEe2JbJx6lI0EiqUw4DgAwtk9tAKUJ9TqKBSI7GuIyr9iy05hXPhtUGw/oyIqgM9lq1zpjjHe0nDnGIX2zMEicH9GNBV5SnbYmoROnf1JMKrIUyXiTBXMYgI+X/1o8WsUL8MSzAkJ+H61rNuQCzre2vEeObxqbz5hR/riUKkmIT/AtcGN/wMfBqvbxlOlnTziPVJ3gliSYuusP/FiktSrrt18vob6P53JA0p1zW33Dp1lwDQAIp97ODvukr8= nosql@nosql100 [nosql@nosql100 .ssh]$ [nosql@nosql100 .ssh]$ ssh-copy-id nosql100 /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/nosql/.ssh/id_rsa.pub" The authenticity of host ' nosql100 (192.168.24.105)' can' t be established.ECDSA key fingerprint is SHA256:gCplKtOGjblpugS1xzPBVrYXXiibQ8G0uqS43sN9ZEQ. Are you sure you want to continue connecting (yes /no/[fingerprint])? yes /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys nosql@nosql100's password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh ' nosql100'" and check to make sure that only the key(s) you wanted were added. [nosql@nosql100 .ssh]$ ll 总用量 16 -rw------- 1 nosql nosql 568 5月 28 23:01 authorized_keys -rw------- 1 nosql nosql 2602 5月 28 22:59 id_rsa -rw-r--r-- 1 nosql nosql 568 5月 28 22:59 id_rsa.pub -rw-r--r-- 1 nosql nosql 185 5月 28 23:01 known_hosts [nosql@nosql100 .ssh]$ cat authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCdazKvml0Xv8flwDd6gdhrwfPGOGrnQF/4cj2OTETIdQZWj6f7WQKyFzgvE7t4Fc9DxLNlK3zuHfFeg4Q6hWkvG+lONSLeoGiJG6fGLLN7hyV2QbdJMwvAyLESFDpX1PVn8VvJ7dAWdS6/04iQ3ybFu+hyj8j+KZzjWPW+BiG1Amf4G96RJsWAaOVHX7jbquRpFNPawzcr1l3KyKRfL43dlL8KnbFxqeNSehIZalDmLcZV7NvJGr/iJRFNdTPO76Iopl0xEe2JbJx6lI0EiqUw4DgAwtk9tAKUJ9TqKBSI7GuIyr9iy05hXPhtUGw/oyIqgM9lq1zpjjHe0nDnGIX2zMEicH9GNBV5SnbYmoROnf1JMKrIUyXiTBXMYgI+X/1o8WsUL8MSzAkJ+H61rNuQCzre2vEeObxqbz5hR/riUKkmIT/AtcGN/wMfBqvbxlOlnTziPVJ3gliSYuusP/FiktSrrt18vob6P53JA0p1zW33Dp1lwDQAIp97ODvukr8= nosql@nosql100 [nosql@nosql100 .ssh]$ #测试 [nosql@nosql100 .ssh]$ ssh nosql100 Activate the web console with: systemctl enable --now cockpit.socket Last login: Tue May 28 22:53:35 2024 from 192.168.10.1 [nosql@nosql100 ~]$ exit 注销 Connection to nosql100 closed. [nosql@nosql100 .ssh]$
4 上传软件包hadoop-2.7.4.tar.gz
5 解压软件包hadoop-2.7.4.tar.gz 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 [nosql@nosql100 ~]$ cd /opt/soft/ [nosql@nosql100 soft]$ ll 总用量 721052 -rw-r--r-- 1 nosql nosql 266688029 5月 28 22:28 hadoop-2.7.4.tar.gz -rw-r--r-- 1 nosql nosql 108176325 5月 28 22:28 hbase-1.2.1-bin.tar.gz -rw-r--r-- 1 nosql nosql 194990602 5月 28 22:28 jdk-8u211-linux-x64.tar.gz -rw-r--r-- 1 nosql nosql 133445425 11月 1 2023 mongodb-linux-x86_64-rhel80-4.2.24.tgz -rw-r--r-- 1 nosql nosql 35042811 5月 28 22:28 zookeeper-3.4.10.tar.gz [nosql@nosql100 soft]$ [nosql@nosql100 soft]$ tar -zxvf hadoop-2.7.4.tar.gz -C ../module/ ...... hadoop-2.7.4/etc/hadoop/httpfs-log4j.properties [nosql@nosql100 soft]$ cd ../module/ [nosql@nosql100 module]$ ll 总用量 0 drwxr-xr-x 10 nosql nosql 160 8月 1 2017 hadoop-2.7.4 drwxr-xr-x 3 nosql nosql 26 5月 28 22:31 jvm drwxr-xr-x 4 nosql nosql 151 3月 4 21:51 mongodb [nosql@nosql100 module]$ [nosql@nosql100 module]$ cd hadoop-2.7.4/ [nosql@nosql100 hadoop-2.7.4]$ ll 总用量 116 drwxr-xr-x 2 nosql nosql 194 8月 1 2017 bin drwxr-xr-x 3 nosql nosql 20 8月 1 2017 etc drwxr-xr-x 2 nosql nosql 106 8月 1 2017 include drwxr-xr-x 3 nosql nosql 20 8月 1 2017 lib drwxr-xr-x 2 nosql nosql 239 8月 1 2017 libexec -rw-r--r-- 1 nosql nosql 86424 8月 1 2017 LICENSE.txt -rw-r--r-- 1 nosql nosql 14978 8月 1 2017 NOTICE.txt -rw-r--r-- 1 nosql nosql 1366 8月 1 2017 README.txt drwxr-xr-x 2 nosql nosql 4096 8月 1 2017 sbin drwxr-xr-x 4 nosql nosql 31 8月 1 2017 share drwxr-xr-x 19 nosql nosql 4096 8月 1 2017 src [nosql@nosql100 hadoop-2.7.4]$ [nosql@nosql100 hadoop-2.7.4]$ ll bin/ 总用量 324 -rwxr-xr-x 1 nosql nosql 111795 8月 1 2017 container-executor -rwxr-xr-x 1 nosql nosql 6488 8月 1 2017 hadoop -rwxr-xr-x 1 nosql nosql 8786 8月 1 2017 hadoop.cmd -rwxr-xr-x 1 nosql nosql 12223 8月 1 2017 hdfs -rwxr-xr-x 1 nosql nosql 7478 8月 1 2017 hdfs.cmd -rwxr-xr-x 1 nosql nosql 5953 8月 1 2017 mapred -rwxr-xr-x 1 nosql nosql 6310 8月 1 2017 mapred.cmd -rwxr-xr-x 1 nosql nosql 1776 8月 1 2017 rcc -rwxr-xr-x 1 nosql nosql 125103 8月 1 2017 test-container-executor -rwxr-xr-x 1 nosql nosql 13352 8月 1 2017 yarn -rwxr-xr-x 1 nosql nosql 11386 8月 1 2017 yarn.cmd [nosql@nosql100 hadoop-2.7.4]$ [nosql@nosql100 hadoop-2.7.4]$ ll sbin/ 总用量 120 -rwxr-xr-x 1 nosql nosql 2752 8月 1 2017 distribute-exclude.sh -rwxr-xr-x 1 nosql nosql 6452 8月 1 2017 hadoop-daemon.sh -rwxr-xr-x 1 nosql nosql 1360 8月 1 2017 hadoop-daemons.sh -rwxr-xr-x 1 nosql nosql 1640 8月 1 2017 hdfs-config.cmd -rwxr-xr-x 1 nosql nosql 1427 8月 1 2017 hdfs-config.sh -rwxr-xr-x 1 nosql nosql 2291 8月 1 2017 httpfs.sh -rwxr-xr-x 1 nosql nosql 3128 8月 1 2017 kms.sh -rwxr-xr-x 1 nosql nosql 4080 8月 1 2017 mr-jobhistory-daemon.sh -rwxr-xr-x 1 nosql nosql 1648 8月 1 2017 refresh-namenodes.sh -rwxr-xr-x 1 nosql nosql 2145 8月 1 2017 slaves.sh -rwxr-xr-x 1 nosql nosql 1779 8月 1 2017 start-all.cmd -rwxr-xr-x 1 nosql nosql 1471 8月 1 2017 start-all.sh -rwxr-xr-x 1 nosql nosql 1128 8月 1 2017 start-balancer.sh -rwxr-xr-x 1 nosql nosql 1401 8月 1 2017 start-dfs.cmd -rwxr-xr-x 1 nosql nosql 3734 8月 1 2017 start-dfs.sh -rwxr-xr-x 1 nosql nosql 1357 8月 1 2017 start-secure-dns.sh -rwxr-xr-x 1 nosql nosql 1571 8月 1 2017 start-yarn.cmd -rwxr-xr-x 1 nosql nosql 1347 8月 1 2017 start-yarn.sh -rwxr-xr-x 1 nosql nosql 1770 8月 1 2017 stop-all.cmd -rwxr-xr-x 1 nosql nosql 1462 8月 1 2017 stop-all.sh -rwxr-xr-x 1 nosql nosql 1179 8月 1 2017 stop-balancer.sh -rwxr-xr-x 1 nosql nosql 1455 8月 1 2017 stop-dfs.cmd -rwxr-xr-x 1 nosql nosql 3206 8月 1 2017 stop-dfs.sh -rwxr-xr-x 1 nosql nosql 1340 8月 1 2017 stop-secure-dns.sh -rwxr-xr-x 1 nosql nosql 1642 8月 1 2017 stop-yarn.cmd -rwxr-xr-x 1 nosql nosql 1340 8月 1 2017 stop-yarn.sh -rwxr-xr-x 1 nosql nosql 4295 8月 1 2017 yarn-daemon.sh -rwxr-xr-x 1 nosql nosql 1353 8月 1 2017 yarn-daemons.sh [nosql@nosql100 hadoop-2.7.4]$ [nosql@nosql100 hadoop-2.7.4]$ ll etc/hadoop/ 总用量 152 -rw-r--r-- 1 nosql nosql 4436 8月 1 2017 capacity-scheduler.xml -rw-r--r-- 1 nosql nosql 1335 8月 1 2017 configuration.xsl -rw-r--r-- 1 nosql nosql 318 8月 1 2017 container-executor.cfg -rw-r--r-- 1 nosql nosql 774 8月 1 2017 core-site.xml -rw-r--r-- 1 nosql nosql 3670 8月 1 2017 hadoop-env.cmd -rw-r--r-- 1 nosql nosql 4224 8月 1 2017 hadoop-env.sh -rw-r--r-- 1 nosql nosql 2598 8月 1 2017 hadoop-metrics2.properties -rw-r--r-- 1 nosql nosql 2490 8月 1 2017 hadoop-metrics.properties -rw-r--r-- 1 nosql nosql 9683 8月 1 2017 hadoop-policy.xml -rw-r--r-- 1 nosql nosql 775 8月 1 2017 hdfs-site.xml -rw-r--r-- 1 nosql nosql 1449 8月 1 2017 httpfs-env.sh -rw-r--r-- 1 nosql nosql 1657 8月 1 2017 httpfs-log4j.properties -rw-r--r-- 1 nosql nosql 21 8月 1 2017 httpfs-signature.secret -rw-r--r-- 1 nosql nosql 620 8月 1 2017 httpfs-site.xml -rw-r--r-- 1 nosql nosql 3518 8月 1 2017 kms-acls.xml -rw-r--r-- 1 nosql nosql 1527 8月 1 2017 kms-env.sh -rw-r--r-- 1 nosql nosql 1631 8月 1 2017 kms-log4j.properties -rw-r--r-- 1 nosql nosql 5540 8月 1 2017 kms-site.xml -rw-r--r-- 1 nosql nosql 11237 8月 1 2017 log4j.properties -rw-r--r-- 1 nosql nosql 951 8月 1 2017 mapred-env.cmd -rw-r--r-- 1 nosql nosql 1383 8月 1 2017 mapred-env.sh -rw-r--r-- 1 nosql nosql 4113 8月 1 2017 mapred-queues.xml.template -rw-r--r-- 1 nosql nosql 758 8月 1 2017 mapred-site.xml.template -rw-r--r-- 1 nosql nosql 10 8月 1 2017 slaves -rw-r--r-- 1 nosql nosql 2316 8月 1 2017 ssl-client.xml.example -rw-r--r-- 1 nosql nosql 2697 8月 1 2017 ssl-server.xml.example -rw-r--r-- 1 nosql nosql 2250 8月 1 2017 yarn-env.cmd -rw-r--r-- 1 nosql nosql 4567 8月 1 2017 yarn-env.sh -rw-r--r-- 1 nosql nosql 690 8月 1 2017 yarn-site.xml [nosql@nosql100 hadoop-2.7.4]$
6 添加hadoop环境变量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [nosql@nosql100 hadoop-2.7.4]$ sudo vim /etc/profile ...... export JAVA_HOME=/opt/module/jvm/jdk1.8.0_211export HADOOP_HOME=/opt/module/hadoop-2.7.4export PATH=$PATH :$JAVA_HOME /bin:$HADOOP_HOME /bin:$HADOOP_HOME /sbin...... wq! "/etc/profile" 95L, 2466C 已写入[nosql@nosql100 hadoop-2.7.4]$ [nosql@nosql100 hadoop-2.7.4]$ [nosql@nosql100 hadoop-2.7.4]$ source /etc/profile [nosql@nosql100 hadoop-2.7.4]$ hadoop version Hadoop 2.7.4 Subversion https://shv@git-wip-us.apache.org/repos/asf/hadoop.git -r cd915e1e8d9d0131462a0b7301586c175728a282 Compiled by kshvachk on 2017-08-01T00:29Z Compiled with protoc 2.5.0 From source with checksum 50b0468318b4ce9bd24dc467b7ce1148 This command was run using /opt/module/hadoop-2.7.4/share/hadoop/common/hadoop-common-2.7.4.jar [nosql@nosql100 hadoop-2.7.4]$
7 分布式HDFS的安装和启动 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 4个默认的配置文件: 位置: HADOOP_HOME/share/xxxx.jar/xxx-default.xml core-default.xml: 设置hadoop最核心的参数! hdfs-default.xml 保存的是hdfs相关的参数! mapred-default.xml: MR程序在运行时,需要使用的参数! yarn-default.xml: yarn在启动时,需要的参数! 4个用户可以自定义的配置文件: xxx-site.xml core-site.xml: 用户自定义的设置hadoop最核心的参数! hdfs-site.xml 用户自定义的保存的是hdfs相关的参数! mapred-site.xml: 用户自定义的MR程序在运行时,需要使用的参数! yarn-site.xml: 用户自定义的yarn在启动时,需要的参数! 用户自定义的配置文件,可以覆盖默认配置文件中同名的参数的值! Hadoop在启动时,先加载4个默认的配置文件,再加载用户自定义的配置文件,如果用户自定义的配置文件 中有和4个默认配置文件中门的参数,可以覆盖之前已经加载的值!
hadoop安装后,hadoop的性能和表现取决于用户的配置!
如果没有配置,默认读取 HADOOP_HOME/etc/hadoop 中对应的配置文件!
hadoop-daemon.sh start namenode脚本在执行时,只会去默认的目录中读取配置文件!
Hadoop可以在单个节点(一台机器)上以伪分布式的方式运行,同一个节点既作为名称节点(NameNode)
,也作为数据节点(DataNode)
,读取的是分布式文件系统 HDFS 中的文件。
需要配置相关文件,才能够让Hadoop在伪分布式模式下顺利运行。Hadoop的配置文件位于$HADOOP_HOME/etc/hadoop/
中,进行伪分布式模式配置时,需要修改3个配置文件,即hadoop-env.sh
,core-site.xml
和hdfs-site.xml
。
(1)修改 $HADOOP_HOME/etc/hadoop/hadoop-env.sh 可以使用vim编辑器打开hadoop-env.sh
文件,进行修改JAVA_HOME
配置。
1 2 3 4 5 6 [nosql@nosql100 hadoop-2.7.4]$ cd [nosql@nosql100 ~]$ cd /opt/module/hadoop-2.7.4/etc/hadoop/ [nosql@nosql100 hadoop]$ vim hadoop-env.sh …… export JAVA_HOME=/opt/module/jvm/jdk1.8.0_211……
(2)修改 $HADOOP_HOME/etc/hadoop/core-site.xml 可以使用vim编辑器打开core-site.xml
文件,它的初始内容如下:
1 2 <configuration> </configuration>
修改以后,core-site.xml
文件的内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [nosql@nosql100 hadoop]$ vim core-site.xml <configuration> <property> <name>fs.defaultFS</name> <!-- 告知NameNode在哪个机器,NN使用哪个端口号接受客户端和DN的RPC请求. --> <value>hdfs://nosql100:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/opt/module/hadoop-2.7.4/data/tmp</value> <description>A base for other temporary directories.</description> </property> </configuration> "core-site.xml" 30L, 1149C 已写入
在上面的配置文件中,hadoop.tmp.dir
用于保存临时文件,若没有配置hadoop.tmp.dir
这个参数,则默认使用的临时目录为/tmp/hadoo-hadoop
,而这个目录在Hadoop重启时有可能被系统清理掉,导致一些意想不到的问题,因此,必须配置这个参数。fs.defaultFS
这个参数,用于指定HDFS的
访问地址,其中,9000
是端口号 。
(3)修改 $HADOOP_HOME/etc/hadoop/hdfs-site.xml 同样,需要修改配置文件hdfs-site.xml
,修改后的内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [hbase@hadoop102 hadoop]$ vim hdfs-site.xml <configuration> <!-- 指定Hadoop辅助名称节点主机配置 --> <property> <name>dfs.namenode.secondary.http-address</name> <value>nosql100:50090</value> </property> <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:/opt/module/hadoop-2.7.4/data/tmp/dfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:/opt/module/hadoop-2.7.4/data/tmp/dfs/data</value> </property> </configuration> "hdfs-site.xml" 32L, 1259C 已写入
在hdfs-site.xml
文件中,dfs.replication
这个参数用于指定副本的数量,因为,在分布式文件系统HDFS
中,数据会被冗余存储多份,以保证可靠性和可用性。但是,由于这里采用伪分布式模式,只有一个节点,因此,只可能有1个副本,因此,设置dfs.replication
的值为1。dfs.namenode.name.dir
用于设定名称节点的元数据的保存目录,dfs.datanode.data.dir
用于设定数据节点的数据保存目录,这两个参数必须设定,否则后面会出错。
需要指出的是,Hadoop的运行方式(比如运行在单机模式下还是运行在伪分布式模式下),是由配置文件决定的,启动Hadoop时会读取配置文件,然后根据配置文件来决定f运行在什么模式下。因此,如果需要从伪分布式模式切换回单机模式,只需要删除 core-site.xml
中的配置项即可。
(4)格式化Namenode(只需要格式化一次) 需要在NN所配置的节点进行格式化,即规划时的主机 hadoop101
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [nosql@nosql100 hadoop]$ cd [nosql@nosql100 ~]$ hadoop namenode -format DEPRECATED: Use of this script to execute hdfs command is deprecated. Instead use the hdfs command for it. 24/05/28 23:32:06 INFO namenode.NameNode: STARTUP_MSG: /************************************************************ STARTUP_MSG: Starting NameNode STARTUP_MSG: host = nosql100/192.168.24.105 STARTUP_MSG: args = [-format] STARTUP_MSG: version = 2.7.4 …… [nosql@nosql100 ~]$ cd /opt/module/hadoop-2.7.4/data/tmp/ [nosql@nosql100 tmp]$ ll 总用量 0 drwxrwxr-x 3 nosql nosql 18 5月 28 23:32 dfs [nosql@nosql100 tmp]$ tree . └── dfs └── name └── current ├── fsimage_0000000000000000000 ├── fsimage_0000000000000000000.md5 ├── seen_txid └── VERSION 3 directories, 4 files [nosql@nosql100 tmp]$
(5)集群时间同步 时间同步的方式:找一个机器,作为时间服务器,所有的机器与这台集群时间进行定时的同步,比如,每隔十分钟,同步一次时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 [nosql@nosql100 tmp]$ date 2024年 05月 28日 星期二 23:34:37 CST [nosql@nosql100 tmp]$ [nosql@nosql100 tmp]$ su root 密码: [root@nosql100 tmp]# rpm -qa|grep chrony chrony-4.1-1.el8.x86_64 [root@nosql100 tmp]# ll /etc/yum.repos.d/ 总用量 12 drwxr-xr-x. 2 root root 4096 8月 28 2023 bak -rw-r--r--. 1 root root 2590 8月 4 2022 CentOS-Base.repo -rw-r--r--. 1 root root 189 8月 28 2023 dvd.repo [root@nosql100 tmp]# yum -y install chrony 上次元数据过期检查:0:43:30 前,执行于 2024年05月28日 星期二 22时52分25秒。 软件包 chrony-4.1-1.el8.x86_64 已安装。 依赖关系解决。 无需任何处理。 完毕! [root@nosql100 tmp]# [root@nosql100 tmp]# timedatectl set-timezone "Asia/Shanghai" [root@nosql100 tmp]# vim /etc/chrony.conf pool 2.centos.pool.ntp.org iburst server time1.aliyun.com iburst server time2.aliyun.com iburst server time3.aliyun.com iburst server time4.aliyun.com iburst server time5.aliyun.com iburst server time6.aliyun.com iburst server 0.asia.pool.ntp.org iburst server 1.asia.pool.ntp.org iburst server 2.asia.pool.ntp.org iburst server 3.asia.pool.ntp.org iburst server cn.ntp.org.cn iburst server ntp.shu.edu.cn iburst driftfile /var/lib/chrony/drift makestep 1.0 3 rtcsync keyfile /etc/chrony.keys leapsectz right/UTC logdir /var/log/chrony [root@nosql100 tmp]# systemctl restart chronyd.service [root@nosql100 tmp]# chronyc sources -v .-- Source mode '^' = server, '=' = peer, '#' = local clock. / .- Source state '*' = current best, '+' = combined, '-' = not combined, | / 'x' = may be in error, '~' = too variable, '?' = unusable. || .- xxxx [ yyyy ] +/- zzzz || Reachability register (octal) -. | xxxx = adjusted offset, || Log2(Polling interval) --. | | yyyy = measured offset, || \ | | zzzz = estimated error. || | | \ MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^- ntp7.flashdance.cx 2 6 17 8 -21ms[ -21ms] +/- 144ms ^- ntp1.flashdance.cx 2 6 17 9 -29ms[ -29ms] +/- 141ms ^- ntp.wdc2.us.leaseweb.net 2 6 17 8 +73ms[ +73ms] +/- 344ms ^* time.neu.edu.cn 1 6 17 9 +1410us[ +90us] +/- 17ms ^+ 203.107.6.88 2 6 17 10 -4353us[-5674us] +/- 27ms ^- 236.99.217.185.interhost> 3 6 33 5 +10ms[ +10ms] +/- 136ms ^? tw.ntp.twds.com.tw 2 7 120 13 -60ms[ -60ms] +/- 172ms ^? ntp7.mum-in.hosts.301-mo> 0 6 0 - +0ns[ +0ns] +/- 0ns ^? time.cloudflare.com 0 7 0 - +0ns[ +0ns] +/- 0ns ^- 120.25.115.20 2 6 33 8 +3573us[+3573us] +/- 21ms ^? 202.120.127.191 0 7 0 - +0ns[ +0ns] +/- 0ns [root@nosql100 tmp]# [root@nosql100 tmp]# exit exit [nosql@nosql100 tmp]$ cd [nosql@nosql100 ~]$ date 2024年 05月 28日 星期二 23:39:02 CST [nosql@nosql100 ~]$
(6)运行群启脚本 ①群起脚本的原理是获取集群中所有的节点的主机名 默认读取当前机器 HADOOP_HOME/etc/hadoop/slaves,获取集群中所有的节点的主机名
1 2 3 4 5 [nosql@nosql100 ~]$ cd /opt/module/hadoop-2.7.4/etc/hadoop/ [nosql@nosql100 hadoop]$ vim slaves nosql100
②循环执行 ssh 主机名 hadoop-daemon.sh start xxx 保证当前机器到其他节点,已经配置了ssh免密登录 保证集群中所有当前用户的家目录/.bashrc中,已经配置source /etc/profile
注意: start-all.sh 时,其实分别调用了start-dfs.sh和start-yarn.sh start-dfs.sh 可以在集群的任意一台机器使用!可以启动HDFS中的所有进程! start-yarn.sh 在集群的非RM所在的机器使用时,不会启动resourcemanager!
1 2 3 4 5 6 7 8 9 10 11 [nosql@nosql100 ~]$ start-dfs.sh Starting namenodes on [nosql100] nosql100: starting namenode, logging to /opt/module/hadoop-2.7.4/logs/hadoop-nosql-namenode-nosql100.out nosql100: starting datanode, logging to /opt/module/hadoop-2.7.4/logs/hadoop-nosql-datanode-nosql100.out Starting secondary namenodes [nosql100] nosql100: starting secondarynamenode, logging to /opt/module/hadoop-2.7.4/logs/hadoop-nosql-secondarynamenode-nosql100.out [nosql@nosql100 ~]$ jps 13808 Jps 13257 NameNode 13439 DataNode 13663 SecondaryNameNode
(7)查看
jps 或通过浏览器访问 http://NameNode所在的主机名/ip:50070 例如:nosql100:50070
Namenode information
如果NN和DN都在一台机器,且只有一个DN节点,称为伪分布式!
Hadoop成功启动后,可以在Linux系统中(不是Windows系统)打开一个浏览器,在地址栏输入地址http://localhost:9870
,就可以查看名称节点和数据节点信息,还可以在线查看 HDFS 中的文件。
hadoop3.X的Web UI端口为:9870
hadoop2.X的Web UI端口为:50070
旧版本与新版本之间端口号有不一致的地方
(8)运行群停脚本 1 2 3 4 5 6 7 [nosql@nosql100 ~]$ stop-dfs.sh Stopping namenodes on [nosql100] nosql100: stopping namenode nosql100: stopping datanode Stopping secondary namenodes [nosql100] nosql100: stopping secondarynamenode [nosql@nosql100 ~]$
下次启动Hadoop时,无需进行名称节点的初始化(否则会出错) ,也就是说,不要再次执行hdfs namenode -format
命令,每次启动Hadoop只需要直接运行start-dfs.sh
命令即可。
安装HBase 1 上传软件包 hbase-1.2.1-bin.tar.gz
2 解压软件包 hbase-1.2.1-bin.tar.gz 1 2 [nosql@nosql100 ~]$ cd /opt/sof/ [nosql@nosql100 soft]$ tar -zxvf hbase-1.2.1-bin.tar.gz -C ../module/
3 HBase的配置 (1)修改 conf/HBase-env.sh 打开hbase-env.sh
文件以后,需要在hbase-env.sh
文件中配置JAVA_HOME
和HBASE_MANAGES_ZK
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [nosql@nosql100 ~]$ cd /opt/module/hbase-1.2.1/ [nosql@nosql100 hbase-1.2.1]$ cd conf/ [nosql@nosql100 conf]$ ll 总用量 40 -rw-r--r-- 1 nosql nosql 1811 12月 27 2015 hadoop-metrics2-hbase.properties -rw-r--r-- 1 nosql nosql 4537 1月 29 2016 hbase-env.cmd -rw-r--r-- 1 nosql nosql 7468 1月 29 2016 hbase-env.sh -rw-r--r-- 1 nosql nosql 2257 12月 27 2015 hbase-policy.xml -rw-r--r-- 1 nosql nosql 934 12月 27 2015 hbase-site.xml -rw-r--r-- 1 nosql nosql 4339 1月 29 2016 log4j.properties -rw-r--r-- 1 nosql nosql 10 12月 27 2015 regionservers [nosql@nosql100 conf]$ vim hbase-env.sh export JAVA_HOME=/opt/module/jvm/jdk1.8.0_211export HBASE_MANAGES_ZK=true
(2)修改 conf/HBase-site.xml 在hbase-site.xml
文件中,需要设置属性hbase.rootdir
,用于指定HBase数据的存储位置。在HBase伪分布式模式中,是使用伪分布式模式的HDFS存储数据,因此,需要把hbase.rootdir
设置为HBase在HDFS上的存储路径,根据Hadoop伪分布式模式的配置可以知道,HDFS的访问路径为hdfs://nosql100:9000/
,因为,这里设置hbase.rootdir
为hdfs://nosql100:9000/hbase
。此外,由于采用了伪分布式模式,因此,还需要将属性hbase.cluter.distributed
设置为**true
**。修改后的hbase-site.xml
文件中的配置信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <configuration> <property> <name>hbase.rootdir</name> <value>hdfs: </property> <property> <name>hbase.cluster.distributed</name> <value>true </value> </property> <property> <name>hbase.unsafe.stream.capability.enforce</name> <value>false </value> </property> </configuration>
(3)修改 conf/regionservers 1 2 [nosql@nosql100 conf]$ vim regionservers nosql100
(4)配置hbase环境变量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 [nosql@nosql100 ~]$ vi .bashrc if [ -f /etc/bashrc ]; then . /etc/bashrc fi if ! [[ "$PATH " =~ "$HOME /.local/bin:$HOME /bin:" ]]then PATH="$HOME /.local/bin:$HOME /bin:$PATH " fi export JAVA_HOME=/opt/module/jvm/jdk1.8.0_211/export HADOOP_HOME=/opt/module/hadoop-2.7.4export HBASE_HOME=/opt/module/hbase-1.2.1export PATH=$PATH :$JAVA_HOME /bin:$HADOOP_HOME /bin:$HADOOP_HOME /sbin:$HBASE_HOME /bin【此处省略...】 [nosql@nosql100 ~]$ source .bashrc [nosql@nosql100 ~]$ hbase version HBase 1.2.1 Source code repository git://asf-dev/home/busbey/projects/hbase revision=8d8a7107dc4ccbf36a92f64675dc60392f85c015 Compiled by busbey on Wed Mar 30 11:19:21 CDT 2016 From source with checksum f4bb4a14bb4e0b72b46f729dae98a772 [nosql@nosql100 ~]$ hadoop version Hadoop 2.7.4 Subversion https://shv@git-wip-us.apache.org/repos/asf/hadoop.git -r cd915e1e8d9d0131462a0b7301586c175728a282 Compiled by kshvachk on 2017-08-01T00:29Z Compiled with protoc 2.5.0 From source with checksum 50b0468318b4ce9bd24dc467b7ce1148 This command was run using /opt/module/hadoop-2.7.4/share/hadoop/common/hadoop-common-2.7.4.jar [nosql@nosql100 ~]$ java -version java version "1.8.0_211" Java(TM) SE Runtime Environment (build 1.8.0_211-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode) [nosql@nosql100 ~]$
(5)XShell的设置
启动HBase集群 1 启动hdfs 1 2 3 4 5 6 7 8 9 10 11 [nosql@nosql100 ~]$ start-dfs.sh Starting namenodes on [nosql100] nosql100: starting namenode, logging to /opt/module/hadoop-2.7.4/logs/hadoop-nosql-namenode-nosql100.out nosql100: starting datanode, logging to /opt/module/hadoop-2.7.4/logs/hadoop-nosql-datanode-nosql100.out Starting secondary namenodes [nosql100] nosql100: starting secondarynamenode, logging to /opt/module/hadoop-2.7.4/logs/hadoop-nosql-secondarynamenode-nosql100.out [nosql@nosql100 ~]$ jps 17506 NameNode 17933 SecondaryNameNode 17694 DataNode 18078 Jps
2 启动HBase
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 [nosql@nosql100 ~]$ start-hbase.sh localhost: starting zookeeper, logging to /opt/module/hbase-1.2.1/logs/hbase-nosql-zookeeper-nosql100.out localhost: SLF4J: Class path contains multiple SLF4J bindings. localhost: SLF4J: Found binding in [jar:file:/opt/module/hbase-1.2.1/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class] localhost: SLF4J: Found binding in [jar:file:/opt/module/hadoop-2.7.4/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class] localhost: SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. localhost: SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory] starting master, logging to /opt/module/hbase-1.2.1/logs/hbase-nosql-master-nosql100.out Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0 Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0 SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:/opt/module/hbase-1.2.1/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/opt/module/hadoop-2.7.4/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory] nosql100: starting regionserver, logging to /opt/module/hbase-1.2.1/logs/hbase-nosql-regionserver-nosql100.out nosql100: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0 nosql100: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0 nosql100: SLF4J: Class path contains multiple SLF4J bindings. nosql100: SLF4J: Found binding in [jar:file:/opt/module/hbase-1.2.1/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class] nosql100: SLF4J: Found binding in [jar:file:/opt/module/hadoop-2.7.4/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class] nosql100: SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. nosql100: SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory] [nosql@nosql100 ~]$ jps 17506 NameNode 18487 HMaster 18745 HRegionServer 19081 Jps 17933 SecondaryNameNode 17694 DataNode 18366 HQuorumPeer [nosql@nosql100 ~]$
② 访问web界面: nosql100:16010
访问master进程所在机器 Master: nosql100
1 2 3 [nosql@nosql100 ~]$ stop-hbase.sh stopping hbase...... localhost: stopping zookeeper.
4 总结:集群停止
HBase的操作 HBase的Shell操作 HBase Shell提供了大量操作HBase的命令,通过Shell命令可以很方便地操作HBase数据库,例如创建、删除及修改表、向表中添加数据、列出表中的相关信息等操作。不过当使用Shell命令行操作HBase时,需要进入HBase Shell交互界面。在HBase的安装目录下,执行“bin/hbase shell”或者“hbase shell”命令进入到HBase Shell界面,具体效果如图所示。
进入HBase Shell交互界面后,可以通过一系列Shell命令操作HBase,接下来,通过一张表列举一些操作HBase表常见的Shell命令,具体如表所示。
命令名称
相关说明
create
创建表
put
插入或更新数据
scan
扫描表并返回表的所有数据
describe
查看表的结构
get
获取指定行中列的数据
count
统计表中数据的行数
delete
删除指定行或者列的数据
deleteall
删除整个行或列的数据
truncate
删除整个表中的数据,但是结构还在
drop
删除整个表,数据和结构都删除(慎用)
1 创建表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 hbase(main):001:0> create 'phone' ,'info' 0 row(s) in 1.3980 seconds => Hbase::Table - phone hbase(main):002:0> hbase(main):002:0> list TABLE phone 1 row(s) in 0.0180 seconds => ["phone" ]
2 插入操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 hbase(main):003:0> put 'phone' ,'p001' ,'info:brand' ,'Apple' 0 row(s) in 0.1090 seconds hbase(main):004:0> put 'phone' ,'p001' ,'info:name' ,'iPhone 11 Pro' 0 row(s) in 0.0140 seconds hbase(main):005:0> put 'phone' ,'p002' ,'info:brand' ,'HUAWEI' 0 row(s) in 0.0110 seconds hbase(main):006:0> put 'phone' ,'p002' ,'info:name' ,'HUAWEI Mate 30 Pro' 0 row(s) in 0.0180 seconds hbase(main):007:0> put 'phone' ,'p002' ,'info:price' ,'5899' 0 row(s) in 0.0120 seconds
3 扫描操作 1 2 3 4 5 6 7 8 9 hbase(main):008:0> scan 'phone' ROW COLUMN+CELL p001 column=info:brand, timestamp=1716989818342, value=Apple p001 column=info:name, timestamp=1716989829913, value=iPhone 11 Pro p002 column=info:brand, timestamp=1716989838358, value=HUAWEI p002 column=info:name, timestamp=1716989846174, value=HUAWEI Mate 30 Pro p002 column=info:price, timestamp=1716989853905, value=5899 2 row(s) in 0.0290 seconds
4 查看操作 1 2 3 4 5 6 7 8 hbase(main):009:0> describe 'phone' Table phone is ENABLED phone COLUMN FAMILIES DESCRIPTION {NAME => 'info' , BLOOMFILTER => 'ROW' , VERSIONS => '1' , IN_MEMORY => 'false' , KEEP_DELETED_CELLS => 'FALSE' , DATA_BLOCK_ENCODING => 'NONE' , TTL => 'FOREVER' , COMPRESSION => 'NONE' , MIN_VERSIONS => '0' , BLOCKCAC HE => 'true' , BLOCKSIZE => '65536' , REPLICATION_SCOPE => '0' } 1 row(s) in 0.0340 seconds
从上述返回结果可以看出,数据表phone的表结构包含很多字段,具体介绍如下: NAME: 表示列族名。 BLOOMFILTER: 表示为列族级别的类型。 VERIONS: 表示版本数。 IN_MEMORY: 设置是否存入内存。 KEEP_DELETED_CELLS: 设置被删除的数据,在基于时间的历史数据查询中是否依然可见。 DATA_BLOCK_ENCODING: 表示数据块的算法。 TTL: 表示版本存活的时间。 COMPRESSION: 表示设置压缩算法。 MIN_VERSIONS: 表示最小版本数。 BLOCKCACHE: 表示是否设置读缓存。 REPLICATION_SCOPE: 表示设置备份。
5 更新操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 hbase(main):010:0> put 'phone' ,'p001' ,'info:name' ,'iPhone X' 0 row(s) in 0.0120 seconds hbase(main):011:0> scan 'phone' ROW COLUMN+CELL p001 column=info:brand, timestamp=1716989818342, value=Apple p001 column=info:name, timestamp=1716990146490, value=iPhone X p002 column=info:brand, timestamp=1716989838358, value=HUAWEI p002 column=info:name, timestamp=1716989846174, value=HUAWEI Mate 30 Pro p002 column=info:price, timestamp=1716989853905, value=5899 2 row(s) in 0.0220 seconds
6 获取指定字段的操作 1 2 3 4 5 6 hbase(main):012:0> get 'phone' ,'p001' COLUMN CELL info:brand timestamp=1716989818342, value=Apple info:name timestamp=1716990146490, value=iPhone X 2 row(s) in 0.0260 seconds
7 统计操作 1 2 3 4 5 hbase(main):013:0> count 'phone' 2 row(s) in 0.0200 seconds => 2
8 删除操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 hbase(main):014:0> delete 'phone' ,'p002' ,'info:price' 0 row(s) in 0.0240 seconds hbase(main):015:0> scan 'phone' ROW COLUMN+CELL p001 column=info:brand, timestamp=1716989818342, value=Apple p001 column=info:name, timestamp=1716990146490, value=iPhone X p002 column=info:brand, timestamp=1716989838358, value=HUAWEI p002 column=info:name, timestamp=1716989846174, value=HUAWEI Mate 30 Pro 2 row(s) in 0.0250 seconds hbase(main):016:0> deleteall 'phone' ,'p001' 0 row(s) in 0.0090 seconds hbase(main):017:0> scan 'phone' ROW COLUMN+CELL p002 column=info:brand, timestamp=1716989838358, value=HUAWEI p002 column=info:name, timestamp=1716989846174, value=HUAWEI Mate 30 Pro 1 row(s) in 0.0260 seconds hbase(main):018:0> truncate 'phone' Truncating 'phone' table (it may take a while ): - Disabling table... - Truncating table... 0 row(s) in 3.3890 seconds hbase(main):019:0> scan 'phone' ROW COLUMN+CELL 0 row(s) in 0.3220 seconds hbase(main):020:0> disable 'phone' 0 row(s) in 2.2370 seconds hbase(main):021:0> drop 'phone' 0 row(s) in 1.2410 seconds hbase(main):022:0> list TABLE 0 row(s) in 0.0070 seconds => []
HBase的Java API操作 十一、实战可视化管理Robo 3T
常见的可视化管理工具 :
1. 下载安装Robo 3T 下载地址 :https://robomongo.org/download/
Studio 3T
和 Robo 3T
的区别:前者是商业付费软件,后者开源免费软件
这里选择仅仅下载Robo 3T
填写好信息后点击下载 这里选择下载.exe
下载后得到exe
文件 双击运行进行安装,傻瓜式下一部安装完成即可
2. 使用Robo 3T 安装完成后打开 点击Create
创建一个链接,添加连接数据库的相关信息 我们开启了身份验证,因此需要填写身份验证的用户名和密码,最后Save
然后点击Connect
进行连接 成功连接到数据库 然后就可以可视化进行各种操作
十二、mongoose 1. 简介 mongoose.js
是node
中操作mongodb
的模块,可以通过node语法实现MongoDB数据库的增删改查
中文网:http://www.mongoosejs.net/
英文网:https://mongoosejs.com/
核心概念 :
schema
:约束字段/列数据
model
:对应集合,用它来实现数据增删改查
2. 安装 用Vscode
新建并打开一个文件夹,在终端输入如下命令安装mongoose
模块
1 2 # 安装 npm install mongoose
3. CURD语法 新建一个.js
文件,用来连接并操作mongodb数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 var mongoose = require ("mongoose" );const db = mongoose.createConnection ('mongodb://user:pass@localhost:port/database' ,{useNewUrlParser :true ,useUnifiedTopology :true },err => { if (err){ console .log ('数据库连接失败' ,err); return ; } console .log ('数据库连接成功' ); }) const model = db.model ('user' ,{ name :{type :String ,default :"username" }, age :{type :Number }, sex :{type :String } }) const insertObj = new model (数据对象)方法一:inserObj.save ((err )=> db.close ()) 方法二:(推荐) insertObj.save () .then (res => { return res }) .catch (err => { console .log ('插入失败' +err) return false }) 方法一:model.remove /deleteOne/deleteMany (条件对象,(err )=> db.close ()) 方法二:(推荐) model.deleteOne (条件对象) .then (res => { return res.deletedCount }) .catch (err => { console .log ('删除失败' +err) return false }) 方法一:model.update /updateOne/updateMany (条件对象,数据对象,(err )=> db.close ()) 方法二:(推荐) model.updateOne (条件对象,数据对象) .then (res => { return res.nModified }) .catch (err => { console .log ('修改失败' +err) return false }) 方法一:model.find /findOne (条件对象,要显示的字段数据对象,(err,result )=> db.close ()) 方法二:(推荐) model.findOne (条件对象) .then (res => { return res }) .catch (err => { console .log ('查询失败' +err) return false })
4. 测试 增 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 var mongoose = require ("mongoose" );const db = mongoose.createConnection ('mongodb://shop2:123456@localhost:27017/shop' , { useNewUrlParser : true , useUnifiedTopology : true }, err => { if (err) { console .log ('数据库连接失败' , err); return ; } console .log ('数据库连接成功' ); }) const model = db.model ('user' , { name : { type : String , default : "username" }, age : { type : Number }, sex : { type : String } }) const insertObj = new model ({ name : "zsr" , age : 21 , sex : "男" }) insertObj.save () .then (res => { console .log (res) return res }) .catch (err => { console .log ('插入失败' + err) return false })
然后运行测试: 然后打开Robo 3T
查看,可以看到成功插入数据
查 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 model.findOne ({}) .then (res => { console .log (res) return res }) .catch (err => { console .log ('查询失败' +err) return false }) model.find ({}).skip (0 ).limit (1 ) .then (res => { console .log (res) return res }) .catch (err => { console .log ('查询失败' +err) return false })
十三、接口 1. 简介 随着移动互联网的发展,客户端层出不穷,微信端、 WEB/PC、APP等等,而后端业务逻辑基本是一致的,如 何做到业务逻辑一次编写,多次/随时接入
呢?
就是定义接口,调用接口;
1️⃣ 什么是接口?
就是一个文件,主要响应JSON数据(操作方便,体积小)或XML数据
2️⃣ 接口能干嘛?
数据角度:让项目静态而数据动态
功能角度:短信接口,天气接口,股票接口
3️⃣ 去哪找?
通过node/go/java/php等语言去开发
使用第三方接口
4️⃣ 好处
实现一次编写,多次/随机接入,减小后端工作量,方便维护
2. 接口开发规范(Restful API)
3. 接口测试工具Postman 1. 简介 Postman
就是一个用来模拟http请求的工具,用于测试接口,查看接口返回数据
后端调试接口避免出现bug
前端查看接口是否使用并查看返回的数据内容
官网 :https://www.postman.com/
2. 下载安装 下载地址 :https://www.postman.com/downloads/ ,选择合适的版本下载 下载后得到.exe
文件,双击进行安装即可 安装完成自动打开,出现如下界面,我们可以在官网 创建一个账户进行登录,然后即可使用
3. 使用 新建一个request
请求 填写相关信息,然后保存 然后填写请求信息,这里以get
方式请求https://jsonview.com/example.json
在下面可以看到请求返回的数据
十四、express框架教学系统学生模块接口开发 1. express快速入门 1️⃣ 简介 :express
是基于nodejs开发第一个框架(原理:基于nodejs内置的http模块进行封装),加快项目开发,便于团队协作
官网 :https://www.expressjs.com.cn/
2️⃣ 下载 :
1 npm install express --save
3️⃣ 简单使用 :创建一个js
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const express = require ("express" );const app = express ()app.get ('/' ,(req,res )=> { res.send ("hello" ) }) app.listen (3000 , () => { console .log ('http://localhost:3000' ); })
运行该js
文件测试,打开浏览器3000
端口,可以看到效果
2. 教学系统学生模块接口开发
项目总结构:
1. 安装模块依赖 新建一个空目录,用vscode打开,首先安装相关模块
1 2 3 npm install express --save npm install mogoose npm install body-parser
2 expree框架搭建,定义路由 新建入口文件student.js
,首先快速搭建express框架web服务器,其中定义两个路由:
get
方式请求/stu
,用于添加学生,用stuController.add方法处理(后续编写)
post
方式请求/stu
,用于查询所有学生,用stuController.index方法处理(后续编写)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 const express = require ("express" );const bodyparser = require ('body-parser' )const app = express ()app.use (bodyparser.urlencoded ({extended :true })) app.use (bodyparser.json ()) const stuController = require (process.cwd () + '/controller/stuController' )app.post ('/stu' , stuController.add ) app.get ('/stu' ,stuController.index ) app.listen (3000 , () => { console .log ('http://localhost:3000' ); })
3. mongoose模块操作数据库 在项目目录下新建models
包,其中新建stuModels.js
,采用mongoose
模块实现操作mongodb数据库,定义并暴露两个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 var mongoose = require ("mongoose" );const db = mongoose.createConnection ('mongodb://shop2:123456@localhost:27017/shop' , { useNewUrlParser : true , useUnifiedTopology : true }, err => { if (err) { console .log ('数据库连接失败' , err); return ; } console .log ('数据库连接成功' ); }) const model = db.model ('stu' , { name : { type : String , default : "zsr" }, age : { type : Number }, sex : { type : String } }) const insert = postData => { const insertObj = new model (postData) return insertObj.save () .then (res => { return res }) .catch (err => { console .log ('插入失败' + err) return false }) } const query = ( ) => { return model.find () .then (res => { return res }) .catch (err => { console .log ('查询失败' + err) return false }) } module .exports = { insert, query }
3. 编写路由处理方法 在项目目录下新建controller
包,其中新建stuController.js
,用于处理路由,其中暴露两个方法:
add
用于处理post请求/stu
添加学生
index
用于处理get请求/stu
查询全部学生
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 const stuModel = require (process.cwd () + '/models/stuModel' )const add = async (req, res ) => { let postData = req.body console .log (postData) let rs = await stuModel.insert (postData) if (rs) { res.send ({ meta : { state : 200 , msg : "添加成功" }, data : null }) } else { res.send ({ meta : { state : 500 , msg : "添加失败" }, data : null }) } } const index = async (req, res ) => { let data = await stuModel.query () res.send ({ meta : { stage : 200 , msg : "查询成功" }, data : data }) } module .exports = { add, index }
4. 测试 运行入口文件student.js
,然后打开postman
进行测试
1️⃣ 首先进行 添加学生 测试,以post
方式请求http://localhost:3000/stu
根据返回结果,可以看到成功添加,再回到Robo 3T
查看数据库结果,成功添加学生
2️⃣ 然后进行 查询所有学生 测试,以get
方式请求http://localhost:3000/stu
根据返回结果,成功查询到学生信息
3. 接口文档开发apiDoc 1. 简介 apiDoc
就是nodejs中的一个模块,用于通过注释快速生成接口文档
官网 :https://apidocjs.com/
2. 使用 1️⃣ 下载模块,后期通过注释生成接口文档
2️⃣ 项目根目录下创建apidoc.json
文件,格式如下:
1 2 3 4 5 6 7 { "name" : "example" , "version" : "0.1.0" , "description" : "apiDoc basic example" , "title" : "Custom apiDoc browser title" , "url" : "https://api.github.com/v1" }
3️⃣ 添加接口注释,在stuController.js
处理路由方法中添加注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 const stuModel = require (process.cwd () + '/models/stuModel' )const add = async (req, res ) => { let postData = req.body console .log (postData) let rs = await stuModel.insert (postData) if (rs) { res.send ({ meta : { state : 200 , msg : "添加成功" }, data : null }) } else { res.send ({ meta : { state : 500 , msg : "添加失败" }, data : null }) } } const index = async (req, res ) => { let data = await stuModel.query () res.send ({ meta : { stage : 200 , msg : "查询成功" }, data : data }) } module .exports = { add, index }
4️⃣ 生成接口文档
1 apidoc -i ./接口注释目录 -o ./接口文档存放目录
运行以上命令后,项目根目录下生成了doc
目录,找到其中的index.html
文件 用浏览器打开,就是生成的接口文档