2014-07-16 22 views
0

我有一個表中的數據列使用SQL來按ID排序事件列表。我們用這個在我們的網站上顯示這些事件的活動提要,但是想把所有這些移到redis。我們已經完成了很多方法來完成這樣的事情,但我想從這裏的社區中反彈出來以獲得一些反饋。這是當前的專欄。在多個鍵上對Redis進行復雜排序。建築活動飼料

enter image description here

會有另一個哈希表中的所有事件的數據是肯定的。然而,事情變得粘滯的是時機,需要多種類型。第一個問題是我們系統中的事件既有未來,現在也有過去。因此,我們需要能夠通過考慮當前時間,看看現在,將來和現在正在發生的事情。然而,除此之外,我們還有其他的colums可以排序。多重排序是事情真正發生的地方。以下是一些多種排序:

是功能? (boolean)=它是否是一個特色事件,如果是這樣,它應該顯示在我們的源的頂部,而不管時間。

現在發生了嗎? (unixtimestamp)=根據當前時間進行檢查,並獲取所有正在進行的事情列表和列表ID。

它過去了嗎? (unixtimestamp)=檢查當前的時間,看看它已經完成,列表ID

是在將來(unixtimestamp)=檢查當前的時間,看看它後面發生的事情,列表ID

事情變得更瘋狂當你考慮到事件屬於其他用戶時。所以我們也必須採取這些想法並通過USER ID過濾出來,然後對它們進行排序。我們不喜歡爲每個用戶擁有數千個有序集的想法。那麼你們會如何去解決像這樣的複雜流?

回答

2

在Redis中可視化關係數據不是直截了當的。像在討論的例子中一樣,存儲具有不同排序選項的數據是一個挑戰。可能的解決方案可能在第一次實例時效率不高,但應該進行性能測試以得出最終結論。

我的執行會出現這樣的解決方案建議:

每列應被映射到Redis的列表。選擇LIST是因爲重複條目是可能的,否則可以使用SET。

在上面的例子中,我們可以有以下列表:

ID,ACTIVITY_TYPE,ACTIVITY_ID,列表類型,LISTING_ID,IS_PUBLIC,CREATED_AT,的updated_at,ACTIVITY_AT

數據存儲在在下面的方式這些列表:

//first row 
    //Column ID 
    $ redis-cli lpush ID 10730268 
    1 

    //If we want to search by ID then create a separate HASH for ID 
    $ redis-cli HSET ID_HASH 10730268 1 
    1 

    //If we want to search by sorted ID then create a separate LIST which stores IDs 
    $ redis-cli lpush SORTED_ID 10730268 

    //Column ACTIVITY_TYPE 
    $ redis-cli lpush ACTIVITY_TYPE "created_event_highlight" 
    1 

    //Column ACTIVITY_ID 
    $ redis-cli lpush ACTIVITY_ID 707003 
    1 

    //Column LISTING_TYPE 
    $ redis-cli lpush LISTING_TYPE "CHANNEL" 
    1 

    //Column LISTING_ID 
    $ redis-cli lpush LISTING_ID 51670 
    1 

    //Column IS_PUBLIC 
    $ redis-cli lpush IS_PUBLIC 1 
    1 

    //Column CREATED_AT 
    $ redis-cli lpush CREATED_AT "2013-04-21 13:34:09" 
    1 

    //If we want to search by sorted CREATED_AT then create a separate 
    //LIST which maintains for CREATED_AT 
    $ redis-cli lpush SORTED_CREATED_AT "2013-04-21 13:34:09" 
    1 
    //If we want to search by CREATED_AT then create a separate HASH 
    $ redis-cli HSET CREATED_AT_HASH "2013-04-21 13:34:09" 1 
    1 
    //Column UPDATED_AT 
    $ redis-cli lpush UPDATED_AT "2013-04-02 11:34:09" 
    1 

    //Column ACTIVITY_AT 
    $ redis-cli lpush ACTIVITY_AT "2014-01-01 03:04:01" 
    1 

HASH ID_HASH用於使用ID作爲KEY搜索數據。如果要使用SORTED ID檢索數據,則可以使用SORT命令對SORTED_ID列表進行排序。可以使用從SORTED_ID返回的已排序ID來搜索ID_HASH以獲取索引。使用這個INDEX我們可以得到所有列的值。

To fetch data you can do something like : 
    $ redis-cli hget ID_HASH 10730268 
    1 

    Using these to values as index query columns as 
    $redis-cli lindex ID 1 
    10730268 

    $redis-cli lindex ACTIVITY_TYPE 1 
    "created_event_highlight" 
    $redis-cli lindex ACTIVITY_ID 1 
    707003 
    $redis-cli lindex LISTING_TYPE 1 
    "CHANNEL 
    $redis-cli lindex IS_PUBLIC 1 
    1 
    $redis-cli lindex CREATED_AT 1 
    "2013-04-21 13:34:09" 
    $redis-cli lindex UPDATED_AT 1 
    "2013-04-02 11:34:09" 
    $redis-cli lindex ACTIVITY_AT 1 
    "2014-01-01 03:04:01" 

類似地,如果數據是使用SORTED CREATED_AT然後被檢索,SORTED_CREATED_AT列表可能是使用排序SORT命令。可以在HASH CREATED_AT_HASH中搜索返回的CREATED_AT以獲取索引。使用這個INDEX我們可以得到所有列的值。這是假設ID時間戳是唯一的。如果時間戳是常見的,那麼我們必須爲每個時間戳創建單獨的LISTS,並存儲映射到時間戳的所有索引。

