由于目前旧链还是基于链mongo同步节点存储数据,mongo服务使用的阿里云云数据库 MongoDB,单片存储已经接近最大存储值(2T),所以需要做分片扩容。
主要的注意点有

  1. 每个表 shard key的选择,以及如何设置
  2. 检查各片均衡同步是否正常

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=trueupdate_one所需的查询索引一致。

对于upsert=true 各表索引如下

account_controls
  1. controlled_account
  2. controlled_permission
  3. controlling_account
accounts
  1. name
action_traces

block_states
  1. block_id

如果开启了mongodb-update-via-block-num

  1. block_num
blocks
  1. block_id

如果开启了mongodb-update-via-block-num

  1. block_num
pub_keys
  1. account
  2. public_key
  3. permission
transaction_traces

transactions
  1. 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