Google Go 中的 App Engine 数据存储分片
Google App Engine Datastore sharding in Go
我在 GAE 中制作了一个分片,只是有时,在 运行 分片代码后并不总是收到此消息。
(datastore_v3: BAD_REQUEST): Key path element must not be incomplete: [ResumeShard: ]
代码:
//Sharding
//Getting shard ID
rand.Seed(time.Now().UnixNano())
shardId := rand.Int63n(5)
resumeShardKey := datastore.NewKey(*pC, "ResumeShard", "", accountKey.IntID()+shardId, nil)
var resumeShard param.ResumeShard
if err = datastore.Get(*pC, resumeShardKey, &resumeShard); err != nil {
if err == datastore.ErrNoSuchEntity {
resumeShard = param.ResumeShard{}
resumeShard.Counter = 1
} else {
log.Println(err.Error())
}
} else {
resumeShard.Counter += 1
}
*pC
是指向来自 appengine 的上下文的指针。
accountKey
是每个用户独有的数据存储 Key
。
此错误随机出现,例如 10 次请求中出现 3 次。我想知道,因为我必须使用 datastore.NewKey(..)
为分片创建密钥,我怎样才能获得调用 Put(..)
后我将收到的完整密钥,因为这是分片,GAE 文档上的示例使用 datastore.NewKey(..)
还有。
请推荐。
您收到一条错误消息,指出您提供的密钥不完整。这是因为您指定了一个空键名 (""
) (stringID
),并且 accountKey.IntID()
加上一个随机数(来自范围 0..4
- 包括两者)作为数字密钥 ID (intID
)。请注意,如果您的 accountKey.IntID()
未初始化,它将是 0
并且随机数也可能是 0
在这种情况下, 0
用作 intID
.
并引用 datastore.Key
的文档:
Either one or both of stringID
and intID
must be zero. If both are zero, the key returned is incomplete.
intID
获得 0
的几率是 5 分之 1,即 20%(这接近您报告的 10 分之 3)。
intID
的 0
值无效,它必须是非零值,因为 0
是一个特殊值,就像空字符串 ""
为stringID
,两者都用来表示,另一个属性用来标识实体;或者 - 如果两者都是零值 - 表示密钥是不完整的密钥(因此需要系统随机分配 intID
)。
请注意,此解决方案不好,因为您使用的密钥具有 相对 数字 ID (intID
),相对于帐户密钥的数字 ID (accountKey.IntID()
).系统分配的密钥将随机分配,但有可能 2 个帐户密钥可能彼此接近(例如,一个是另一个 +1)。在这种情况下,您的分片键会重叠!
如果使用datastore.Put()
保存实体,系统分配的随机键是Put()
的return值:
func Put(c context.Context, key *Key, src interface{}) (*Key, error)
我在 GAE 中制作了一个分片,只是有时,在 运行 分片代码后并不总是收到此消息。
(datastore_v3: BAD_REQUEST): Key path element must not be incomplete: [ResumeShard: ]
代码:
//Sharding
//Getting shard ID
rand.Seed(time.Now().UnixNano())
shardId := rand.Int63n(5)
resumeShardKey := datastore.NewKey(*pC, "ResumeShard", "", accountKey.IntID()+shardId, nil)
var resumeShard param.ResumeShard
if err = datastore.Get(*pC, resumeShardKey, &resumeShard); err != nil {
if err == datastore.ErrNoSuchEntity {
resumeShard = param.ResumeShard{}
resumeShard.Counter = 1
} else {
log.Println(err.Error())
}
} else {
resumeShard.Counter += 1
}
*pC
是指向来自 appengine 的上下文的指针。
accountKey
是每个用户独有的数据存储 Key
。
此错误随机出现,例如 10 次请求中出现 3 次。我想知道,因为我必须使用 datastore.NewKey(..)
为分片创建密钥,我怎样才能获得调用 Put(..)
后我将收到的完整密钥,因为这是分片,GAE 文档上的示例使用 datastore.NewKey(..)
还有。
请推荐。
您收到一条错误消息,指出您提供的密钥不完整。这是因为您指定了一个空键名 (""
) (stringID
),并且 accountKey.IntID()
加上一个随机数(来自范围 0..4
- 包括两者)作为数字密钥 ID (intID
)。请注意,如果您的 accountKey.IntID()
未初始化,它将是 0
并且随机数也可能是 0
在这种情况下, 0
用作 intID
.
并引用 datastore.Key
的文档:
Either one or both of
stringID
andintID
must be zero. If both are zero, the key returned is incomplete.
intID
获得 0
的几率是 5 分之 1,即 20%(这接近您报告的 10 分之 3)。
intID
的 0
值无效,它必须是非零值,因为 0
是一个特殊值,就像空字符串 ""
为stringID
,两者都用来表示,另一个属性用来标识实体;或者 - 如果两者都是零值 - 表示密钥是不完整的密钥(因此需要系统随机分配 intID
)。
请注意,此解决方案不好,因为您使用的密钥具有 相对 数字 ID (intID
),相对于帐户密钥的数字 ID (accountKey.IntID()
).系统分配的密钥将随机分配,但有可能 2 个帐户密钥可能彼此接近(例如,一个是另一个 +1)。在这种情况下,您的分片键会重叠!
如果使用datastore.Put()
保存实体,系统分配的随机键是Put()
的return值:
func Put(c context.Context, key *Key, src interface{}) (*Key, error)