您可以採取的其他方法是將您的數據映射到數據結構並創建其對象。將這些已創建的對象以序列化的字符串形式存儲在REDIS中,用於標識或時間戳。

不存在將關係數據庫映射到REDIS的直接方法。也許你可以探索其他的NoSQL選項。但是,如果REDIS是您的話,那麼請嘗試使用REDIS中的可能的數據結構(字符串,列表,集合,哈希)來實現或創新。

===========================================

序列化對象

考慮到上述解決辦法有問題,創造它的給定的數據映射一個datatstructre和串序列化格式存儲它們針對不同的按鍵似乎更合理。

(C++結構的一個例子)

struct EventInformation{ 
    friend class boost::serialization::access; 

    long id;   //Primary key, you could have primary key as 
         //combination of members, accordingly KEY in 
         //HASH TABLE and values being stored in LISTS would change 
    long activityId; 
    long listingId; 
    bool isPublic; 
    std::string activityType; 
    std::string listingType; 
    std::string createdAt; 
    std::string updatedAt; 
    std::string activityAt; 

    template<class Archive> 
     void serialize(Archive &ar, const unsigned int version){ 

     ar & id 
      & activityId 
      & listingId 
      & isPublic 
      & activityType 
      & listingType 
      & createdAt 
      & updatedAt 
      & activityAt; 
}; 
  • 在Redis的,我們可以對以上結構的ID的序列化的對象存儲在哈希表中。
  • 爲CREATED_AT創建一個單獨的LISTS(即LIST的名稱將類似於「2013-04-21 13:34:09」),它存儲了映射到它們的ID的LIST。這意味着如果有n個時間戳,我們將有n個列表。
 
     //created at: we append string "created" in beginning of 
     //List names to segregate UPDATE, CREATE and ACTIVITY, 
     //although in given example all timestamps are same for a single row 
     //I think they might be different as well hence the addition of string literal 

     $ redis-cli lpush "created-2013-04-21 13:34:09" 10730268  
     $ redis-cli lpush "created-2013-04-21 13:34:09" 10730267  
     $ redis-cli lpush "created-2013-04-21 13:40:26" 10730266  
     $ redis-cli lpush "created-2013-04-21 13:40:26" 10730265  
     $ redis-cli lpush "created-2013-04-21 13:38:41" 10730264  
     $ redis-cli lpush "created-2013-04-21 13:38:41" 10730263 
  • CREATED_AT時間戳列表的所有名稱都存儲在一個名爲CREATED_AT_LIST主列表。這使我們能夠對CREATED_AT時間戳進行排序。
 
     $ redis-cli lpush CREATED_AT_LIST "2013-08-23 09:34:09" 
     $ redis-cli lpush CREATED_AT_LIST "2013-08-23 09:34:09" 
     $ redis-cli lpush CREATED_AT_LIST "2013-08-23 09:40:26" 
     $ redis-cli lpush CREATED_AT_LIST "2013-08-23 09:40:26" 
     $ redis-cli lpush CREATED_AT_LIST "2013-08-23 09:38:41" 
     $ redis-cli lpush CREATED_AT_LIST "2013-08-23 09:38:41" 

     Above LIST has to be retrieved in client code and strings have to be converted to 
     time format and then sort. 

的updated_at和ACTIVITY_AT的類似的列表可能會導致產生,這將有被映射到它們的ID列表。他們的主名單也創建。

//update at 
    $ redis-cli lpush "updated-2013-04-21 09:44:19" 10730268  
    $ redis-cli lpush "updated-2013-04-21 09:44:19" 10730267  
    $ redis-cli lpush "updated-2013-04-21 09:40:26" 10730266  

    $ redis-cli lpush UPDATED_AT_LIST "2013-08-23 09:44:19" 
    $ redis-cli lpush UPDATED_AT_LIST "2013-08-23 09:44:19" 
    $ redis-cli lpush UPDATED_AT_LIST "2013-08-23 09:40:26" 

    //activity at 
    $ redis-cli lpush "activity-2013-04-21 09:44:19" 10730265  
    $ redis-cli lpush "activity-2013-04-21 09:44:19" 10730264  
    $ redis-cli lpush "activity-2013-04-21 09:40:26" 10730263 


    $ redis-cli lpush ACTIVITY_AT_LIST "2013-08-23 09:44:19" 
    $ redis-cli lpush ACTIVITY_AT_LIST "2013-08-23 09:44:19" 
    $ redis-cli lpush ACTIVITY_AT_LIST "2013-08-23 09:40:26" 

可以對創建的主列表進行排序,並可以相應地檢索ID。一旦我們有了ID,我們就可以查詢HASH表來找回可能被反序列化的序列化對象。

我會嘗試添加上面的工作示例。

+0

感謝這個Nik。感覺Redis給人的感覺是簡潔,因爲它沒有模式,但是當我們進入複雜的排序過程時,所有鬆散的數據開始損害我的大腦,這在SQL中是微不足道的。我會盡力把我的大腦包裹在這一切中,看看它是如何發展的。看起來最難的部分是跟蹤時間,因爲它不斷移動,所以名單需要改變。我們需要永遠知道它的過去,現在還是未來。好帖子雖然 –

+0

@ Mr.BigglesWorth在這方面,REDIS很難使用。但正如我們總是說每種語言一樣,每種技術都在解決一個目的。 REDIS KEY-VALUE數據存儲不是在RDMS的線上設計的。它有它自己的優點和缺點。利用可用的數據結構,可以設計應用程序以實現高吞吐量。 COLUMN,DOCUMENT可以探索NoSQL選項來解決上述問題。 – Nik

+0

我在我的項目中使用REDIS獲得了積極的成果。 – Nik