【问题标题】:Tombstoned cells without DELETE没有删除的墓碑单元格
【发布时间】:2014-10-16 03:05:01
【问题描述】:

我正在运行 Cassandra 集群

Software version: 2.0.9
Nodes: 3
Replication factor: 2

我有一个非常简单的表格,我可以在其中插入和更新数据。

CREATE TABLE link_list (
      url text,
      visited boolean,
      PRIMARY KEY ((url))
    );

行没有过期,我没有执行任何删除操作。一旦我运行我的应用程序,由于墓碑单元数量的增加,它很快就会变慢:

Read 3 live and 535 tombstoned cells

它在几分钟内达到数千。

我的问题是,如果我不进行任何删除,是什么负责生成这些单元格?

// 更新

这是我用来通过 com.datastax.driver 与 Cassandra 对话的实现。

public class LinkListDAOCassandra implements DAO {


    public void save(Link link) {
        save(new VisitedLink(link.getUrl(), false));
    }

    @Override
    public void save(Model model) {
        save((Link) model);
    }

    public void update(VisitedLink link) {
        String cql = "UPDATE link_list SET visited = ? WHERE url = ?";
        Cassandra.DB.execute(cql, ConsistencyLevel.QUORUM, link.getVisited(), link.getUrl());
    }

    public void save(VisitedLink link) {
        String cql = "SELECT url FROM link_list_inserted WHERE url = ?";

        if(Cassandra.DB.execute(cql, ConsistencyLevel.QUORUM, link.getUrl()).all().size() == 0) {
            cql = "INSERT INTO link_list_inserted (url) VALUES (?)";
            Cassandra.DB.execute(cql, ConsistencyLevel.QUORUM, link.getUrl());

            cql = "INSERT INTO link_list (url, visited) VALUES (?,?)";
            Cassandra.DB.execute(cql, ConsistencyLevel.QUORUM, link.getUrl(), link.getVisited());
        }
    }

    public VisitedLink getByUrl(String url) {
        String cql = "SELECT * FROM link_list WHERE url = ?";

        for(Row row : Cassandra.DB.execute(cql, url)) {
            return new VisitedLink(row.getString("url"), row.getBool("visited"));
        }

        return null;
    }

    public List<Link> getLinks(int limit) {
        List<Link> links = new ArrayList();
        ResultSet results;

        String cql = "SELECT * FROM link_list WHERE visited = False LIMIT ?";

        for(Row row : Cassandra.DB.execute(cql, ConsistencyLevel.QUORUM, limit)) {
            try {
                links.add(new Link(new URL(row.getString("url"))));
            }
            catch(MalformedURLException e) { }
        }

        return links;
    }
}

这是执行实现

public ResultSet execute(String cql, ConsistencyLevel cl, Object... values) {
        PreparedStatement statement = getSession().prepare( cql ).setConsistencyLevel(cl);
        BoundStatement boundStatement = new BoundStatement( statement );
        boundStatement.bind(values);

        return session.execute(boundStatement);
    }

// 更新 2

cfstats 的一个有趣发现表明,只有一张表有墓碑。这是link_list_visited。这是否意味着使用二级索引更新列会创建墓碑?

Table (index): link_list.link_list_visited
                SSTable count: 2
                Space used (live), bytes: 5055920
                Space used (total), bytes: 5055991
                SSTable Compression Ratio: 0.3491883995187955
                Number of keys (estimate): 256
                Memtable cell count: 15799
                Memtable data size, bytes: 1771427
                Memtable switch count: 1
                Local read count: 85703
                Local read latency: 2.805 ms
                Local write count: 484690
                Local write latency: 0.028 ms
                Pending tasks: 0
                Bloom filter false positives: 0
                Bloom filter false ratio: 0.00000
                Bloom filter space used, bytes: 32
                Compacted partition minimum bytes: 8240
                Compacted partition maximum bytes: 7007506
                Compacted partition mean bytes: 3703162
                Average live cells per slice (last five minutes): 3.0
                Average tombstones per slice (last five minutes): 674.0

【问题讨论】:

  • 你用的是什么客户端?贴出你用来插入数据的代码……如果你用 cqlsh 来放数据,这会发生吗?
  • com.datastax.driver - 我将代码添加到描述中。
  • 我想到的唯一一件事是该表是使用默认 ttl 创建的...您可以打印一个描述表输出吗?如果您使用 cqlsh 放置数据,它们会消失吗?
  • 请看我的第二次更新。看起来用二级索引更新列会生成墓碑。不知道有什么办法可以解决它。
  • 是的,我用二级索引更新了很多列。每条记录都以“visited = False”开头,目的是让它们都变成“visited = True”。我得出的结论是我以不正确的方式使用 cassandra。我知道不鼓励排队,但我认为如果我不运行删除,就可以摆脱它。

标签: cassandra cql


【解决方案1】:

二级索引和额外的列族手动保存索引的唯一主要区别是二级索引只包含有关当前节点的信息(即它不包含有关其他节点数据的信息)以及对当前节点的操作由于对主表的更新,二级索引是原子操作。除此之外,您可以将其视为具有相同弱点的常规列族,主列族上的大量更新将导致索引表上的大量删除,因为主表上的更新将被翻译作为对索引表的删除/插入操作。索引表中的所述删除是墓碑的来源。 Cassandra 删除是逻辑删除,直到下一个修复过程(删除墓碑时)。

希望对你有帮助!

【讨论】:

    猜你喜欢
    • 2015-06-04
    • 2018-03-19
    • 2017-09-17
    • 2019-02-16
    • 2015-06-04
    • 2017-10-03
    • 2017-08-16
    • 2018-10-16
    • 2020-05-02
    相关资源
    最近更新 更多