Mongdb分片实战二(分片逻辑)

数据存储优化:Kafka+MongoDB分片,爬虫异步写入速度达3000条/秒 本文通过Kafka+MongoDB分片的架构,实现了爬虫数据的异步写入,将写入速度提升至3000条/秒以上。解耦:Kafka作为消息队列,将爬虫的生产与存储的消费解耦,避免同步阻塞;并行:Kafka的分区机制和MongoDB的分片机制,实现了数据的并行生产、消费和写入;批量:批量发送、批量消费、批量插入,减少IO次数,提升整体性能。 阅读详情

分片逻辑图

上节搭建的分片集群从逻辑上看如下图所示:

 

片:可以普通的mongod进程,也可以是副本集。但是即使一片内有多台服务器,也只能有一个主服务器,其他的服务器保存相同的数据。

mongos路由进程:它路由所有请求,然后将结果聚合。它不保存存储数据或配置信息。

配置服务器:存储集群的配置信息。

整个分布式的集群通过mongos对客户端提供了一个透明统一的接口,客户端不需要关系具体的分片细节,所有分片的动作都是自动执行的,那是如何做到透明和自动的。

切分数据

上节中建立好集群后,默认的是不会将存储的每条数据进行分片处理,需要在数据库和集合的粒度上都开启分片功能。开启test库的分片功能:

1.    ./bin/mongo –port 20000
2.    mongos> use admin 
3.    switched to db admin
4.    mongos> db.runCommand({"enablesharding":"test"})
5.    { "ok" : 1 }

开启user集合分片功能:

1.    mongos> db.runCommand({"shardcollection":"test.user","key":{"_id":1}})
2.    { "collectionsharded" : "test.user", "ok" : 1 }

注意:需要切换到admin库执行命令。

片键:上面的key就是所谓的片键(shard key)。MongoDB不允许插入没有片键的文档。但是允许不同文档的片键类型不一样,MongoDB内部对不同类型有一个排序:

片键的选择至关重要,后面会进行详细的说明。

这时再切换到config库如下查看:

复制代码
1.    mongos> use config
2.    mongos> db.databases.find()
3.    { "_id" : "admin", "partitioned" : false, "primary" : "config" }
4.    { "_id" : "OSSP10", "partitioned" : false, "primary" : "shard0000" }
5.    { "_id" : "test", "partitioned" : true, "primary" : "shard0000" }
6.    { "_id" : "test2", "partitioned" : false, "primary" : "shard0000" }
7.    { "_id" : "test3", "partitioned" : false, "primary" : "shard0001" }
8.    mongos> db.chunks.find()
9.    { "_id" : "test.user-_id_MinKey", "lastmod" : { "t" : 1, "i" : 0 }, "lastmodEpoch" : ObjectId("515a3797d249863e35f0e3fe"), "ns" : "test.user", "min" : { "_id" : { "$minKey" : 1 } }, "max" : { "_id" : { "$maxKey" : 1 } }, "shard" : "shard0000" }
复制代码

Chunks:理解MongoDB分片机制的关键是理解Chunks。mongodb不是一个分片上存储一个区间,而是每个分片包含多个区间,这每个区间就是一个块。

1.    mongos> use config
2.    mongos> db.settings.find()
3.    { "_id" : "chunksize", "value" : 64 }
4.    ……

平衡:如果存在多个可用的分片,只要块的数量足够多,MongoDB就会把数据迁移到其他分片上,这个迁移的过程叫做平衡。Chunks默认的大小是64M200M,查看config.settings可以看到这个值:

只有当一个块的大小超过了64M200M,MongoDB才会对块进行分割(但根据我的实践2.4版本块分割的算法好像并不是等到超过chunkSize大小就分割,也不是一分为二,有待继续学习),并当最大分片上的块数量超过另一个最少分片上块数量达到一定阈值会发生所谓的chunk migration来实现各个分片的平衡 (如果启动了balancer进程的话)。这个阈值随着块的数量不同而不同:

 

这带来一个问题是我们测开发测试的时候,往往希望通过观察数据在迁移来证明分片是否成功,但64M200M显然过大,解决方法是我们可以在启动mongos的时候用—chunkSize来制定块的大小,单位是MB。

1.    ./bin/mongos --port 20000 --configdb 192.168.32.13:10000 --logpath log/mongos.log  --fork --chunkSize 1

我指定1MB的块大小重新启动了一下mongos进程。

或者向下面这要修改chunkSize大小:

