2013-03-11 11 views
3

我跑我的地方(MAC)機上和遠程Unix服務器:卡桑德拉更新,就不一貫工作

public void deleteValue(final String id, final String value) { 
    log.info("Removing value " + value); 
    final Collection<String> valuesBeforeRemoval = getValues(id); 
    final MutationBatch m = keyspace.prepareMutationBatch(); 
    m.withRow(VALUES_CF, id).deleteColumn(value); 
    try { 
     m.execute(); 
    } catch (final ConnectionException e) { 
     log.error("Unable to delete location " + value, e); 
    } 
    final Collection<String> valuesAfterRemoval = getValues(id); 
    if (valuesAfterRemoval.size()!=(valuesBeforeRemoval.size()-1)) { 
     log.error("value " + value + " was supposed to be removed from list " + valuesBeforeRemoval + " but it wasn't: " + valuesAfterRemoval); 
    } 
... 
    } 

protected Collection<String> getValues(final String id) { 
    try { 
    final OperationResult<ColumnList<String>> operationResult = keyspace 
      .prepareQuery(VALUES_CF).getKey(id).execute(); 
    final ColumnList<String> result = operationResult.getResult(); 
    if (result.isEmpty()) { 
     log.info("No value found for id: " + id); 
     return new ArrayList<String>(); 
    } 
    return result.getColumnNames(); 
    } catch (final ConnectionException e) { 
    log.error("Unable to retrieve session " + id, e); 
    } 
    return new ArrayList<String>(); 
} 

本地下列代碼,該行永遠不會執行,這是有道理的:

log.error("value " + value + " was supposed to be removed from list " + valuesBeforeRemoval + " but it wasn't: " + valuesAfterRemoval); 

但線我開發服務器上執行:

[錯誤] [主要] [nowsdSessionDaoCassandraImpl] [2013年3月8日13:12:24801] [] - 值3本來從列表中刪除[3,2,1,0,7,6,5,4,9,8],但不是:[3,2,1,0,7,6,5,4,9,8, 8]

  • 我使用com.netflix.astyanax
  • 我的兩個本地計算機和遠程開發服務器連接到非常 同卡桑德拉實例。
  • 我的本地機器和遠程開發服務器都運行相同的測試 創建一個新的行系列,並在刪除之前添加10條記錄。
  • 當dev發生錯誤時,log.error(「無法刪除 location」+ value,e);未執行(即運行刪除 命令未產生任何異常)。
  • 我100%肯定地說沒有其他代碼正在影響 數據庫的內容,而我正在dev上運行測試,所以這不是一些 奇怪的併發問題。

什麼可能解釋deleteColumn(值)請求運行時不會產生任何錯誤,但仍不會從數據庫中刪除列?

附加信息

這裏是我所創建的密鑰空間:

create keyspace sessiondata 
    with placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' 
    and strategy_options = {replication_factor:1}; 

這是我如何創建在上面的代碼列家族值,如VALUES_CF引用:

create column family values 
    with comparator = UTF8Type 
; 

以下是如何定義上面java代碼中引用的密鑰空間:

final AstyanaxContext.Builder contextBuilder = getBuilder(); 
final AstyanaxContext<Keyspace> keyspaceContext = contextBuilder 
     .forKeyspace(keyspaceName).buildKeyspace(
       ThriftFamilyFactory.getInstance()); 
keyspaceContext.start(); 
keyspace = keyspaceContext.getEntity(); 

其中getBuilder是:

private Builder getBuilder() { 
    final AstyanaxConfigurationImpl conf = new AstyanaxConfigurationImpl() 
    .setDiscoveryType(NodeDiscoveryType.NONE) 
    .setRetryPolicy(new RunOnce()); 

    final ConnectionPoolConfigurationImpl poolConf = new ConnectionPoolConfigurationImpl("MyPool") 
    .setPort(port) 
    .setMaxConnsPerHost(1) 
    .setSeeds(value); 

    return new AstyanaxContext.Builder() 
    .forCluster(cluster) 
    .withAstyanaxConfiguration(conf) 
    .withConnectionPoolConfiguration(poolConf) 
    .withConnectionPoolMonitor(new CountingConnectionPoolMonitor()); 
    } 

