jjzjj

mongodb - 确保 MongoDB 以动态时间间隔使数据过期并且调用是幂等的

coder 2024-07-05 原文

我正在使用 MongoDB 将用户生成的链接保存在存储器中。用户可以说明他们希望 URL 在过期之前保存多长时间。每个用户 ID 也是唯一的。

理想情况下,我希望我的请求是幂等的。我想调用尽可能多的电话,而不必检查最后一次电话是否有到期值。

我下面的代码似乎给了我:

  • “名称为 creationtime_1 的索引已存在,但选项不同”或
  • 索引不存在。

这是我第一次使用 MongoDB,如果有任何见解,我将不胜感激。我想我也可能对我的代码进行了冗余检查,但我不知道该怎么做

```

//mongo settings
sessionTTL := mgo.Index{
    Key:         []string{"creationtime"},
    Unique:      false,
    DropDups:    false,
    Background:  true,
    ExpireAfter: time.Hour * time.Duration(expires)} // Expire in expire time

// START MONGODB
session, err := mgo.Dial(tokenMongo)
if err != nil {
    return "", err
}
defer session.Close()
//session.SetSafe(&mgo.Safe{})

// Optional. Switch the session to a monotonic behavior.
id := uuid.NewV4().String()

thistime := time.Now().Local()


// find index
err = session.DB("tokenresults").C("tokenurl").Find(bson.M{"id": id}).One(&result)
if err == nil{
    //Drop old values if exist // cant drop if empty
    if err := session.DB("tokenresults").C("tokenurl").DropIndex("creationtime"); err != nil {
        return "", err
    }
}

//add stuff
c := session.DB("tokenresults").C("tokenurl")
err = c.Insert(&TokenUrl{id, tokenstring, thistime}, )
if err != nil {
    return "", err
}

// create index //add session ttl // cant create if exists
if err := session.DB("tokenresults").C("tokenurl").EnsureIndex(sessionTTL); err != nil {
    return "", err
}

```

最佳答案

解决方案

方法is documented :使用日期字段,将值设置为文档过期的日期,创建一个 TTL 索引并将 ExpireAfterSeconds 设置为 0,MongoDB 后台 TTL 清除过程将删除过期的文档。

注意事项

但是,使用 TTL 索引存在一些模糊性。由于对每个即将过期的文档都有一个进程,等待过期时间,然后删除文档,成本太高,MongoDB 选择了不同的解决方案。 There is a background process which checks for expired documents once a minute .因此,无法保证您的文档会在到期时间立即到期,并且文档可能比设定的到期日期长不到 2 分钟(由于过载或其他原因错过了第一次运行,并且只会在下一次删除)运行)。但是请注意,这仅在非常特殊的情况下才会发生。通常,您的文件会在过期后的几分钟内被删除。

说明

我们基本上在这里做的是添加一个字段 ExpirationDate 并创建一个 TTL 索引,该索引设置为检查此到期日期。将此 ExpirationDate 设置为哪个值完全取决于您。使用工厂模式生成 session 或其他内容。

请注意,下面的代码中解释了一些注意事项。

package main

import (
    "flag"
    "fmt"
    "log"
    "time"

    mgo "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
)

const (
    // SESSION_TIMEOUT is a fixed and relatively short
    // timeout for demo purposes
    SESSION_TIMEOUT = 1 * time.Minute
)

// Session is just a sample session struct
// with various session related data and the
// date on which a session should expire.
type Session struct {
    ID             bson.ObjectId `bson:"_id"`
    User           string
    Foo            string
    Bar            string
    ExpirationDate time.Time `bson:"expirationDate"`
}

// NewSession is just a simple helper method to
// return a session with a properly set expiration time
func NewSession(user, foo, bar string) Session {
    // We use a static timeout here.
    // However, you can easily adapt this to use an arbitrary timeout.
    return Session{
        ID:             bson.NewObjectId(),
        User:           user,
        Foo:            foo,
        Bar:            bar,
        ExpirationDate: time.Now().Add(SESSION_TIMEOUT),
    }
}

var (
    mgohost string
    mgoport int
    db      string
    col     string
)

func init() {
    flag.StringVar(&mgohost, "host", "localhost", "MongoDB host")
    flag.IntVar(&mgoport, "port", 27017, "MongoDB port")
    flag.StringVar(&db, "db", "test", "MongoDB database")
    flag.StringVar(&col, "collection", "ttltest", "MongoDB collection")

}

func main() {
    flag.Parse()

    c, err := mgo.Dial(fmt.Sprintf("mongodb://%s:%d/%s", mgohost, mgoport, db))
    if err != nil {
        log.Fatalf("Error connecting to '%s:%d/%s': %s", mgohost, mgoport, db, err)
    }

    // We use a goroutine here in order to make sure
    // that even when EnsureIndex blocks, our program continues
    go func() {
        log.Println("Ensuring sessionTTL index in background")

        // Request a conncetion from the pool
        m := c.DB(db).Session.Copy()
        defer m.Close()

        // We need to set this to 1 as 0 would fail to create the TTL index.
        // See https://github.com/go-mgo/mgo/issues/103 for details
        // This will expire the session within the minute after ExpirationDate.
        //
        // The TTL purging is done once a minute only.
        // See https://docs.mongodb.com/manual/core/index-ttl/#timing-of-the-delete-operation
        // for details
        m.DB(db).C(col).EnsureIndex(mgo.Index{ExpireAfter: 1 * time.Second, Key: []string{"expirationDate"}})

        log.Println("sessionTTL index is ready")
    }()

    s := NewSession("mwmahlberg", "foo", "bar")

    if err := c.DB(db).C(col).Insert(&s); err != nil {
        log.Fatalf("Error inserting %#v into %s.%s: %s", s, db, col, err)
    }

    l := Session{}

    if err := c.DB(db).C(col).Find(nil).One(&l); err != nil {
        log.Fatalf("Could not load session from %s.%s: %s", db, col, err)
    }
    log.Printf("Session with ID %s loaded for user '%s' which will expire in %s", l.ID, l.User, time.Until(l.ExpirationDate))
    time.Sleep(2 * time.Minute)

    // Let's check if the session is still there

    if n, err := c.DB(db).C(col).Count(); err != nil {
        log.Fatalf("Error counting documents in %s.%s: %s", db, col, err)
    } else if n > 1 {
        log.Fatalf("Uups! Someting went wrong!")
    }

    log.Println("All sessions were expired.")
}

关于mongodb - 确保 MongoDB 以动态时间间隔使数据过期并且调用是幂等的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48445720/

有关mongodb - 确保 MongoDB 以动态时间间隔使数据过期并且调用是幂等的的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  3. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  4. ruby-on-rails - 将 Ruby 中的日期/时间格式化为 YYYY-MM-DD HH :MM:SS - 2

    这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build

  5. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  6. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  7. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  8. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  9. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  10. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

随机推荐