1.    mongos> use config
2.    mongos> db.settings.save( { _id:"chunksize", value: 1 } )

 2.4版本之前MongoDB基于范围进行分片的(2.2.4会介绍基于哈希的分片),对一个集合分片时,一开始只会创建一个块,这个块的区间是(-∞,+∞),-∞表示MongoDB中的最小值,也就是上面db.chunks.find()我们看到的$minKey,+∞表示最大值即$maxKey。Chunck的分割是自动执行的,类似于细胞分裂,从区间的中间分割成两个。

分片测试

 现在对上面我们搭建的MongoDB分片集群做一个简单的测试。目前我们的集群情况如下(为了方面展示我采用了可视化的工具MongoVUE):

像上面提到那样为了尽快能观察到测试的效果,我么启动mongos时指定的chunkSize为1MB。

我们对OSSP10库和bizuser集合以Uid字段进行分片:

1.    mongos> use admin
2.    switched to db admin
3.    mongos> db.runCommand({"enablesharding":"OSSP10"})
4.    { "ok" : 1 }
5.    mongos> db.runCommand({"shardcollection":"OSSP10.bizuser","key":{"Uid":1}})
6.    { "collectionsharded" : "OSSP10.bizuser", "ok" : 1 }

在插入数据之前查看一下config.chunks,通过查看这个集合我们可以了解数据是怎么切分到集群的:

1.    mongos> db.chunks.find()
2.    { "_id" : "OSSP10.bizuser-Uid_MinKey", "lastmod" : { "t" : 1, "i" : 0 }, "lastmodEpoch" : ObjectId("515a8f1dc1de43249d8ce83e"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : { "$minKey" : 1 } }, "max" : { "Uid" : { "$maxKey" : 1 } }, "shard" : "shard0000" }

开始只有一个块,区间(-∞,+∞)在shard0000(192.168.32.13:27019)上,下面我们循环的插入100000条数据:

1.    mongos> use OSSP10
2.    switched to db OSSP10
3.    mongos> for(i=0;i<100000;i++){ db.bizuser.insert({"Uid":i,"Name":"zhanjindong","Age":13,"Date":new Date()}); }

完成后我们在观察一下config.chunks的情况:

复制代码
1.    mongos> db.chunks.find()
2.    { "_id" : "OSSP10.bizuser-Uid_MinKey", "lastmod" : { "t" : 3, "i" : 0 }, "lastmodEpoch" : ObjectId("515a8f1dc1de43249d8ce83e"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : { "$minKey" : 1 } }, "max" : { "Uid" : 0 }, "shard" : "shard0002" }
3.    { "_id" : "OSSP10.bizuser-Uid_0.0", "lastmod" : { "t" : 3, "i" : 1 }, "lastmodEpoch" : ObjectId("515a8f1dc1de43249d8ce83e"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : 0 }, "max" : { "Uid" : 6747 }, "shard" : "shard0000" }
4.    { "_id" : "OSSP10.bizuser-Uid_6747.0", "lastmod" : { "t" : 2, "i" : 0 }, "lastmodEpoch" : ObjectId("515a8f1dc1de43249d8ce83e"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : 6747 }, "max" : { "Uid" : { "$maxKey" : 1 } }, "shard" : "shard0001" }
复制代码

我们可以看见刚开始的块分裂成了三块分别是(-∞,0)在shard0002上,[0,6747)在shard0000上和[6747,+ ∞)在shard0001上。

说明:这里需要说明的是MongoDB中的区间是左闭右开的。这样说上面第一个块不包含任何数据,至于为什么还不清楚,有待继续调研。

我们持续上面的插入操作(uid从0到100000)我们发现块也在不停的分裂:

复制代码
1.    mongos> db.chunks.find()
2.    { "_id" : "OSSP10.bizuser-Uid_MinKey", "lastmod" : { "t" : 3, "i" : 0 }, "lastmodEpoch" : ObjectId("515a8f1dc1de43249d8ce83e"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : { "$minKey" : 1 } }, "max" : { "Uid" : 0 }, "shard" : "shard0002" }
3.    { "_id" : "OSSP10.bizuser-Uid_0.0", "lastmod" : { "t" : 3, "i" : 1 }, "lastmodEpoch" : ObjectId("515a8f1dc1de43249d8ce83e"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : 0 }, "max" : { "Uid" : 6747 }, "shard" : "shard0000" }
4.    { "_id" : "OSSP10.bizuser-Uid_6747.0", "lastmod" : { "t" : 3, "i" : 4 }, "lastmodEpoch" : ObjectId("515a8f1dc1de43249d8ce83e"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : 6747 }, "max" : { "Uid" : 45762 }, "shard" : "shard0001" }
5.    { "_id" : "OSSP10.bizuser-Uid_99999.0", "lastmod" : { "t" : 3, "i" : 3 }, "lastmodEpoch" : ObjectId("515a8f1dc1de43249d8ce83e"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : 99999 }, "max" : { "Uid" : { "$maxKey" : 1 } }, "shard" : "shard0001" }
6.    { "_id" : "OSSP10.bizuser-Uid_45762.0", "lastmod" : { "t" : 3, "i" : 5 }, "lastmodEpoch" : ObjectId("515a8f1dc1de43249d8ce83e"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : 45762 }, "max" : { "Uid" : 99999 }, "shard" : "shard0001" }
复制代码