第二次更新

  • 首先,問題並不僅僅涉及到刪除。在數據庫更新時記錄,閱讀他們,不能夠讀取我只是寫

  • 二更新我觀察到類似的問題,我創建了一個測試,做以下操作100次:

    • 寫一行到卡桑德拉
    • 更新該行卡桑德拉
    • 從卡桑德拉讀回該行並檢查該行是否確實更新,延遲後再次定期檢查,如果它不是

    我從試驗觀察是:

    • 再次,當我在本地運行的代碼,所有100次迭代正確通過(無重試曾經需要)
    • 當我在遙控器上運行的代碼服務器,一些迭代通過,一些失敗。當它們失敗時,無論延遲有多大(我等待10秒鐘),測試總是失敗。

在這一點上,我真的不知道,因爲我連接到我的測試非常相同的服務器,因爲我插入比任何額外延遲大得多的延遲任何卡桑德拉設置如何能解釋這種現象從本地計算機連接時,可能需要運行測試。

唯一的區別似乎是代碼運行在哪臺機器上。

第三更新

如果在以前的更新中提到的試驗中,我插入延遲之間的2寫入,代碼開始傳送,如果延遲是> = 1000毫秒。例如100毫秒的延遲沒有幫助。我還修改了構建器以將默認的讀寫一致性設置爲最苛刻的:ALL,並且對測試結果沒有影響(除非寫入之間的延遲> 1s,否則大約一半的時間仍然失敗):

final AstyanaxConfigurationImpl conf = new AstyanaxConfigurationImpl() 
.setDiscoveryType(NodeDiscoveryType.NONE) 
.setRetryPolicy(new RunOnce()).setDefaultReadConsistencyLevel(ConsistencyLevel.CL_ALL).setDefaultWriteConsistencyLevel(ConsistencyLevel.CL_ALL); 
+2

您是否知道墓碑的行爲,並且您在防範嗎?我對astyanax API不熟悉,但是當您執行刪除操作時,有問題的項目會一直顯示在結果中,直到Cassandra將其清除爲止,並且您需要仔細查看結果以確定該項目是否真的被刪除。 – 2013-03-11 20:48:09

+0

嗯,不,我對墓碑行爲一無所知,並且從我所瞭解的情況來看,它可能是原因,儘管這並不能解釋爲什麼它發生在我的機器上而不是一個開發者,除非可能延遲對於我來說,連接cassandra的時間足夠長,以至於如果我在開發中運行,條目有時間消失。無論如何,我會在你剛纔建議的角度下更仔細地看待這一點。謝謝。 – Lolo 2013-03-12 04:11:15

+2

列刪除不會顯示在Cassandra的回覆中,只有行刪除會。所以這是你沒有讀回你立即寫的內容的情況。 Cassandra在使用最終一致性時有這種行爲。你正在使用什麼複製策略和複製選項?你在讀寫什麼一致性水平?最有可能的是,刪除沒有傳播,並且您的讀取使用了一個沒有看到刪除的不同節點。也許你的unix box連接速度比你的mac快,所以你只能在那裏看到它。 – Richard 2013-03-12 14:12:46

回答

1

要進行調試,請嘗試打印整行而不是列名。當我說整行時,我的意思是列名,列值和時間戳。在你的一臺測試機器上有一個很長的時間是錯誤的,而這正在把你的測試扔到另一臺上。

另一件需要仔細檢查的事情是,ip確實是你認爲它在你的應用程序和cassandra中。當你檢索它時,在println(「 - 」+ ip「 - 」)之間打印。在你嘗試在deleteSecureLocation中執行的塊之前和之後,只能獲取該列,而不是整行。我不太清楚如何在astynax上做到這一點,它會得到[id] [ip]。

需要注意的是即使沒有任何東西需要刪除,刪除也不會失敗。對於cassandra這是一個寫,唯一會讓它成爲刪除的東西是,如果在讀取時它是針對該行/列名的最新時間戳條目。