EOS 链mongo 节点数据分片shard key 选取
由于目前旧链还是基于链mongo同步节点存储数据,mongo服务使用的阿里云云数据库 MongoDB,单片存储已经接近最大存储值(2T),所以需要做分片扩容。
主要的注意点有
- 每个表 shard key的选择,以及如何设置
- 检查各片均衡同步是否正常
shard key选择
每个表shard key的选择要查看链源码mongo插件源码中的upsert(true)
所对应的update_one
的查询索引进行一致设置,否则会报错
codeName" : "ShardKeyNotFound", "errmsg" : "Failed to target upsert by query :: could not extract exact shard key"
upsert = true
, 是说使用update_one
代替insert_one
,这样方便去重,如果不存在则insert,存在则update。
对于mongo分片集合建立的索引要与各表upsert=true
时update_one
所需的查询索引一致。
对于upsert=true 各表索引如下
account_controls
- controlled_account
- controlled_permission
- controlling_account
accounts
- name
action_traces
无
block_states
- block_id
如果开启了mongodb-update-via-block-num
- block_num
blocks
- block_id
如果开启了mongodb-update-via-block-num
- block_num
pub_keys
- account
- public_key
- permission
transaction_traces
无
transactions
- trx_id
设置shard key
参考: https://helpcdn.aliyun.com/document_detail/99411.html
所在的数据库启用分片功能
sh.enableSharding("EOS")
transactions
db.transactions.createIndex({trx_id:1}) // 对片键的字段建立索引
sh.shardCollection("EOS.transactions",{"trx_id":1}) // 对集合设置数据分片。
trx_id 不存在添加shard key出错
"message" : "There are documents which have missing or incomplete shard key fields ({ : null }). Please ensure that all documents in the collection include all fields from the shard key.",
将没有trx_id
的记录删掉,此记录为无效数据
db.transactions.deleteMany({trx_id: {$exists: false}})
generic server error
由于空交易块,会不存在trx_id,导致upsert失败,所以将空块排除
config增加
mongodb-filter-out = eosio:onblock:
blocks
db.blocks.createIndex({block_id:1}) // 对片键的字段建立索引
sh.shardCollection("EOS.blocks",{"block_id":1}) // 对集合设置数据分片。
block_states
db.block_states.createIndex({block_id:1}) // 对片键的字段建立索引
sh.shardCollection("EOS.block_states",{"block_id":1}) // 对集合设置数据分片。
account_controls
db.account_controls.createIndex({controlled_account:1}) // 对片键的字段建立索引
db.account_controls.createIndex({controlled_permission:1}) // 对片键的字段建立索引
db.account_controls.createIndex({controlling_account:1}) // 对片键的字段建立索引
sh.shardCollection("EOS.account_controls",{"controlled_account":1}) // 对集合设置数据分片。
accounts
db.accounts.createIndex({name:1}) // 对片键的字段建立索引
sh.shardCollection("EOS.accounts",{"name":1}) // 对集合设置数据分片。
pub_keys
db.pub_keys.createIndex({account:1}) // 对片键的字段建立索引
db.pub_keys.createIndex({public_key:1}) // 对片键的字段建立索引
db.pub_keys.createIndex({permission:1}) // 对片键的字段建立索引
sh.shardCollection("EOS.pub_keys",{"account":1}) // 对集合设置数据分片。
sh.shardCollection("EOS.pub_keys",{"public_key":1}) // 对集合设置数据分片。
sh.shardCollection("EOS.pub_keys",{"permission":1}) // 对集合设置数据分片。
其他表
对于其他表,并没有用到upsert=true
,所以可以根据需要做处理
action_traces
db.action_traces.createIndex({trx_id:1}) // 对片键的字段建立索引
sh.shardCollection("EOS.action_traces",{"trx_id":1}) // 对集合设置数据分片。
transaction_traces
db.transaction_traces.createIndex({id:1}) // 对片键的字段建立索引
sh.shardCollection("EOS.transaction_traces",{"id":1}) // 对集合设置数据分片。
操作细节
买好阿里的云数据库 MongoDB,再附加买一个分片,此时查看db.stats()
能看到2个分片存储
{
"raw" : {
"mgset-40806644/..." : {
"db" : "EOS",
...
"ok" : 1.0
},
"mgset-40806643/..." : {
"db" : "EOS",
...
"ok" : 1.0
}
},
"objects" : 767319,
...
}
配置好同步节点,先往数据库推送链数据
此时看到,只有mgset-40806643
在增加数据,因为我们还没有让数据库做分片处理
设置分片
细节就是执行上面的设置shard key
每增加一个shardCollection
,发现"mgset-40806644
中的collections
会对应的增加(需要数量到一定级别(2个chunk以上,1个chunk默认是64MB,sh.status()查看chunk数量)才会做均衡,第一次均衡后新加的分片才会创建对应的集合)
添加shardCollection
后,对应集合的索引会自动同步过去
查看对应表的stats
,比如db.action_traces.stats()
,能看到sharded = true
注意
对于上面的操作,大部分索引已经默认添加,无需重复操作,但是对于用到upsert=true
的表shardCollection
必须与插件一致,否则报ShardKeyNotFound
参考
https://docs.mongodb.com/manual/core/sharding-shard-key/?spm=a2c4g.11186623.2.25.544e1d8d2ORfYO#choosing-a-shard-key
https://help.aliyun.com/document_detail/100658.html?spm=a2c4g.11186623.6.762.5b3155f12yRKuU
https://helpcdn.aliyun.com/document_detail/99411.html