MongoDB的使用及集群搭建

来源:互联网 发布:淘宝 iphone att群 编辑:程序博客网 时间:2024/05/17 08:07

大数据面临问题:存储 、 分析

存储: 数据库 RMDBS 关系型数据库(MySQL、ORACLE)表 存储
RMDBS: 分库 –> 解决存储

缺点: 不稳定,维护成本高、极大的限制
查询 (只能通过 片键 去查)
性能:基于磁盘 修改|查询>动用磁盘IO 慢 coonection连接数 有限 无法应对 高并发
解决:cache(无法保证缓存和db数据高度一致性) | 读写分离
分析:并没有很好的算法支持分析

解决方案:
存储:NoSQL (not only SQL)并不是替换 RMDBS 而是一种补充
① 很好的集群支持(主从、副本集、分片、分片+副本集)
② 很好的性能 基于内存 支持高并发

摒弃RMDBS的要求:
1、schemaless 弱化表结构
2、弱化事务、弱化约束

NoSQL:Redis 、MongoDB、HBase
1、redis:key-value Map 键值对 内存
2、MongoDB:文档(json) 不支持事务 磁盘 利用率高
3、HBase :列存储 大数据随机访问 10亿行*百万列 量级

MongoDB:

特点
1.不支持事务
2.基于磁盘存储
3.单条记录不得超过16M
4.没有表结构没有约束

与RDBMS对比

RDBMS: 磁盘利用率低
Mongodb:磁盘利用率高 插入速度快

MongoDB安装与使用

1,解压

[root@zpark ~]# tar -zxf mongodb-linux-i686-3.0.6.gz -C /usr/

2.启动MongoDB

参考:[root@zpark mongodb]# ./bin/mongod -h查看启动参数
[root@zpark mongodb]# ./bin/mongod –port 27017 –dbpath ~/db/data/ –journal

3.连接mongo

参考:[root@zpark mongodb]# ./bin/mongo -h
[root@zpark mongodb]# ./bin/mongo –port 27017

1.数据库操作

查看库

db

查看所有库

show databases|dbs

创建库

use 数据库名

删除

db.dropDatabase();

建表>db.createCollection(‘t_user’)
查表>show tables|collections
db.getCollectionNames();
删除表>db.表名.drop();

1.保存

db.表名.save/insert({document});

2.修改$set / $inc /$unset multi/upsert)

db.表名.update({query},{update}[,{options}])
db.t_user.update({id:1},{$set:{salary:12000}})
db.t_user.update({id:1},{$inc:{salary:12000}})
db.t_user.update({id:1},{$unset:{salary:true}})
db.t_user.update({id:4},{$inc:{salary:500}},{multi:true,upsert:true})

3.删除

db.表名.remove({query})

4.查询

等值查

db.表名.findOne({query}[,{fieds}]) //返回一条记录 Document
db.表名.find({query}[,{fieds}])//返回多条 DBCursor 游标 只可以遍历一次

等值

db.t_user.find({id:1})
db.t_user.find({id:{$eq:1}})

不等值查 (> < >= <= != !) gt lt gte lte ne not

db.t_user.find({salary:{$gt:7000}})

AND 操作

db.t_user.find({salary:{$gt:10000,$lt:20000},sex:true})

OR | NOR

db.t_user.find({$or:[{id:1},{name:’lisi’}]})
db.t_user.find({$nor:[{id:1},{name:’lisi’}]})

IN | NIN

db.t_user.find({id:{$in:[1,2,3]}})
db.t_user.find({id:{$nin:[1,2,3]}})

判断field 是否存在 exists

db.t_user.find({name:{$exists:false}})

正则搜索 $regex 只适用于字符串

db.t_user.find({name:{$regex:’^[a-zA-Z]{4}$’}})
db.t_user.find({$or:[{name:{$regex:’^.小.$’}},{id:1}]})

投影查询

db.t_user.find({},{_id:false,id:true,sex:true})

分页

db.t_user.find({}).skip(1).limit(3)

排序

db.t_user.find({}).skip(1).limit(3).sort({id:-1}).pretty();

查询salary最小

db.t_user.find({}).skip(0).limit(1).sort({salary:1}).pretty();

查询总记录数

db.t_user.find({}).count() //返回查询到的文档数目
db.t_user.find({}).size() //返回游标的大小

5、索引:

获取所有索引:

db.t_user.getIndexes();

