2013年10月9日 星期三

Riak實戰(3) - Link Walking

Riak中有個頗強大的功能,叫做link walking。但是在介紹這個功能之前先讓我們來談談graph DB。


什麼是Graph DB?

在台灣或許不多人接觸過graph db,但是希望大家能多少了解一下他的設計概念及使用情境。
Graph DB主要的訴求就是要解決傳統關聯式資料庫所無法處理的關係搜尋。在Graph DB的架構下,每筆資料(document形式)就是一個node,node之間可以存在edge,這個edge儲存的就是node間的關係,如下圖:

(來源:http://readwrite.com/2011/04/20/5-graph-databases-to-consider)
這樣的架構不只直覺,也克服了某些特定架構下的搜尋效能問題。舉例來說,如果你希望搜尋的是「A的朋友的朋友的親人」,這樣的架構在傳統的關聯式資料庫的實作就很複雜,因為人與人之間的關係是多對多的,一定會有個table去儲存這些關係。在我們所提到的「A的朋友的朋友的親人」的使用情境下,我們至少會做 6 次的join!( A->關係->朋友->關係->朋友->關係->親人)
這樣操作並不直覺,效能也不甚理想,所以因應這種需求的Graph DB就出現了,例如:Neo4jTitanInfinite。當然除了這編列的三種以外,還有許多graph db,甚至有些是為了生物學或特定科學領域而誕生的。



Riak 的 Link Walking

我個人覺得 Riak 為這個機制的命名實在非常生動,怎說呢?
Riak在各筆資料之間可以建立一個「單向」的 Link,透過許多link的彼此連結,我們可以再這些資料節點上「散步(walking)」,例如:
GET localhost:8091/riak/people/kevinshu/_,friend,_/_,friend,_/_,relative,_/

從上面的例子中做的事是:

  1. 我們先進入 kevinshu 這個節點
  2. 再「走」到 kevinshu 的朋友
  3. 再「走」到 kevinshu 的朋友的朋友
  4. 再「走」到 kevinshu 的朋友的朋友的親人

於是這樣傳回的結果就是「 kevinshu 的朋友們的朋友們的所有親人們」,一個看似複雜的關係就這樣透過 Link Walking 找出來了。



Link Walking 的建立與query


建立Link:

$ curl -v -XPUT http://127.0.0.1:8091/riak/people/timoreilly \
  -H 'Link: </riak/people/dhh>; riaktag="friend"' \
  -H "Content-Type: text/plain" \
  -d 'I am an excellent public speaker.'
以上的範例除了建立了 davethomas 和 timoreilly 的link外,也用 "riaktag" 來定義這段關係,如 "friend", "relative", "employee"


Query:

$ curl -v http://127.0.0.1:8091/riak/people/timoreilly/{{bucket}},{{tag}},{{Keep}}

  • Bucket: 指定某個bucket,如果這個值是 _ (underscore),則比對所有的 bucket
  • Tag: 指定 riaktag 的值,如果這個值是 _ (underscore),則比對所有的 tag
  • Keep: 0 或 1,是否回傳這個階段的搜尋結果。以一開始提到的使用情境來說,如果我只也想知道 kevinshu 的「朋友」和「朋友的朋友」是誰,我就必須在這兩個query的  Keep 值定為 1。
    如果這個值是 _ (underscore),除了在最終階段的 query 視為 1 外,中間層的query則使用預設值 0 (不回傳)。這樣講不容易懂,直接看例子:
    /riak/people/kevinshu/_,friend,_(視為0)/_,friend,_(視為0)/_,relative,_(視為1)/



Reference


  • http://docs.basho.com/riak/latest/dev/using/link-walking/
  • http://neo4j.tw/understand_graph