2017-09-01 367 views
16

查詢內存數據庫表過程中我有一個不斷變化,但很少訪問的SQL表。出在支持高速緩存

表由用戶ID分配,每個用戶在所述表中的多個記錄。

我想保存數據庫資源並將此表更靠近某種內存緩存中的應用程序。

在過程緩存是太內存密集型所以它需要外部的應用程序。

像Redis這樣的關鍵值存儲由於Redis對錶進行序列化和反序列化的開銷而被證明效率低下。

我正在尋找可以將此表(或數據分區)存儲在內存中的東西,但是讓我僅查詢我需要的信息,而無需爲每次讀取序列化和反序列化大塊數據。

是否有任何內存數據庫表中會提供Out of Process,以支持高速緩存查詢?

搜索顯示Apache Ignite可能是一個可能的選項,但我正在尋找更多的建議。

+0

你所說的「進程外的內存數據庫表」呢? – Sameer

+0

你的前端是什麼?一些像Asp.net這樣的託管環境具有輸出緩存或中間件緩存功能,如果符合您的需求,您還可以查看Elastic Search。我存儲的數據爲 –

回答

9

因爲它是外的過程,它所要做的序列化和反序列化。您所關心的問題是如何減少序列化/反分類工作。如果您使用Redis'STRING類型,則無法減少這些工作。

但是,您可以使用HASH來解決問題:將您的SQL表映射到HASH

假設您有以下表格:person: id(varchar), name(varchar), age(int),您可以將人物id作爲關鍵字,並以nameage作爲字段。當你想搜索的人的名字,你只需要得到名稱字段(HGET person-id name),其它字段將不會被反序列化。

+1

,每個用戶需要緩存很多行。理想情況下,我想用UserId和TagId查詢。每個用戶都有許多不同的行,TagId不同。如果我可以從內存表中執行SQL類型查詢並說出UserId = y和TagId = x,並且只返回包含數據的一行,那將是理想的。這就是我們如何使用SQL來存儲和檢索當前數據。 SQL hekaton聽起來可能是可能的,但成本很高。 – SetiSeeker

4

對於您來說,Ignite確實是一種可行的解決方案,因爲您可以通過使用內部二進制表示來訪問對象字段來優化序列化/反序列化開銷。你可以參考這個文檔頁面,瞭解更多信息:https://apacheignite.readme.io/docs/binary-marshaller

還訪問開銷可通過禁用優化副本上讀選項https://apacheignite.readme.io/docs/performance-tips#section-do-not-copy-value-on-read

通過用戶ID數據的搭配,也可以通過Ignite:https://apacheignite.readme.io/docs/affinity-collocation

2

正如@for_stack說,Hash將非常適合你的情況。

你說過,每個用戶在db中索引的行數都是user_idtag_id。所以它是(user_id,tag_id)唯一指定一行。每一行的功能依賴於這個元組,你可以使用元組作爲HASH KEY。

例如,如果你想保存行(USER_ID,TAG_ID,用戶名,年齡),該值( 「123456」, 「FDSA」, 「安區」,20)到Redis的,你可以這樣做:

HMSET 123456:FDSA username "gsz" age 30 

當您想查詢與USER_ID和TAG_ID的用戶名,你可以這樣做:

HGET 123456:FDSA username 

所以每一個散列鍵將是user_idtag_id組合,如果你想關鍵更具人性化,您可以添加前綴字符串,例如「USERINFO」。例如:USERINFO:123456:FDSA

但是如果你只想查詢一個user_id並獲得所有具有這個user_id的行,上面的這個方法是不夠的。

你可以建立在Redis的的secondary indexes你HASH。

如上所述,我們使用user_id:tag_id作爲HASH密鑰。因爲它可以唯一指向一行。如果我們想查詢關於一個user_id的所有行。

我們可以使用sorted set建立一個二級索引,以便哈希存儲有關此user_id的信息。

我們可以在SortedSet的補充一點:

ZADD user_index 0 123456:FDSA 

如上所述,我們設置了memberstring of HASH key,並設置score爲0和規則是,我們應該將所有評分在這個zset到0,然後我們可以使用字典順序來進行範圍查詢。請參閱zrangebylex

E.g.我們想要得到的所有行約USER_ID 123456,

ZRANGEBYLEX user_index [123456 (123457 

這將返回所有其前綴是123456的散列鍵,然後我們使用這個字符串作爲散列關鍵字和hget或hmget檢索信息來源,我們想要的東西。

[表示包含性,(表示排他性。以及爲什麼我們使用123457?這很明顯。因此,當我們想要獲取具有user_id的所有行時,我們應該指定使user_id字符串的最左端字符的ascii值加1的上限。

有關lex索引的更多信息,請參閱上文提到的文章。

1

對於一個只讀工作負載MySQL MEMORY engine應該可以正常工作(編寫DML鎖定整個表)。這樣你就不需要改變你的數據檢索邏輯。

或者,如果您可以更改數據檢索邏輯,那麼Redis也是一個選項。要增加@GuangshengZuo描述的內容,有ReJSONRedis可動態加載的模塊(用於Redis 4+),它在Redis之上實現文檔存儲。它可以進一步放寬網絡上來回編組大型結構的要求。

1

只需6原則(這是我收集here),它是一個SQL頭腦的人對自己適應Redis的方法非常簡單。簡單地說,他們是:

  1. 最重要的是,不要怕產生大量的鍵值對。所以請隨意將表格的每一行存儲在不同的密鑰中。
  2. 使用Redis的哈希映射數據類型
  3. 表鍵從下表的主鍵的值由分隔的名稱(如‘:’)
  4. 商店剩餘的字段作爲哈希
  5. 當你想查詢單列,直接形成鍵,當你想要查詢各種檢索其結果
  6. ,使用野生字符「*」對你的關鍵。但請注意,掃描鍵會中斷其他Redis進程。所以如果你真的需要使用這種方法。

該鏈接只是給出了一個簡單的表格示例以及如何在Redis中對其進行建模。遵循這6條原則,您可以繼續像普通表一樣思考。 (當然,如果沒有一些不那麼相關概念CRUD,約束,關係等)使用內存緩存和Redis的組合對MYSQL的頂部