Redis在多个键上的复杂排序。构建活动源

时间:2014-07-16 21:25:05

标签: sql sorting redis schema nosql

我有一个包含数据列的表,这些数据列在SQL中用于按Id排序事件列表。我们使用它在我们的网站上显示这些事件的活动源,但是想将所有这些移动到redis。我们已经通过很多方式来做这样的事情了,但是我想在这里把它们从社区中反弹出来以获得一些反馈。这是当前的列。

enter image description here

将会有另一个哈希表,其中包含所有事件数据。然而,事情变得棘手的是时机,并且需要多种排序。第一个问题是我们系统中的事件既是未来的,也是现在的和过去的。因此,我们需要能够通过获取当前时间进行排序,并查看现在,未来和已经完成的内容。然而,除此之外,我们还有其他colums也可以排序。多重排序是事情变得多毛的地方。以下是一些多种类型:

是特色吗? (布尔值)=它是否为特色事件,如果是,它应该显示在我们的Feed的顶部而不管时间。

现在发生了吗? (unixtimestamp)=检查当前时间并获取现在所有事情的列表并列出ID。

过去了吗? (unixtimestamp)=检查当前时间以查看其是否已完成并列出ID

是否将来(unixtimestamp)=检查当前时间以查看其是否稍后发生并列出ID

当您考虑到事件属于其他用户时,事情变得更加疯狂。因此,我们还必须采用这些想法并通过USER ID对其进行过滤,然后对其进行排序。我们不喜欢为每个用户提供数千个排序集的想法。那你们怎么会这样复杂的流?

1 个答案:

答案 0 :(得分:2)

在Redis中可视化关系数据并不简单。与讨论中的示例一样,存储具有不同排序选项的数据是一项挑战。在第一个实例中可能的解决方案可能效率不高,但应该进行性能测试以得出最终结论。

我建议实施此类解决方案:

每列应映射到Redis中的LIST。选择LIST是因为可以重复输入,否则可以使用SET。

在上面的示例中,我们可以使用以下LIST:

ID,ACTIVITY_TYPE,ACTIVITY_ID,LISTING_TYPE,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检索数据,则可以使用SORT命令对SORTED_CREATED_AT列表进行排序。可以在HASH CREATED_AT_HASH中搜索返回的CREATED_AT以获取索引。使用此INDEX,我们可以获得所有列的值。这假设id时间戳是唯一的。如果时间戳很常见,那么我们必须为每个时间戳创建单独的LISTS并存储映射到时间戳的所有索引。

您可以采取的其他方法是将要存储的数据映射到数据结构并创建其对象。将这些创建的对象以序列化字符串形式存储在REDIS中,以防止ID或时间戳。

将关系数据库映射到REDIS没有直接的方法。也许你可以探索其他NoSql选项。但是,如果REDIS是您接着尝试上述方法,或者使用REDIS中可能的数据结构(字符串,列表,集合,哈希)进行创新。

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

SERIALIZED OBJECTS

考虑到上述解决方案可能存在的问题,创建一个datatstructre,它映射给定的数据并将它们以字符串序列化格式存储在不同的键中,这似乎更合理。

(C ++ struct的一个例子)

 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中,我们可以在HASH表中针对ID存储上述struct的序列化对象。
  • 为CREATED_AT创建一个单独的LISTS(即LIST的名称将类似于“2013-04-21 13:34:09”),它存储映射到它们的ID的LIST。这意味着如果有n个时间戳,我们将有n个LISTS。
       //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时间戳LIST的所有名称都存储在名为CREATED_AT_LIST的主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的LISTS,其具有映射到它们的ID的LIST。还创建了他们的主列表。

   //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表以获取可以反序列化的序列化对象。

我会尝试添加上面的工作示例。