启动Cassandra时读取保存的缓存和系统表时出错

启动Cassandra时读取保存的缓存和系统表时出错,cassandra,Cassandra,在运行Cassandra守护进程时,我遇到了以下异常。我从1.2号行李箱跑 WARN 14:47:51,038 error reading saved cache /home/manuzhang/cassandra/saved_caches/system-local-KeyCache-b.db java.lang.NullPointerException at org.apache.cassandra.cache.AutoSavingCache.loadSaved(AutoSavingC

在运行Cassandra守护进程时,我遇到了以下异常。我从1.2号行李箱跑

WARN 14:47:51,038 error reading saved cache /home/manuzhang/cassandra/saved_caches/system-local-KeyCache-b.db
java.lang.NullPointerException
    at org.apache.cassandra.cache.AutoSavingCache.loadSaved(AutoSavingCache.java:141)
    at org.apache.cassandra.db.ColumnFamilyStore.<init>(ColumnFamilyStore.java:237)
    at org.apache.cassandra.db.ColumnFamilyStore.createColumnFamilyStore(ColumnFamilyStore.java:340)
    at org.apache.cassandra.db.ColumnFamilyStore.createColumnFamilyStore(ColumnFamilyStore.java:312)
    at org.apache.cassandra.db.Table.initCf(Table.java:332)
    at org.apache.cassandra.db.Table.<init>(Table.java:265)
    at org.apache.cassandra.db.Table.open(Table.java:110)
    at org.apache.cassandra.db.Table.open(Table.java:88)
    at org.apache.cassandra.db.SystemTable.checkHealth(SystemTable.java:284)
    at org.apache.cassandra.service.CassandraDaemon.setup(CassandraDaemon.java:168)
    at org.apache.cassandra.service.CassandraDaemon.activate(CassandraDaemon.java:318)
    at org.apache.cassandra.service.CassandraDaemon.main(CassandraDaemon.java:361)
此外,无法加载系统表文件

ERROR 17:03:16,637 Fatal exception during initialization
org.apache.cassandra.config.ConfigurationException: Found system table files, but they    couldn't be loaded!
at org.apache.cassandra.db.SystemTable.checkHealth(SystemTable.java:303)
at org.apache.cassandra.service.CassandraDaemon.setup(CassandraDaemon.java:201)
at org.apache.cassandra.service.CassandraDaemon.activate(CassandraDaemon.java:349)
at org.apache.cassandra.service.CassandraDaemon.main(CassandraDaemon.java:392)
现在,我能够为Cassandra的每三次运行重现加载系统表故障(之后我会清理所有文件)。异常在此处引发:

/**
 * One of three things will happen if you try to read the system table:
 * 1. files are present and you can read them: great
 * 2. no files are there: great (new node is assumed)
 * 3. files are present but you can't read them: bad
 * @throws ConfigurationException
 */
public static void checkHealth() throws ConfigurationException
{
    Table table;
    try
    {
        table = Table.open(Table.SYSTEM_TABLE);
    }
    catch (AssertionError err)
    {
        // this happens when a user switches from OPP to RP.
        ConfigurationException ex = new ConfigurationException("Could not read system table!");
        ex.initCause(err);
        throw ex;
    }
    ColumnFamilyStore cfs = table.getColumnFamilyStore(LOCAL_CF);

    String req = "SELECT cluster_name FROM system.%s WHERE key='%s'";
    UntypedResultSet result = processInternal(String.format(req, LOCAL_CF, LOCAL_KEY));

    if (result.isEmpty() || !result.one().has("cluster_name"))
    {
        // this is a brand new node
        if (!cfs.getSSTables().isEmpty())
            throw new ConfigurationException("Found system table files, but they couldn't be loaded!");

        // no system files.  this is a new node.
        req = "INSERT INTO system.%s (key, cluster_name) VALUES ('%s', '%s')";
        processInternal(String.format(req, LOCAL_CF, LOCAL_KEY, DatabaseDescriptor.getClusterName()));
        return;
    }

    String savedClusterName = result.one().getString("cluster_name");
    if (!DatabaseDescriptor.getClusterName().equals(savedClusterName))
        throw new ConfigurationException("Saved cluster name " + savedClusterName + " != configured name " + DatabaseDescriptor.getClusterName());
}
这三次运行完全符合注释中的三个条件

第一次运行时“没有文件”,因为它是一个全新的节点

在第二次运行中,“文件在那里,您可以读取它们”

在第三次运行中,“文件在那里,但您无法读取它们”,我检查了
result.isEmpty()
result.one.has(“集群名称”)
返回
false

实际上,我对异常“无法加载”感到困惑。这是什么意思?我认为这不是文件系统权限问题,因为r/w权限被授予当前用户

在我删除所有相关文件后,上述问题就会消失,但我不想每次运行Cassandra时都这样做

这已经折磨了我好一阵子了

一个无关的问题是我不认为Cassandra@stackoverflow受到了社会的足够关注。你同意吗

如有任何意见或建议,将不胜感激


谢谢。

我在两种情况下遇到了这个问题

  • 我尝试在不删除集群数据的情况下更改分区器(不能这样做),也可以查看以进行解释
  • 第一次启动cassandra进程时,我以超级用户的身份运行了它。
    sudo./cassandra
    ,它创建了只对超级用户具有权限的必要数据/日志/缓存目录,然后重新启动cassandra并以普通用户的身份运行该进程(因此没有权限使用超级用户运行的进程创建的目录中的文件)

  • 我知道你解决了这个问题,但这可能对其他开发人员有用。

    为什么你运行的是cassandra trunk,而不是发布的版本?@sbridges如果你在cassandra wiki之后下载代码库,那就是你得到的;我还可以读到一些新的东西,比如虚拟节点。你可以用官方版本重现你的问题吗以此类推,@sbridges还没有尝试过。会有什么不同吗?即使如此,这也不能解决我的主干问题。试着用一个发布的版本复制它。我不知道主干有多稳定,但它可能很容易出现错误。
    /**
     * One of three things will happen if you try to read the system table:
     * 1. files are present and you can read them: great
     * 2. no files are there: great (new node is assumed)
     * 3. files are present but you can't read them: bad
     * @throws ConfigurationException
     */
    public static void checkHealth() throws ConfigurationException
    {
        Table table;
        try
        {
            table = Table.open(Table.SYSTEM_TABLE);
        }
        catch (AssertionError err)
        {
            // this happens when a user switches from OPP to RP.
            ConfigurationException ex = new ConfigurationException("Could not read system table!");
            ex.initCause(err);
            throw ex;
        }
        ColumnFamilyStore cfs = table.getColumnFamilyStore(LOCAL_CF);
    
        String req = "SELECT cluster_name FROM system.%s WHERE key='%s'";
        UntypedResultSet result = processInternal(String.format(req, LOCAL_CF, LOCAL_KEY));
    
        if (result.isEmpty() || !result.one().has("cluster_name"))
        {
            // this is a brand new node
            if (!cfs.getSSTables().isEmpty())
                throw new ConfigurationException("Found system table files, but they couldn't be loaded!");
    
            // no system files.  this is a new node.
            req = "INSERT INTO system.%s (key, cluster_name) VALUES ('%s', '%s')";
            processInternal(String.format(req, LOCAL_CF, LOCAL_KEY, DatabaseDescriptor.getClusterName()));
            return;
        }
    
        String savedClusterName = result.one().getString("cluster_name");
        if (!DatabaseDescriptor.getClusterName().equals(savedClusterName))
            throw new ConfigurationException("Saved cluster name " + savedClusterName + " != configured name " + DatabaseDescriptor.getClusterName());
    }