2017-05-27 33 views
0

我試圖實現數據存儲中的強一致性,不知道任何其他方式來處理我的需求。我有一個應用程序,用戶可以隨機連接。所以基本上在'connect'api調用中,它查詢QueueUser實體,如果它沒有找到任何實體,它將推送隊列中的主叫用戶。強化GAE上的客觀性與一致性

ofy().load().type(QueueUser.class) 
    .filterKey("!=", KeyFactory.createKey("QueueUser", caller.id)) 
    .order("__key__") 
    .order("-time") 
    .limit(5) 
    .keys(); 

我明白,這將不會獲取最新的實體按鍵,爲指標可能不是最新的。所以我通過密鑰進行交流,並通過密鑰獲取每個實體。如果我得到一個非null的實體,我會嘗試刪除它。如果我成功了,我認爲這是用戶的一個匹配。這個get-by-key和delete()在Transaction中。

  while(keyIterator.hasNext()) { 
       QueueUser queueUser = null; 
       try { 
        final Key<QueueUser> key = keyIterator.next(); 
        queueUser = ofy().transactNew(1, new Work<QueueUser>() { 
         public QueueUser run() { 
          QueueUser queueUser = ofy().load().key(key).now(); 
          if(queueUser == null) { 
           logger.log(Level.WARNING, "queue user was already deleted"); 
           return null; 
          } 
          else 
           ofy().delete().key(key).now(); 
          return queueUser; 
         } 
        }); 
       } catch (ConcurrentModificationException e) { 
        logger.log(Level.WARNING, "exception while deleting queue user. err: " + e.getMessage()); 
       } 
       if (queueUser != null) { 
       // we have a match here 
       // delete calling user from the queue if it's there 
       ofy().delete().entity(new QueueUser(caller.id, null, null, null, null, null, null, null, null)).now(); 
       break; 
       } 
      } 

這在大多數情況下都能正常工作,但有時候用戶會被擠入隊列中而不能快速拾起。請求延遲時間長達15秒。查詢返回很多實體,但大多數都被刪除,有些會被對等請求刪除(預期爲ConcurrentModificationException)。

我想知道如果我在這裏丟失了任何明顯的東西,或者有沒有更好的方法來處理這個問題。

回答

1

這段代碼絕對沒有意義,也沒有做你想做的事情。抱歉。我建議刪除所有的代碼,只包括這個問題:

我有一個應用程序,用戶之間隨機連接。 所以基本上'連接'api調用,它查詢QueueUser實體, 如果沒有找到任何實體,它會推送主叫用戶在隊列中。

假設您需要按比例(每秒多次)執行此操作,這對於數據存儲實際上是一件很難的事情。數據存儲不喜歡快速變異的狀態。你真正擁有的不是一個隊列,而是一個地方;每當有人連接時,他們要麼放在現場(如果是空的),要麼與現場人員配對(使現場空着)。

我會使用不同的工具。將持久狀態存儲爲諸如配對之類的短暫事物是毫無意義的。無論如何,客戶需要重試邏輯。

Memcache可以是一個不錯的選擇 - 使用getIdentifiableputIfUntouched使它成爲事務性的,並結合一些重試邏輯。唯一的問題是GAE的Memcache偶爾會變得不可用(它不如數據存儲可靠)。如果你正在構建一款熱門遊戲的matchmaking引擎,你可能想要在GCE中運行你自己的memcached。

老實說,構建自己的內存服務並將其作爲單例運行可能更容易。一個簡單的版本可能是10行代碼。

+0

謝謝你的回答。我知道數據存儲不適合我的要求。是的,不需要持久性存儲。我會嘗試memcache。我認爲memcache只與數據存儲一起使用,如果在memcache中找不到@cached實體,它會從數據存儲中獲取它。 – sandeepd

+0

帶'getIdentifiable'和'putIfUntouched'的Memcache完成了這個任務。延遲大幅降低。非常感謝@stickfigure!順便說一句,在極少數情況下,兩個請求在精確的毫秒內執行'putIfUntouched',它返回'true'。 – sandeepd