2012-10-13 37 views
2

我知道這個問題在stackoverflow中多次被詢問。 我發佈這個問題,以找出什麼將是我的設計的最佳選擇。 我有我的工作細節以下架構。在內存關係數據庫

_unique_key  varchar(256) NULL 
_job_handle  varchar(256) NULL 
_data    varchar(1024) NULL 
_user_id   int(11) NULL 
_server_ip   varchar(39) NULL 
_app_version  varchar(256) NULL 
_state    int(11) NULL 
_is_set_stopped bool 

我們正在做此表上進行了什麼操作:

  1. 因爲我們將有一個更新,並在此表10選擇查詢每個作業。所以我們需要高頻率進行讀寫。
  2. 有其通過做濾波器操縱此表中的許多應用:
    1. _unique_key
    2. _STATE
    3. is_set_stopped
    4. _USER_ID
  3. _data字段大小從5KB變化到1 MB基於應用程序和用戶的類型。
  4. 應用程序可以更新選擇性屬性。

解決方案,我們認爲:

MySQL的InnoDB的

我認爲MySQL將沒有足夠的規模,由於高讀寫需求。

的MySQL在存儲器表

問題的這種解決方案是

  1. 它不支持動態字段大小。 MEMORY表使用固定長度的行存儲格式。可變長度類型(如VARCHAR)使用固定長度進行存儲。來源http://dev.mysql.com/doc/refman/5.0/en/memory-storage-engine.html
  2. 選擇....更新它將鎖定整個表。我不知道這會是一個問題。

Redis的

Redis的樣子喜歡一個不錯的選擇。但我認爲我的表對於鍵值緩存服務器並不好。

  1. 它只支持非常讓我們的數據類型集。我只能在列表中存儲字符串。我需要將字段存儲爲JSON或其他格式。
  2. 如果客戶想要更新特定屬性,他們需要下載完整的值,然後解析對象並重新映射到服務器。 可能是我錯了有沒有辦法做到這一點?
  3. 基於價值的過濾是不可能的。 可能是我錯了有沒有辦法做到這一點?

MySQL的InnoDB的上TMPFS文件系統

此看好。但是,在內存表中,它的規模不會與Redis或MySQL相似。

+1

什麼是您的實際讀/寫速度要求? –

+0

@Joachim Isaksson。 當前需求是1380每秒讀取和寫入一個完整的行,每秒6900讀取is_set_stopped列。 隨着服務器上作業數量的增加,計數將會增加。 –

+0

爲什麼你認爲MySQL和InnoDB不能相關?你需要調好它...... –

回答

4

在這個問題中,您將原始性能(即效率)與可伸縮性混爲一談。他們是不同的概念。在InnoDB和內存引擎之間,InnoDB可能是最具可擴展性的。 InnoDB支持多版本併發控制,有大量的優化來處理爭用,所以它會比內存引擎更好地處理併發訪問。即使在某些I/O限制的情況下它可能會比較慢。

Redis是一個單線程服務器。所有的操作都是序列化的。它具有零可擴展性。這並不意味着效率低下。相反,它可能會支持MySQL(由於其基於epoll的事件循環)和更多流量(由於其非常有效的無鎖實現和內存數據結構)而產生的更多連接。

要回答你的問題,我會試着用InnoDB來試試MySQL。如果它被正確配置(沒有同步提交,足夠的緩存等等),它可以保持良好的吞吐量。而不是在tmpfs上運行它,我會考慮SSD硬件。

現在,如果您更喜歡使用Redis(它不是​​一個關係型商店btw),您當然可以做到這一點。沒有必要系統地序列化/反序列化您的數據。如果您可以預見所有訪問路徑並找到適合的數據結構,過濾的確是可能的。

例如:每個作業

  • 一個哈希對象。關鍵是_unique_key。散列的字段應與您的關係表的列對應。
  • 每狀態值
  • 一組
  • 2套每用戶ID值

is_set_stopped

  • 一組對於每個作業插入,需要管道下面的命令:

    HMSET job:AAA job_handle BBB data CCC user_id DDD server_ip EEE app_version FFF state GGG is_set_stopped HHH 
    SADD state:GGG AAA 
    SADD is_set_stopped:HHH AAA 
    SADD user_id:DDD AAA 
    

    你可以輕鬆更新任何單獨的字段,只要您保持相應的設置。

    您可以通過交集集來執行過濾查詢。例如:

    SINTER is_set_stopped:HHH state:GGG 
    

    使用Redis時,瓶頸將可能是網絡,特別是在數據字段很大的情況下。我希望你的工作比1MB的工作多5KB。例如,1 MB對象的1000次寫入代表8 GBits/s,可能比您的網絡能承受的更多。 Redis和MySQL都是如此。

  • +0

    啊哈謝謝。我從來沒有想過網絡限制。 –

    1

    我建議postgresql比mysql更有能力(對複雜查詢和數據類型有更多的功能和更好的支持),並且有很多調優選項。

    如果您給postgresql足夠的內存並調整參數,它會將所有內容緩存在內存中。

    或者,您也可以在tmpfs上使用它,如果這是您的首選項,並使用流式複製到硬盤上的磁盤數據庫。

    流式複製異步,接收和fsync上有3種操作模式。如果您使用第一個異步服務器,則不必等待複製服務器上的磁盤同步,因此使用tmpfs時,任何更新都將非常快速。

    由於您似乎還有很多文本字段,所以其他功能可能會有所幫助,postgresql可以在一行上存儲文本搜索向量,並且您可以添加一個索引並通過觸發器對其進行更新,連接內容爲所有你正在搜索的行。當你在多列上進行文本搜索時,這會給你帶來難以置信的性能提升,而不是任何你可能用mysql編寫的方式。

    無論數據庫的使用

    幽州_data爲varchar [1024],你還說它含有5K至1M數據?這實際上是一個blob?即使它的長度錯誤,mysql也不支持長度超過65535字節的varchar字段!我想這不會像其他行那樣更新,將它分成兩個表格是明智的,一個是靜態數據,另一個是動態數據,以最大限度地減少磁盤訪問。