什么是固定集合
固定集合(capped collection)是一种限定大小的集合,其中capped是覆盖、限额的意思。跟普通的集合相比,数据在写入这种集合时遵循FIFO原则。可以将这种集合想象为一个环状的队列,新文档在写入时会被插入队列的末尾,如果队列已满,那么之前的文档就会被新写入的文档所覆盖
类似于环形队列,只不过 新来的元素会覆盖之前的元素 。
创建一个环形队列
db.createCollection(
"logs",
{capped:true ,size:4096,max:10}
)
#向其中插入十条数据
for(var i=0;i<15;i++){
db.logs.insert({t:"row-"+i})
}
res:
- 有最5条数据消失不见了
如果不指定max参数,那么当文档的总大小(空间占用)超过size限额时,也会产生覆盖的情况:
db.createCollection(
“logs”,
{capped:true ,size:4096}
)
特征
固定集合在底层使用的是顺序I/O操作,而普通集合使用的是随机I/O。众所周知,顺序I/O在磁盘操作上由于寻道次数少而比随机I/O要高效得多,因此固定集合的写入性能是很高的。此外,如果按写入顺序进行数据读取,也会获得非常好的性能表现。
(1)无法动态修改存储的上限,如果需要修改max或size,则只能先执行collection.drop命令,将集合删除后再重新创建。
(2)无法删除已有的数据,对固定集合中的数据进行删除将会得到如下错误
(3)对已有数据进行修改,新文档大小必须与原来的文档大小一致,否则不允许更新
(4)默认情况下,固定集合只有一个_id索引,而且最好是按数据写入的顺序进行读取。当然,也可以添加新的索引,但这会降低数据写入的性能。
(5)固定集合不支持分片,同时,在MongoDB 4.2版本中规定了事务中也无法对固定集合执行写操作。
总结:只能再合适的地方才能适用 。例如日志,存储少量文档
使用固定集合实现FIFO (先进先出)
在股票实时系统中,大家往往最关心股票价格的变动。而应用系统中也需要根据这些实时的变化数据来分析当前的行情。倘若将股票的价格变化看作是一个事件,而股票交易所则是价格变动事件的“发布者”,股票APP、应用系统则是事件的“消费者”。这样,我们就可以将股票价格的发布、通知抽象为一种数据的消费行为,此时往往需要一个消息队列来实现该需求。
生产者
创建一个fifo环形队列
db.createCollection("stockqueue",{capped:true,size:10485760})
function pushEvent(){
while(true){
db.stockqueue.insertOne({
timestamped:new Date(),
stock: "MongoDB Inc",
price: 100*Math.random(1000)
})
}
print("publish stock changed");
sleep(1000);
}
pushEvent()
消费者
function listen() {
var cursor = db.stockqueue.find({timestamped: {$gte: new Date()}}).tailable();
while (true) {
if (cursor.hasNext()) {
print(JSON.stringify(cursor.next(), null, 2))
}
}
}
listen()