分片的规则正是上面提到的块的自动分裂和平衡,可以发现不同的块是分布在不同的分片上。

注意:这里使用Uid作为片键通常是有问题的,2.3对递增片键有详细说明。

Note:通过sh.status()可以很直观的查看当前整个集群的分片情况,类似如下:

对已有数据进行分片

面的演示都是从零开始构建分片集群,但是实际中架构是一个演进的过程,一开始都不会进行分片,只有当数据量增长到一定程序才会考虑分片,那么对已有的海量数据如何处理。我们在上节的基础上继续探索。《深入学习MongoDB》中有如下描述:

我们现在来尝试下(也许我使用的最新版本会有所有变化),先在192.168.71.43:27179上再启一个mongod进程:

1.    numactl --interleave=all ./bin/mongod --dbpath data/shard3/ --logpath log/shard3.log  --fork --port 27019

现在我们像这个mongod进程中的OSSP10库的bizuser集合中插入一些数据:

1.    for(i=0;i<10;i++){ db.bizuser.insert({"Uid":i,"Name":"zhanjindong2","Age":13,"Date":new Date()}); }

我们这个时候尝试将这个mongod加入到之前的集群中去:

1.    mongos> db.runCommand({addshard:"192.168.71.43:27019" })
2.    {
3.            "ok" : 0,
4.            "errmsg" : "can't add shard 192.168.71.43:27019 because a local database 'OSSP10' exists in another shard0000:192.168.32.13:27019"
5.    }

果然最新版本依旧不行。我们删除OSSP10库,新建个OSSP20库再添加分片则可以成功。

1.    { "shardAdded" : "shard0003", "ok" : 1 }

那么看来我们只能在之前已有的数据的mongod进程基础上搭建分片集群,那么这个时候添加切片,MongoDB对之前的数据又是如何处理的呢?我们现在集群中移除上面添加的切片192.168.71.43:27019,然后在删除集群中的OSSP10库。

这次我们尽量模拟生产环境进行测试,重新启动mongos并不指定chunksize,使用默认的最优的大小(64M200M)。然后在192.168.71.43:27019中新建OSSP10库并向集合bizuser中插入100W条数据:

1.    for(i=0;i<1000000;i++){ db.bizuser.insert({"Uid":i,"Name":"zhanjindong2","Age":13,"Date":new Date()}); }

然后将此节点添加到集群中,并仍然使用递增的Uid作为片键对OSSP10.bizuser进行分片:

1.    mongos> use admin
2.    switched to db admin
3.    mongos> db.runCommand({"enablesharding":"OSSP10"})
4.    { "ok" : 1 }
5.    mongos> db.runCommand({"shardcollection":"OSSP10.bizuser","key":{"Uid":1}})
6.    { "collectionsharded" : "OSSP10.bizuser", "ok" : 1 }

观察一下config.chunks可以看见对新添加的切片数据进行切分并进行了平衡(每个分片上一个块),基本是对Uid(0~1000000)进行了四等分,当然没那精确:

复制代码
1.    mongos> use config
2.    switched to db config
3.    mongos> db.chunks.find()
4.    { "_id" : "OSSP10.bizuser-Uid_MinKey", "lastmod" : { "t" : 2, "i" : 0 }, "lastmodEpoch" : ObjectId("515b8f3754fde3fbab130f92"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : { "$minKey" : 1 } }, "max" : { "Uid" : 0 }, "shard" : "shard0000" }
5.    { "_id" : "OSSP10.bizuser-Uid_381300.0", "lastmod" : { "t" : 4, "i" : 1 }, "lastmodEpoch" : ObjectId("515b8f3754fde3fbab130f92"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : 381300 }, "max" : { "Uid" : 762601 }, "shard" : "shard0003" }
6.    { "_id" : "OSSP10.bizuser-Uid_762601.0", "lastmod" : { "t" : 1, "i" : 2 }, "lastmodEpoch" : ObjectId("515b8f3754fde3fbab130f92"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : 762601 }, "max" : { "Uid" : { "$maxKey" : 1 } }, "shard" : "shard0003" }
7.    { "_id" : "OSSP10.bizuser-Uid_0.0", "lastmod" : { "t" : 3, "i" : 0 }, "lastmodEpoch" : ObjectId("515b8f3754fde3fbab130f92"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : 0 }, "max" : { "Uid" : 250000 }, "shard" : "shard0001" }
8.    { "_id" : "OSSP10.bizuser-Uid_250000.0", "lastmod" : { "t" : 4, "i" : 0 }, "lastmodEpoch" : ObjectId("515b8f3754fde3fbab130f92"), "ns" : "OSSP10.bizuser", "min" : { "Uid" : 250000 }, "max" : { "Uid" : 381300 }, "shard" : "shard0002" }
复制代码

MongoDB这种自动分片和平衡的能力使得在迁移老数据的时候变得非常简单,但是如果数据特别大话则可能会非常的慢。

Hashed Sharding

MongoDB2.4以上的版本支持基于哈希的分片,我们在上面的基础上继续探索。

交代一下因为环境变动这部分示例操作不是在之前的那个集群上,但是系统环境都是一样,逻辑架构也一样,只是ip地址不一样(只搭建在一台虚拟机上),后面环境有改动不再说明:

配置服务器:192.168.129.132:10000

路由服务器:192.168.129.132:20000

分片1:192.168.129.132:27017

分片2:192.168.129.132:27018

……其他分片端口依次递增。

我们重建之前的OSSP10库,我们仍然使用OSSP10.bizuser不过这次启动哈希分片,选择_id作为片键:

1.    mongos> use admin
2.    switched to db admin
3.    mongos> db.runCommand({"enablesharding":"OSSP10"})
4.    { "ok" : 1 }
5.    mongos> db.runCommand({"shardcollection":"OSSP10.bizuser","key":{"_id":"hashed"}})
6.    { "collectionsharded" : "OSSP10.bizuser", "ok" : 1 }

我们现在查看一下config.chunks

复制代码
1.    mongos> use config
2.    switched to db config
3.    mongos> db.chunks.find()
4.    { "_id" : "OSSP10.bizuser-_id_MinKey", "lastmod" : { "t" : 2, "i" : 2 }, "lastmodEpoch" : ObjectId("515e47ab56e0b3341b76f145"), "ns" : "OSSP10.bizuser", "min" : { "_id" : { "$minKey" : 1 } }, "max" : { "_id" : NumberLong("-4611686018427387902") }, "shard" : "shard0000" }
5.    { "_id" : "OSSP10.bizuser-_id_-4611686018427387902", "lastmod" : { "t" : 2, "i" : 3 }, "lastmodEpoch" : ObjectId("515e47ab56e0b3341b76f145"), "ns" : "OSSP10.bizuser", "min" : { "_id" : NumberLong("-4611686018427387902") }, "max" : { "_id" : NumberLong(0) }, "shard" : "shard0000" }
6.    { "_id" : "OSSP10.bizuser-_id_0", "lastmod" : { "t" : 2, "i" : 4 }, "lastmodEpoch" : ObjectId("515e47ab56e0b3341b76f145"), "ns" : "OSSP10.bizuser", "min" : { "_id" : NumberLong(0) }, "max" : { "_id" : NumberLong("4611686018427387902") }, "shard" : "shard0001" }
7.    { "_id" : "OSSP10.bizuser-_id_4611686018427387902", "lastmod" : { "t" : 2, "i" : 5 }, "lastmodEpoch" : ObjectId("515e47ab56e0b3341b76f145"), "ns" : "OSSP10.bizuser", "min" : { "_id" : NumberLong("4611686018427387902") }, "max" : { "_id" : { "$maxKey" : 1 } }, "shard" : "shard0001" }
复制代码

MongoDB的哈希分片使用了哈希索引:

哈希分片仍然是基于范围的,只是将提供的片键散列成一个非常大的长整型作为最终的片键。官方文中描述如下:

不像普通的基于范围的分片,哈希分片的片键只能使用一个字段。

 

选择哈希片键最大的好处就是保证数据在各个节点分布基本均匀,下面使用_id作为哈希片键做个简单的测试:

1.    mongos> db.runCommand({"enablesharding":"mydb"})
2.    db.runCommand({"shardcollection":"mydb.mycollection","key":{"_id":"hashed"}})
3.    mongos> use mydb
4.    mongos> for(i=0;i<333333;i++){ db.mycollection.insert({"Uid":i,"Name":"zhanjindong2","Age":13,"Date":new Date()}); }

 

通过MongoVUE观察三个切片上的数据量非常均匀:

上面是使用官方文档中推荐的Objectid作为片键,情况很理想。如果使用一个自增长的Uid作为片键呢:

1.    db.runCommand({"shardcollection":"mydb.mycollection","key":{"Uid":"hashed"}})
2.    for(i=0;i<333333;i++){ db.mycollection.insert({"Uid":i,"Name":"zhanjindong2","Age":13,"Date":new Date()}); }

故障恢复

先不考虑集群中每个分片是副本集复杂的情况,只考虑了每个分片只有一个mongod进程,这种配是只是不够健壮还是非常脆弱。我们在testdb.testcollection上启动分片,然后向其中插入一定量的数据(视你的chunkSize而定),通过观察config.chunks确保testdb.testcollection上的数据被分布在了不同的分片上。

复制代码
1.    mongos> db.runCommand({"enablesharding":"testdb"})
2.    mongos> db.runCommand({"shardcollection":"testdb.testcollection","key":{"Uid":1}})
3.    use testdb
4.    for(i=0;i<1000000;i++){ db.testcollection.insert({"Uid":i,"Name":"zhanjindong","Age":13,"Date":new Date()}); }
5.    mongos> use config
6.    switched to db config
7.    mongos> db.chunks.find()
8.    ……
9.    { "_id" : "testdb.testcollection-Uid_747137.0", "lastmod" : { "t" : 4, "i" : 1 }, "lastmodEpoch" : ObjectId("515fc5f0365c860f0bf8e0cb"), "ns" : "testdb.testcollection", "min" : { "Uid" : 747137 }, "max" : { "Uid" : 962850 }, "shard" : "shard0000" }
10.    ……
11.    { "_id" : "testdb.testcollection-Uid_0.0", "lastmod" : { "t" : 1, "i" : 3 }, "lastmodEpoch" : ObjectId("515fc5f0365c860f0bf8e0cb"), "ns" : "testdb.testcollection", "min" : { "Uid" : 0 }, "max" : { "Uid" : 6757 }, "shard" : "shard0001" }
12.    ……
13.    { "_id" : "testdb.testcollection-Uid_531424.0", "lastmod" : { "t" : 2, "i" : 4 }, "lastmodEpoch" : ObjectId("515fc5f0365c860f0bf8e0cb"), "ns" : "testdb.testcollection", "min" : { "Uid" : 531424 }, "max" : { "Uid" : 747137 }, "shard" : "shard0002" }
复制代码

这时我们强制杀掉shard2进程:

1.    [root@localhost mongodb-2.4.1]# ps -ef |grep mongo
2.    root      6329     1  0 22:52 ?        00:00:08 ./bin/mongod --dbpath data/shard3/ --logpath log/shard3.log --fork --port 27019
3.    kill -9 6329

我们尝试用属于不同范围的Uid对testdb.testcollection进行写入操作(这里插入一条记录应该不会导致新的块迁移):

复制代码
1.    [root@localhost mongodb-2.4.1]# ps -ef |grep mongo
2.    use testdb
3.    switched to db testdb
4.    ####写
5.    mongos> db.testcollection.insert({"Uid":747138,"Name":"zhanjindong","Age":13,"Date":new Date()})
6.    ##向shard0000插入没有问题
7.    mongos> db.testcollection.insert({"Uid":6756,"Name":"zhanjindong","Age":13,"Date":new Date()})
8.    ##向shard0001插入没有问题
9.    mongos> db.testcollection.insert({"Uid":531425,"Name":"zhanjindong","Age":13,"Date":new Date()})
10.    socket exception [CONNECT_ERROR] for 192.168.129.132:27019
11.    ##向shard0002插入出问题
12.    ####读
13.    mongos> db.testcollection.find({Uid:747139})
14.    ##从shard0000读取没有问题
15.    mongos> db.testcollection.find({Uid: 2})
16.    ##从shard0001读取没有问题
17.    mongos> db.testcollection.find({Uid: 531426})
18.    error: {
19.        "$err" : "socket exception [SEND_ERROR] for 192.168.129.132:27019",
20.        "code" : 9001,
21.        "shard" : "shard0002"
22.    }
23.    ##从shard0002读取有问题
24.    b.testcollection.count()
25.    Sat Apr  6 00:23:19.246 JavaScript execution failed: count failed: {
26.        "code" : 11002,
27.        "ok" : 0,
28.        "errmsg" : "exception: socket exception [CONNECT_ERROR] for 192.168.129.132:27019"
29.    } at src/mongo/shell/query.js:L180
复制代码