创建索引:

db.t_user.ensureIndex({name:1},{name:’name_index’})

删除索引:

db.t_user.dropIndex(“name_index”)

复合索引:

db.t_user.ensureIndex({name:1,age:1},{name:’name_age_index’})

唯一索引:

db.t_user.ensureIndex({name:1},{name:”name_index”,unique:true});

稀疏索引:

db.t_user.ensureIndex({name:1},{name:”name_index”,unique:true,sparse:true});

SpringData操作MongoDB(Spring-4.2.8版本)

spring.xml配置文件

<mongo:mongo id="mongo" host="192.168.11.128" port="27017">    <mongo:options connections-per-host="8"        threads-allowed-to-block-for-connection-multiplier="4"        connect-timeout="1000"        max-wait-time="1500"        auto-connect-retry="true"        socket-keep-alive="true"        socket-timeout="1500"        slave-ok="true"        write-number="1"        write-timeout="0"        write-fsync="true"/>    </mongo:mongo>    <mongo:db-factory id="dbFactory" dbname="love" mongo-ref="mongo"/>    <!-- 配置momngoTemplate -->    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">        <constructor-arg index="0" ref="dbFactory"/>    </bean>

代码
测试类

public class TestMongoDB {    private Mongo mongo;    private MongoTemplate mongoTemplate;    private DB db;    private DBCollection collection;    @Before    public void before(){        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");        mongo = (Mongo) ac.getBean("mongo");        mongoTemplate = (MongoTemplate) ac.getBean("mongoTemplate");    }    @Test    public void save(){        Hero hero=new Hero("张局座",42,new Date());        mongoTemplate.save(hero);    }    @Test    public void find(){        Query query=new Query();        Criteria criteria=new Criteria();        query.addCriteria(criteria);        List<Hero> find = mongoTemplate.find(query, Hero.class);        for(Hero hero:find){            System.out.println(hero);        }    }    @Test    public void findCriteria(){        Query query=new Query();        Criteria criteria=new Criteria("name");        criteria.is("spiderMan");        criteria.and("age").equals("22");        query.addCriteria(criteria);        List<Hero> find = mongoTemplate.find(query, Hero.class);        System.out.println(find);    }    @Test    public void findById(){        Hero findById = mongoTemplate.findById("5860bff364282b8143a92386", Hero.class);        System.out.println(findById);    }    @Test    public void count(){        Query query=new Query();        long count = mongoTemplate.count(query, Hero.class);        System.out.println(count);    }    @Test    public void update(){        Query query=new Query();        Criteria criteria=new Criteria("name");        criteria.is("张局座");        query.addCriteria(criteria);        Update update=new Update();        update.set("age", 41);        WriteResult updateFirst = mongoTemplate.updateFirst(query, update, Hero.class);        System.out.println(updateFirst);    }    @Test    public void delete(){        Query query=new Query();        Criteria criteria=new Criteria("name").is("superMan");        query.addCriteria(criteria);        WriteResult remove = mongoTemplate.remove(query, Hero.class);        System.out.println(remove);    }    @Test    public void queryAll(){        Query query=new Query();        query.skip(0);        query.limit(5);        Sort sort=new Sort(Direction.ASC,"age");        query.with(sort);        List<Hero> find = mongoTemplate.find(query, Hero.class);        for(Hero hero:find){            System.out.println(hero);        }    }}

实体类

public class Hero implements Serializable{    @Id    private String id;    @Field    @Indexed(direction=IndexDirection.ASCENDING,name="name_index",unique=true,sparse=true)    private String name;    @Indexed(direction=IndexDirection.ASCENDING,name="age_index",unique=true,sparse=true)    private Integer age;    private Date bir;    public Hero(String name, Integer age, Date bir) {        super();        this.name = name;        this.age = age;        this.bir = bir;    }    public Hero() {        super();        // TODO Auto-generated constructor stub    }    public String getId() {        return id;    }    public void setId(String id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }    public Date getBir() {        return bir;    }    public void setBir(Date bir) {        this.bir = bir;    }    @Override    public String toString() {        return "Hero [id=" + id + ", name=" + name + ", age=" + age + ", bir="                + bir + "]";    }}

辅线

主从架构(old):
优点:数据冗余备份
缺点:机器的故障转移一般需要人工干预;存储 遵循 木桶原理
应用:读写分离

副本集(升级版主从):
优点:数据冗余备份,故障转移
缺点:存储 遵循 木桶原理

分片(起源 RDBMS 分库分表):
优点: 提升系统的并发能力,提升系统存储能力
缺点: 增加了系统故障率,一旦有一台宕机整个集群处于宕机状态.
副本集+分片: 解决存储/并发 故障率降低了

启动主机:

[root@zpark ~]# ./mongodb/bin/mongod –port 27017 –dbpath /db/master/ –journal –master

启动从机

[root@zpark ~]# ./mongodb/bin/mongod –port 27018 –dbpath /db/slave/ –journal –slave –source 192.168.12.129:27017

查看当前是否是主机:

rs.isMaster();

如果查看从机器:

rs.slaveOK();

副本集搭建

启动三台副本集合

[root@zpark ~]# ./mongodb/bin/mongod –port 27017 –dbpath ~/db/rep1/ –journal –replSet zpark
[root@zpark ~]# ./mongodb/bin/mongod –port 27018 –dbpath ~/db/rep2/ –journal –replSet zpark
[root@zpark ~]# ./mongodb/bin/mongod –port 27019 –dbpath ~/db/rep3/ –journal –replSet zpark

use adminvar config = { _id:"zpark", members:[{_id:0,host:"192.168.12.129:27019"},{_id:1,host:"192.168.12.129:27018"},{_id:2,host:"192.168.12.129:27017"}]}rs.initiate(config) | rs.isMaster();rs.status();//查看集群状态

副本集运维(只能在主机上运维集群):

①添加一台机器到集群

[root@zpark ~]# ./bin/mongod –port 27020 –dbpath ~/db/rep4/ –journal –replSet zpark
rs.add(‘192.168.12.129:27020’)/rs.add({_id:3,host:”192.168.12.129:27020”})

②删除一个节点

rs.remove(‘192.168.12.129:27020’)

节点类型介绍
主节点 /从节点/仲裁节点/secondary Only节点/隐藏节点/延迟节点/non-voting节点

1、仲裁节点:
只参与 选举/投票 不参与存储 一般用于凑数

2、secondary Only节点:
永远只当从节点 永远都不可以成为主
var conf=rs.conf();
conf[].priority=0
rs.reconf(conf);

3、隐藏节点:
var conf=rs.conf();
conf[].priority=0
conf[].hidden=true
rs.reconf(conf);

4、延迟节点:
var conf=rs.conf();
conf[].priority=0
conf[].hidden=true
conf[].slaveDelay=3600
rs.reconf(conf);

5、non-voting节点
var conf=rs.conf();
conf[].votes=0
rs.reconf(conf);
注意事项:一般要求3台机器作为一个副本集合 MongoDB的副本级别最大上限是17个,其中最对7台具备投票权

分片搭建:
1.启动两个shard (启动两个副本集)

[root@zpark ~]# ./bin/mongod –port 27017 –dbpath ~/db/shard1/ –journal –shardsvr
[root@zpark ~]# ./bin/mongod –port 27018 –dbpath ~/db/shard2/ –journal –shardsvr

2.启动confserver(启动三台)

[root@zpark ~]# ./bin/mongod –port 27019 –dbpath ~/db/conf/ –journal –configsvr

3.启动路由服务

[root@zpark ~]# ./bin/mongos –port 27020 –configdb 192.168.12.129:27019,[….]

4.连接路由服务器写入集群配置

[root@zpark ~]# ./bin/mongo –port 27020

5、启动

use adminsh.addShard("192.168.12.129:27017") //sh.addShard("副本集id/server:port,...")sh.addShard("192.168.12.129:27018") db.runCommand({addshard : "192.168.12.129:27018",  "name" : "shard00000" })sh.enableSharding('baizhi');//开启对baizhi库的分片sh.shardCollection("baizhi.t_user",{_id:1}); // range based shard sh.shardCollection('baizhi.t_email',{_id:'hashed'});//hash bashed shard

6、插入测试数据

use baizhifor(var i=0; i<10000; i++){db.t_user.insert({name:"user"+i, age:i, email:"zpark@163.com" })}db.printShardingStatus();db.t_user.stats();

7、shard管理:

①添加shard

[root@zpark ~]# ./bin/mongod –port 27021 –dbpath ~/db/shard3/ –journal –shardsvr

②删除节点

use admin
db.runCommand({removeShard : “shard0001”});

0 0