MongoDB-Springboot增删改查

学习思路

  1. 对比mysql名词解释
  2. 分布式原理
  3. 代码实现

一、对比mysql名词解释

解释:一个database包含多个collection,document以json格式存储,同时也支持唯一索引和联合索引,用的方式和mysql基本一致,创建索引时也跟mysql一样会默认锁表,但mongodb提供了background方式让创建工作在后台执行,避免了长时间锁表

db.values.createIndex({open: 1, close: 1}, {background: true})

解释:为values集合创建复合索引,key为open、close两个字段,在后台执行,1为按升序创建索引、如果想按降序创建索引可用-1

二、分布式原理

1、MongoDB复制(副本集)

  1. 保障数据的安全性,其中一个副本异常数据完整性不受影响
  2. 提高高可用
  3. 灾难恢复
  4. 无停机维护(备份、压缩)
  5. 分布式读取数据

2、复制原理

MongoDB复制至少需要两个节点,一般可部署为一主一从、一主多从,

客户端写数据时,先写入主节点,然后记录oplog,然后从节点定时读取进行同步,可见这里同步并不是强一致性,而是最终一致性,可能存在短时间的数据不一致

3、分片

任何数据库 或其它分片归根结底都是在写入或读取是遇到了瓶颈(硬件、数据量等)

MongoDB的分片集群机构主要有三个组件构成:Shard、Config Server、Query Routers

解释:

  1. Router(mongos):前端路由,客户端由此接入,后台集群对客户端无感知可像连接单一库一样透明使用,从Config Server获取分片配置路由数据
  2. Config Server:mongod实例,存储了整个集群的配置数据,包含chunk(见后面)
  3. Shard(replica set):实际存储数据的数据块,实际中一个shard Server可能由多台机器组成一个副本集,防止单点故障

使用时可逐个启动Shard Server、Config Server、Router然后在Router节点添加Shard(副本集)暴露Router统一ip端口即可,这个对客户端暴露的时候建议暴露域名,后台Router上线线可对客户端无感知

4、数据分裂、迁移

每个分片都有多个chuck(数据块)组成默认64M,数据写入时超过64M会 进行自动分裂

当单分片上分裂过多,导致多分片chuck数量不均衡时,会在分片间进行迁移,实现均衡负载

如无特殊需求,建议保持默认值;chunkSize 会直接影响到 chunk 分裂、迁移的行为。

  • chunkSize 越小,chunk 分裂及迁移越多,数据分布越均衡;反之,chunkSize 越大,chunk 分裂及迁移会更少,但可能导致数据分布不均。
  • chunkSize 太小,容易出现 jumbo chunk(即shardKey 的某个取值出现频率很高,这些文档只能放到一个 chunk 里,无法再分裂)而无法迁移;chunkSize 越大,则可能出现 chunk 内文档数太多(chunk 内文档数不能超过 250000 )而无法迁移。
  • chunk 自动分裂只会在数据写入时触发,所以如果将 chunkSize 改小,系统需要一定的时间来将 chunk 分裂到指定的大小。
  • chunk 只会分裂,不会合并,所以即使将 chunkSize 改大,现有的 chunk 数量不会减少,但 chunk 大小会随着写入不断增长,直到达到目标大小。

三、代码实现

1、引入jar包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2、application.properties配置mongodb

spring.data.mongodb.uri=mongodb://localhost:27017/product

3、自定义document

@Document(collection = "order_info")
public class OrderInfo implements Serializable {
	@Id
	private Long id;
	private String desc;
	@Field(targetType=FieldType.INT64)
	private Date createTime=new Date();
	private Date updateTime=new Date();
	@Field(value = "id")
	private String orderNo;
}

order_info是我们自定义的集合名,类似于表名,如果对象字段名和存储的字段名不一致可用@Field注解

4、自定义Repository类

public interface OrderInfoRepository extends MongoRepository<OrderInfo,Long> {
	OrderInfo getById(Long orderNo);
}

继承MongoRepository,Long是docuement的主键类型,

当然可以自定义,比如getBy+字段名称即可实现响应查询

5、自定义服务-增删改查

public class MongoDBService {

	@Autowired
	MongoTemplate mongoTemplate;
	@Autowired
	OrderInfoRepository orderInfoRepository;

	public void insert(OrderInfo orderInfo){
//		log.info("insert====={}", JSON.toJSONString(mongoTemplate.insert(orderInfo)));
		log.info("insert=====1=={}",JSON.toJSONString(orderInfoRepository.insert(orderInfo)));
	}
	public void insertAll(List<OrderInfo> list){
		log.info("insertAll==={}",JSON.toJSONString(mongoTemplate.insertAll(list)));
	}
	public void updateById(OrderInfo orderInfo){
		if (orderInfo!=null && orderInfo.getId()!=null){
			Query query=new Query(Criteria.where("_id").is(orderInfo.getId()));
			Update update=new Update();
			update.set("desc",orderInfo.getDesc());
			log.info("updateResult==={}",JSON.toJSONString(mongoTemplate.updateMulti(query, update, OrderInfo.class)));
		}
	}
	public void getById(Long orderNo){
		log.info("getById===={}",JSON.toJSONString(mongoTemplate.findById(orderNo,OrderInfo.class)));
		log.info("getById====1==={}",JSON.toJSONString(orderInfoRepository.getById(orderNo)));
	}
	public void getByPage(int pageIndex,int pageNo,OrderInfo orderInfo){
		Query query=new Query().limit(pageNo).skip(pageIndex);
		log.info("getByPage====={}",JSON.toJSONString(mongoTemplate.find(query,OrderInfo.class)));
		ExampleMatcher matcher=ExampleMatcher.matching()
				.withIgnorePaths("createTime","updateTime");
		Example<OrderInfo> ex = Example.of(orderInfo,matcher);
		log.info("getByPage====={}",JSON.toJSONString(orderInfoRepository.findAll(ex, PageRequest.of(pageIndex,pageNo))));
	}
	public void findAll(OrderInfo orderInfo){
		ExampleMatcher matcher=ExampleMatcher.matching()
				.withMatcher("desc",ExampleMatcher.GenericPropertyMatchers.exact())
				.withIgnorePaths("createTime","updateTime")
				.withIgnoreNullValues();
		Example<OrderInfo> ex = Example.of(orderInfo,matcher);
		log.info("findAll====={}",JSON.toJSONString(orderInfoRepository.findAll(ex)));
	}
}

文中代码地址:https://gitee.com/carpentor/spring-cloud-example

公众号主要记录各种源码、面试题、微服务技术栈,帮忙关注一波,非常感谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值