可以看到插入操作涉及到分片shard0002的操作都无法完成。这是顺理成章的。

下面我们重新启动shard3看集群是否能自动恢复正常操作:

复制代码
1.    ./bin/mongod --dbpath data/shard3/ --logpath log/shard3.log --fork --port 27019
2.    mongos> use config
3.    switched to db config
4.    mongos> db.shards.find()
5.    { "_id" : "shard0000", "host" : "192.168.129.132:27017" }
6.    { "_id" : "shard0001", "host" : "192.168.129.132:27018" }
7.    { "_id" : "shard0002", "host" : "192.168.129.132:27019" }
复制代码

重复上面的插入和读取shard0002的操作:

1.    mongos> db.testcollection.insert({"Uid":531425,"Name":"zhanjindong","Age":13,"Date":new Date()})
2.    ##没有问题
3.    db.testcollection.find({Uid: 531426})
4.    { "_id" : ObjectId("515fc791b86c543aa1d7613e"), "Uid" : 531426, "Name" : "zhanjindong", "Age" : 13, "Date" : ISODate("2013-04-06T06:58:25.516Z") }
5.    ##没有问题

总结:当集群中某个分片宕掉以后,只要不涉及到该节点的操纵仍然能进行。当宕掉的节点重启后,集群能自动从故障中恢复过来。

这一节在前一节搭建的集群基础上做了一些简单的测试,下一节的重点是性能和优化相关。


基于STM32设计的遥控小车(手机APP+GPS+温湿度+ESP8266) 一、环境介绍 小车主控MCU: STM32F103ZET6 STM32程序开发IDE: keil5 STM32程序风格: 采用寄存器方式开发,注释齐全,执行效率高,方便移植 手机APP: 采用QT设计,程序支持跨平台编译运行(Android、IOS、Windows、Linux都可以编译运行,对应平台上QT的环境搭建,之前博客已经发了文章讲解) 硬件包含: 淘宝购买的完整一套4轮遥控小车(采用STM32F103ZET6作为主控板)、DHT11温湿度传感器、中科微GPS模块、ESP8266 ... 阅读详情

相关推荐

C#与Lua交互原理

以前每一次研究一些新知识并且有所收获的时候,都想写一篇博客来分享这种自己的收获。 一直没有写主要是因为自己水平太菜了,怕写出来贻笑大方,最近想通了,想写就写下来,就算对别人毫无用处,还可以自己没事翻翻,省得自己都忘了。当然如果能对你有一丝丝的帮助,那真是再好不过了 。本文将针对C#与Lua的调用原理阐述一些个人的心得 。 Lua开发环境搭建 有关于VS &amp...

Hui Ye的博客 1万+

mongodb分片集群搭建踩坑记录

b. 将升序键的当前值一直到正无穷范围的块都指定分布在SSD分片上:sh.addTagRange("dbName.collName",{"_id":ObjectId()},...{"_id":MaxKey},"ssd")创建步骤: db.users.ensureIndex({"username":"hashed"}) , sh.shardCollection("app.users",{"username":"hashed"})如需查看所有的块,可使用sh.status(true)命令。

lipengyao2010的专栏 1688

T100批处理作业开发

g_bgjob = ‘Y’ 后台执行g_bgjob = ‘N’ 前台执行。

weixin_43400895的博客 585

MongoDB分片实战(二):Sharding

分片逻辑图 上节搭建的分片集群从逻辑上看如下图所示:   片:可以普通的mongod进程,也可以是副本集。但是即使一片内有多台服务器,也只能有一个主服务器,其他的服务器保存相同的数据。 mongos路由进程:它路由所有请求,然后将结果聚合。它不保存存储数据或配置信息。 配置服务器:存储集群的配置信息。 整个分布式的集群通过mongos对客户端提供了一个透明统一的接口,客户端不需要关...

weixin_33852020的博客 262

weblogic等保测评操作过程

weblogic网络安全等级测评保护操作

qq_48257021的博客 2757

【AI面试】2026 AI Agent 应用开发|应届生简历模板 + 完整学习路线图(校招可直接复用)

