尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

新农保为什么用MongoDB——一个省级社保系统的分片集群搭建实录

新农保为什么用MongoDB——一个省级社保系统的分片集群搭建实录 新农保为什么用MongoDB——一个省级社保系统的分片集群搭建实录这不是MongoDB入门教程。这是一个真实的新农保生产环境中4台服务器、2个分片、3个config server副本集的完整部署过程。每一行配置、每一个片键设计都是真实业务场景下的决策。文章目录新农保为什么用MongoDB——一个省级社保系统的分片集群搭建实录一、背景为什么新农保要用MongoDB二、集群规划4台服务器2个分片三、安装与配置3.1 安装3.2 目录规划3.3 mongos 配置3.4 config server 配置3.5 shard 配置四、副本集初始化4.1 Config Server 副本集4.2 Shard 副本集4.3 启动路由层五、分片配置——片键设计的决策5.1 添加分片5.2 启用分片库5.3 创建集合5.4 创建片键片键创建后不可修改5.5 创建索引六、启动与维护6.1 启动顺序6.2 关闭6.3 常用运维命令七、集群架构总结八、结语一、背景为什么新农保要用MongoDB新农保新型农村社会养老保险的数据有一个典型特征参保人数巨大、查询模式单一、写操作集中在建档期。一个省的新农保参保人数在百万到千万级别个人信息、缴费记录、待遇发放——三张大表扛不住高并发读写。传统做法是Oracle分库分表。但社保系统的数据库操作绝大部分是按个人编号aac001查询——翻页、导航、统计全部围绕这个字段。用Oracle分表分表键和查询键不一致会导致跨表join性能不升反降。MongoDB的方案用aac001做片键数据按个人编号均匀分布到两个shard上。同一个人包括它的子集如参保人以单位查询的所有数据在同一个shard上避免了跨节点查询。二、集群规划4台服务器2个分片架构图 客户端请求 │ ▼ mongos (路由) │ ├──→ config server 副本集 (3节点) │ 192.168.0.75:21000 │ 192.168.0.84:21000 │ 192.168.0.86:21000 │ ├──→ shard1 副本集 │ 192.168.0.75:27001 (主) │ 192.168.0.86:27001 (从仲裁) │ └──→ shard2 副本集 192.168.0.84:27002 (主) 192.168.0.86:27002 (从仲裁)3台config server保证集群元数据高可用。2个shard各带1主1从仲裁节点放在第三台服务器上——Shard1的仲裁在Shard2所在服务器Shard2的仲裁在Shard1所在服务器实现互备。三、安装与配置3.1 安装# 解压tar-xzvfmongodb-linux-x86_64-3.4.6.tgz-C/usr/local/mv/usr/local/mongodb-linux-x86_64-3.4.6 /usr/local/mongodb# 环境变量echoexport MONGODB_HOME/usr/local/mongodb/etc/profileechoexport PATH$MONGODB_HOME/bin:$PATH/etc/profilesource/etc/profile3.2 目录规划mkdir-p/usr/local/mongodb/confmkdir-p/usr/local/mongodb/mongos/logmkdir-p/usr/local/mongodb/config/datamkdir-p/usr/local/mongodb/config/logmkdir-p/usr/local/mongodb/shard1/datamkdir-p/usr/local/mongodb/shard1/logmkdir-p/usr/local/mongodb/shard2/datamkdir-p/usr/local/mongodb/shard2/log目录按角色分mongos路由、config配置、shard1/2数据。mos和config在所有3台服务器上创建shard按规划分布。3.3 mongos 配置# /usr/local/mongodb/conf/mongos.confpidfilepath/usr/local/mongodb/mongos/log/mongos.pid logpath/usr/local/mongodb/mongos/log/mongos.log logappendtruebind_ip0.0.0.0 port20000forktrue# 监听的配置服务器configdbconfigs/192.168.0.75:21000,192.168.0.84:21000,192.168.0.86:21000 maxConns20000核心是configdb——路由层通过它知道数据分布在哪里。3.4 config server 配置# /usr/local/mongodb/conf/config.confpidfilepath/usr/local/mongodb/config/log/configsrv.pid dbpath/usr/local/mongodb/config/data logpath/usr/local/mongodb/config/log/configsrv.log logappendtruebind_ip0.0.0.0 port21000forktrueconfigsvrtruereplSetconfigs maxConns20000configsvr true声明这个节点是集群的配置服务器。replSet configs指定副本集名称。3.5 shard 配置# /usr/local/mongodb/conf/shard1.conf (shard2.conf端口改为27002replSet改为shard2)pidfilepath/usr/local/mongodb/shard1/log/shard1.pid dbpath/usr/local/mongodb/shard1/data logpath/usr/local/mongodb/shard1/log/shard1.log logappendtruebind_ip0.0.0.0 port27001forktruehttpinterfacetrueresttruereplSetshard1 shardsvrtruemaxConns20000shardsvr true声明是数据分片节点。httpinterface true开启Web监控。四、副本集初始化4.1 Config Server 副本集# 启动所有config servermongod-f/usr/local/mongodb/conf/config.conf# 连接任意一台mongo--port21000# 初始化副本集config{_id:configs, members:[{_id:0, host:192.168.0.75:21000},{_id:1, host:192.168.0.84:21000},{_id:2, host:192.168.0.86:21000}]}rs.initiate(config)4.2 Shard 副本集# 启动shardmongod-f/usr/local/mongodb/conf/shard1.conf mongod-f/usr/local/mongodb/conf/shard2.conf# 连接shard1mongo--port27001# 初始化shard1副本集config{_id:shard1, members:[{_id:0, host:192.168.0.75:27001},{_id:1, host:192.168.0.86:27001},{_id:2, host:192.168.0.86:27001, arbiterOnly: true}]}rs.initiate(config)shard2同样操作。每个shard使用2个数据节点1个仲裁节点3台服务器刚好满配。4.3 启动路由层mongos-f/usr/local/mongodb/conf/mongos.conf mongo--port20000五、分片配置——片键设计的决策5.1 添加分片use admin sh.addShard(shard1/192.168.0.75:27001,192.168.0.86:27001)sh.addShard(shard2/192.168.0.84:27002,192.168.0.86:27002)5.2 启用分片库db.runCommand({enablesharding:xnb})5.3 创建集合use xnb db.createCollection(ac01)-- 个人信息 db.createCollection(ac02)-- 参保信息 db.createCollection(ac04)-- 缴费档次基数 db.createCollection(ac50)-- 待遇信息 db.createCollection(ac71)-- 发放记录 db.createCollection(ac93)-- 特殊身份 db.createCollection(ae03)-- 转移信息 db.createCollection(ic50)-- 缴费明细 db.createCollection(unit)-- 单位信息5.4 创建片键片键创建后不可修改use admin# 个人的业务——用aac001做片键db.runCommand({shardcollection:xnb.ac01, key:{aac001:1}})db.runCommand({shardcollection:xnb.ac02, key:{aac001:1}})db.runCommand({shardcollection:xnb.ac04, key:{aac001:1}})db.runCommand({shardcollection:xnb.ac50, key:{aac001:1}})db.runCommand({shardcollection:xnb.ac71, key:{aac001:1}})db.runCommand({shardcollection:xnb.ac93, key:{aac001:1}})db.runCommand({shardcollection:xnb.ae03, key:{aac001:1}})db.runCommand({shardcollection:xnb.ic50, key:{aac001:1}})# 单位维度的业务——用unit_id做片键db.runCommand({shardcollection:xnb.unit, key:{unit_id:1}})片键设计的核心逻辑社保的查询永远围绕这个人或这个单位进行。aac001个人编号和unit_id单位编号是天然的片键——同一个人/单位的所有数据落在同一个shard上查询不需要跨节点。5.5 创建索引use xnb# 个人维度的倒排索引支持分页和排序db.ac01.createIndex({aac001:-1})db.ac01.createIndex({aac002:-1})-- aac002是身份证号也需要倒排# 缴费明细按个人编号和批次号索引db.ic50.createIndex({aac001:-1})db.ic50.createIndex({aaz281:-1})# 单位维度——按父单位ID做树形导航db.unit.createIndex({parent_id:-1})注意片键aac001已经自动有索引。额外加的索引是为了身份证号查询aac002和树形单位导航parent_id。六、启动与维护6.1 启动顺序启动顺序必须是config server → shard → mongos。路由层必须等配置中心和分片就绪# 第一步config servermongod-f/usr/local/mongodb/conf/config.conf# 第二步shardmongod-f/usr/local/mongodb/conf/shard1.conf mongod-f/usr/local/mongodb/conf/shard2.conf# 第三步路由mongos-f/usr/local/mongodb/conf/mongos.conf6.2 关闭killallmongodkillallmongos生产环境不建议用killall——应该逐个优雅关闭。但开发/测试环境这个方式最直接。6.3 常用运维命令# 查看索引db.[collection].getIndexes()# 开启慢查询监控200ms以上记录db.setProfilingLevel(1,200)# 查看慢查询db.system.profile.find({millis:{$gt:200}})# 查看记录级别db.getProfilingLevel()# CRUDdb.ac01.find({aac001:10001})# 查询db.ac01.find({aac001:10001}).skip(20).limit(10)# 分页db.ac01.count({aaz031:1})# 统计db.ac01.insert({aac001:10001,aac003:张三})# 插入db.ac01.update({aac001:10001},{$set:{aac003:李四}})# 更新db.ac01.remove({aac001:10001})# 删除七、集群架构总结mongos路由层3节点 │ ┌─────────────┼─────────────┐ │ │ │ configsvr shard1 shard2 配置中心 数据分片1 数据分片2 3节点副本集 2数据1仲裁 2数据1仲裁组件端口数量作用mongos200003路由请求到对应shardconfig server210003存储集群元数据和分片映射shard12700121按aac001存储个人数据shard22700221按aac001存储个人数据八、结语MongoDB在新农保系统里的角色不是替代Oracle是承担Oracle不擅长的高并发接入层。参保人数据按aac001分片后99%的社保业务查询都能在单个shard上完成——这是分片设计最关键的一环。这个集群的实际物理规划、分片策略、片键选择、索引设计——都是在新农保真实业务场景下反复验证过的。不是MongoDB官方文档能告诉你的。片键一选定终身选错了没法改。新农保能从2018年跑到系统下线说明选对了。
返回列表