Cassandra:table 中的固定行数

Cassandra: Fixed number of rows in a table

我想创建一个 table 具有固定行数(假设为 N),如果添加第 N+1 行,则将删除第 1 行。

这是 table,我用来存储图形分析的最后 N 个最佳结果:

CREATE TABLE IF NOT EXISTS lp_registry.best (
    value float, // best value for current graph
    verts int,   // number of vertices in graph
    edges int,   // number of edges in graph
    wid text,    // worker id       
    id timeuuid, // timeuuid
    PRIMARY KEY (wid, id)
) WITH CLUSTERING ORDER BY (id ASC);

我读过 expiring data at DataStax,但只发现 TTL 过期。所以我决定按照下面的方式去做。

我的方法A:

每次要添加新结果时,都会检索最旧行的 ID..

SELECT wid, id FROM lp_registry.best LIMIT 1;

..以及当前行数..

SELECT COUNT(*) FROM FROM lp_registry.best;

因此,如果计数 >= N,则删除最旧的行并添加最新的行...

BEGIN BATCH
    INSERT INTO lp_registry.best (value, verts, edges, wid, id) VALUES (?, ?, ?, ? now());
    DELETE FROM lp_registry.best WHERE wid = ? AND id = ?;
APPLY BATCH;

此方法存在问题,因为第一个 selects 不是原子操作以及后续批处理。因此,如果任何其他工作人员删除了 select 和批次之间最旧的行,或者超过了 N,那么这将不起作用。

我的方法B:

相同的第一步...

SELECT wid, id FROM lp_registry.best LIMIT 1;
SELECT COUNT(*) FROM FROM lp_registry.best;

然后尝试一次又一次地删除最旧的行,直到成功..

if count < N {
  INSERT INTO lp_registry.best (value, verts, edges, wid, id) VALUES (?, ?, ?, ? now());
} else { 
  while not success {
    DELETE FROM lp_registry.best WHERE wid = ? AND id = ? IF EXISTS;
  }
  INSERT INTO lp_registry.best (value, verts, edges, wid, id) VALUES (?, ?, ?, ? now());
}

在这种方法中,在检查计数 < N 之前,数据库中超过 N 仍然存在问题。

你能指出正确的解决方案吗?

这是我的解决方案。首先我们需要创建一个 table 来存储当前行数...

CREATE TABLE IF NOT EXISTS row_counter (
  rmax int,  // maximum allowed number of rows
  rows int,  // current number of rows
  name text, // name of table
  PRIMARY KEY (name)
);

然后为给定的固定行初始化它 tables:

INSERT INTO row_counter (name, rmax, rows) 
VALUES ('best', 100, 0);

这些是以下代码中使用的语句:

q1 = "SELECT rows, rmax FROM row_counter WHERE name = 'best'";
q2 = "UPDATE row_counter SET rows = ? WHERE name = 'best' IF rows < ?";
q3 = "SELECT wid, id FROM best LIMIT 1";
q4 = "DELETE FROM best WHERE wid = ? AND id = ? IF EXISTS";
q5 = "INSERT INTO best (vertex, value, verts, edges, wid, id) VALUES (?, ?, ?, ?, ?, now())";

selectCounter = session.prepare(q1);
updateCounter = session.prepare(q2);
selectOldBest = session.prepare(q3);
deleteOldBest = session.prepare(q4);
insertNewBest = session.prepare(q5);

Java中的解决方案:

// Success indicator
boolean succ = false;

// Get number of registered rows in the table with best results
Row row = session.execute(selectCounter.bind()).one();
int rows = row.getInt("rows") + 1;
int rmax = row.getInt("rmax");

// Repeatedly try to reserve empty space in table
while (!succ && rows <= rmax) {
  succ = session.execute(updateCounter.bind(rows, Math.min(rows, rmax))).wasApplied();
  rows = session.execute(selectCounter.bind()).one().getInt("rows") + 1;
}

// If there is not empty space in table, repeatedly try to make new empty space
while (!succ) {
  row = session.execute(selectOldBest.bind()).one();
  succ = session.execute(deleteOldBest.bind(row.getString("wid"), row.getUUID("id"))).wasApplied();
}

// Insert new row
session.execute(insertNewBest.bind(vertex, value, verts, edges, workerCode));