很多同学学完 RAG、Agent 之后,不知道简历怎么写,项目写成 “调用大模型 API 实现聊天机器人”,投出去几乎没有面试。AI Agent 应用开发,本质还是软件开发岗位。简历要突出工程能力、踩坑优化、问题解决,不要只堆砌 AI 关键词。注意:本文针对【AI 应用开发 / Agent 应用工程师】本科校招;不适合大模型训练、微调算法岗。AI Agent 应用开发岗位,不是只会写提示词、调用 API 就可以拿到 offer。拥有传统软件工程基本功,同时懂大模型、RAG、Agent 工程落地的开发者。

十年老程序猿,AI 疯狂研究专家,前沿硬核知识分享 299

MongoDB分片(sharding)/分区(partitioning)介绍

分片是指将数据拆分,将其分散存放在不同的机器上的过程。有时也用分区(partitioning)来表示这个概念。   几乎所有数据库软件都能进行手动分片(manual sharding)。应用需要维护与若干不同数据库服务器的连接,每个连接还是完全独立的。应用程序管理不同服务器上不同数据的存储,还管理在合适的数据库上查询数据的工作。   Mongodb支持自动分片(autosharding),可以

杨春建的博客 2万+

基于MATLAB的特征模式分解(FMD)算法详解

本文详细介绍了基于MATLAB的特征模式分解(FMD)算法实现。FMD是一种新型自适应信号分解方法,通过自适应FIR滤波器组和相关峭度优化目标,有效解决传统方法(如EMD、VMD)的模态混叠问题。文章系统阐述了FMD的算法原理、数学模型和实现步骤,包括自适应FIR滤波器设计、相关峭度优化和模态选择机制。与现有方法相比,FMD在旋转机械故障诊断中展现出更强的特征提取能力和噪声鲁棒性。MATLAB实现部分包含核心函数、参数优化和可视化工具,并通过轴承故障等案例验证了算法的有效性。

qq_42212808的博客 192

mongo分片

1.搭建mongo分片式集群主要是用来处理用户行驶的gps数据信息。gps集合的字段有member_id,order_id,longitude,latitude,reporttime这5个数据字段。搭建方式:https://jeremyxu2010.github.io/2018/10/mongodb高可用集群部署/#启用用户认证登录,可以参考mongo中文社区和官方文档。 2.片键及片键选择 ...

xzx1232010的博客 519

11-16 Fluent结果查看及后处理功能(做动画、监控点)

监控点、面及动画操作

zheaa的博客 1万+

pycharm一直选择不了conda正确路径弹框报错:latinit property envs_dirs has not been initialized...如何解决?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 2911

分库分表-常见的分片规则(逻辑图+配置信息)

最常用的九种分片规则:逻辑图+配置信息

彬的博客 344

从0到1带大家搭建spring cloud alibaba 微服务大型应用框架(十一)spring-boot-admin 监控篇(2)springcloud 集成spring boot admin

从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(十一)spring-boot-admin 监控篇(2)springcloud 集成spring boot admin spring-boot-admin 服务端创建与集成入nacos spring-boot-admin 查看日志

峡谷电光马仔的博客 1378

Mongdb分片集群教程

分片(Sharding)技术是开发人员用来提高数据存储和数据读写吞吐量常用的技术之一。简单的来说,分片主要是将数据进行划分后,将它们分别存放于不同机器上的过程。通过使用分片可以实现降低单个机器的压力和处理更大的数据负载功能。分片与副本集主要区别在于,分片是每个节点存储数据的不同片段,而副本集是每个节点存储数据的相同副本。所有数据库都可以进行手动分片(ManualSharding),因此,分片并不是MongoDB特有的。

2302_80467554的博客 1205

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

mongodb分片集群

一、mongodb分片集群 Mongodb sharding cluster:分布式mongodb集群:将海量数据水平扩展,数据分表存储在sharding的各个节点 mongodb的数据分块称为chunk。每个chunk都是collection中一段连续的数据记录,通常最大尺寸是200MB,超过则生成新的数据块 1.1 分片角色类型: 1)shard server:存储实际数据的分片。每个shard可以是一个mongod实例,也可以一个replica set。为了实现每个分片内存的自动故障转移,

归来仍少年 1425

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

猿创征文|MongoDB数据库 分片集群搭建部署实战

MongoDB数据库、分片集群搭建教程;使用mtools搭建MongoDB复制集和分片集群,其包括MongoDB日志分析、报表生成及简易的数据库安装等功能。

yaya_jn的博客 2285

mongDB

