前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >mongo集群中读写操作与并发

mongo集群中读写操作与并发

原创
作者头像
王宝
修改2024-11-27 08:58:13
修改2024-11-27 08:58:13
1010
举报
文章被收录于专栏:核心思路逻辑核心思路逻辑

主从读取策略

副本集mongo中,在没有指定读取策略的情况下,默认到primary读取

  •  readPreference

 1、含义: 

主要控制客户端driver从副本集(Replica Set)读数据的时候如何路由

  各个配置值的含义如下:

  • primary:只主(默认模式)。只从primary节点读数据。
  • primaryPreferred:先主后从。优先从primary读取,primary不可用时从secondary读。
  • secondary:只从。只从副本集中secondary节点读数据。
  • secondaryPreferred:先从后主。优先从secondary读取,如果secondary不可用时就从primary读。
  • nearest:就近。根据网络距离,就近读取,根据客户端与服务端的PingTime是实现

 2、配置secondaryPreferred示例

mongodb+srv://xxx.com?ssl=false&retryWrites=true&w=majority&readConcernLevel=majority&readPreference=secondaryPreferred

upsert是否为原子操作

mongo的upsert命令【不是】原子的,upsert 分为两步:

  • 找数据
  • 覆盖数据或插入数据

在使用该功能时,需考虑fifter条件是否作唯一,  在并发下,多个线程或协程同时 upsert 并完成找数据这一步操作,此时这些线程都没有找到数据,然后都进行插入数据的操作,于是重复数据便产生了;

解决这一问题的方案有两种种:

1、一种是给表加唯一索引

2、给执行upsert 操作加上一个写锁,

大多数情况下,我们采用第一种,在代码上线前,先执行唯一索引

db.$collection.createIndex($unique_keys, { backgroud : true, unique : true}),如果不加【unique : true】则为普通索引,解决不了并发重复的问题

事务问题

事务中读操作

mongo在指定读写分离时,即 readPreference=secondaryPreferred或者readPreference=secondary时, 在代码中开启事务时,事务的sessionContext不能用于查询,事务的读只能在主库处理,否则会报错误【 read preference in a transaction must be primary】, 如果事务中没有读取操作,则不存在该问题

处理方案

  为了在读取操作也使用事务功能,  需要在开启事务时指定主库操作,后面就可以在读取时,使用事务的sessionContext,如下

opts := &options.TransactionOptions{ReadPreference: readpref.Primary()}

sessionContext.StartTransaction(opts)

代码语言:txt
复制
ctx := context.Background()
client := mongo.GetClient(constant.DBPrefix)
 
err := client.UseSession(ctx, func(sessionContext m.SessionContext) error {
    
opts := &options.TransactionOptions{ReadPreference: readpref.Primary()}   
//关键代码,如果事务中全是写入操作,此处不必指定
    
err := sessionContext.StartTransaction(opts)
 
    
// 后续的db操作要用事务就用sessionContext
    
// 不用事务就用ctx,正常情况下,开启事务后,里面的db操作都应该使用事务的sessionContext
    
//err = mongo.MongoDBCurd(constant.DBPrefix, mongomodel.MyCollectionName).Find(ctx, query, &list)  //无事务读取   
    
err = mongo.MongoDBCurd(constant.DBPrefix, mongomodel.MyCollectionName).Find(sessionContext, query, &list)
//有事务的读取
    
    
if err != nil {
        
   _ = sessionContext.AbortTransaction(sessionContext)
       
   return err  
}
     
   _ = sessionContext.CommitTransaction(sessionContext)
       
   return nil
})

参考文献

https://www.mongodb.com/docs/manual/core/read-preference

https://www.mongodb.com/zh-cn/docs/manual/core/read-preference/

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 主从读取策略
    •  1、含义: 
    •  2、配置secondaryPreferred示例
  • upsert是否为原子操作
  • 事务问题
    • 事务中读操作
    • 处理方案
  • 参考文献
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档