MongoDB是一个文档型数据库,数据以类似JSON的文档形式存储。MongoDB的设计理念是为了应对大数据量、高性能和灵活性需求MongoDB使用集合(Collections)来组织文档(Documents),每每个文档都是由键值对组成的。数据库(Database):存储数据的容器,类似于关系型数据库中的数据库。集合(Collection):数据库中的一个集合,类似于关系型数据库中的表文档(Document):集合中的一个数据记录,类似于关系型数据库中的行(row。

2401_84100398的博客 895

Mongodb分片实践

Mongodb分片实践 分片简介: 分片(sharding)是指将数据拆分,将其分散存在不同的机器上的过程。将数据分散到不同的机器上,不需要功能强大的大型计算机就可以存储更多的数据,处理更大的负载。 手动分片:几乎所有的数据库软件都能进行手动分片。应用需要维护与不同数据库服务器的链接,管理不同服务器上的数据,存储、查询都在不同服务器上进行。这种方法可以很好地工作,但是不易维护,从集群中增

ctf_htj的专栏 1565

MongoDB分布式存储之分片技术

在mongodb里面存在另一种集群,就是分片技术,跟sql server的表分区类似,我们知道当数据量达到T级别的时候,我们的磁盘,内存 就吃不消了,针对这样的场景我们该如何应对。   一:分片      mongodb采用将集合进行拆分,然后将拆分的数据均摊到几个片上的一种解决方案。   下面我对这张图解释一下:      人脸:       代

PHPer的技术记录 2382

mongoDB之分片集群

摘要:本文探讨了MongoDB分片集群在直播平台高并发场景下的应用。针对MySQL分表存在的数据分布不均、扩容繁琐等问题,分析了MongoDB分片集群的三大优势:灵活的数据模型、JSON格式存储和自动水平扩展能力。详细阐述了分片集群的架构组成、三种数据分布策略(范围、哈希、地域)以及自动均衡机制。结合直播打赏和订单系统等业务场景,提出了分片集群的适用条件和片键选择原则。最后强调分片集群虽能解决性能瓶颈,但管理复杂成本高,建议谨慎评估使用。

476

手撸架构,MongDB 面试50问

什么是RDBMS? 关系数据库管理系统(Relational Database Management System:RDBMS)是指包括相互联系的逻辑组织和存取这些数据的一套程序 (数据库管理系统软件)。关系数据库管理系统就是管理关系数据库,并将数据逻辑组织的系统。 高度组织化结构化数据 结构化查询语言(SQL) (SQL) 数据和关系都存储在单独的表中。 数据操纵语言,数据定义语言 严格的一致性 基础事务 什么是NoSQL? NoSQL,指的是非关系型的数据库。NoSQL有时也称作..

vincent 1119

MongoDB 高可用与海量数据实战:从副本集、分片到事务全解析

保障高可用、实现水平扩展、确保数据一致性。本文将由浅入深,从架构原理到开发实践,带你掌握这些技术的核心逻辑与落地要点。

佑瞻的博客 912

mongdb和mysql 区别和场景

在写一个新需求时,往往要进行创表,或者创建文档,这个时候就需要进行一个选型,怎么进行一个选型呢,下面就是mongdb和mysql的一些区别和我的心得。

m0_51468272的博客 304

mysql mongodb tidb_TiDB和MongoDB分片集群架构比较

此文已由作者温正湖授权网易云社区发布。欢迎访问网易云社区,了解更多网易技术产品运营经验。最近阅读了TiDB源码的说明文档,跟MongoDB的分片集群做了下简单对比。首先展示TiDB的整体架构MongoDB分片集群架构如下:更加具体点如下:下面从介绍TiDB组件的角度切入,将其跟MongoDB分片集群做对比。TiDB 集群主要分为三个组件:TiDB ServerTiDB Server 负责接收 SQ...

weixin_28923083的博客 432

MongDB初识

MongoDB是一种开源的分布式文档型数据库管理系统,它使用类似于JSON的BSON格式(Binary JSON)来存储数据。与传统关系型数据库不同,MongoDB不使用表和行的结构,而是采用集合(Collection)(Mysql表)和文档(Document)(MySql行)的概念来组织数据。

w2144217940的博客 693

MongoDB部署模型概述、分片

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34184158的博客 236

MongDB 数据库简单介绍

通过以上内容,你可以快速上手 MongoDB 的基本操作!如果需要进一步学习,建议参考官方文档:https://docs.mongodb.com/,以高性能、高扩展性和灵活的数据模型著称。(类似 JSON 格式的 BSON),适合处理。MongoDB 是一个开源的。

FAQEW的博客 988
上一篇: MongoDB 分片的原理、搭建、应用
下一篇: Mongdb分片实战一(集群搭建)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值