Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Poprzednia wersja
Nowa wersja
Poprzednia wersja
pl:dydaktyka:ztb:2010:projekty:nosql_casandra:start [2010/06/29 23:23]
ztb2010
pl:dydaktyka:ztb:2010:projekty:nosql_casandra:start [2019/06/27 15:50] (aktualna)
Linia 3: Linia 3:
 Cassandra jest magazynem klucz-wartość. Łączy ona rozproszone technologie Dynamo oraz model danych z Google BigTable. Podobnie ja Dynamo zakłada, iż po odpowiednio długim czasie bez nowych zmian wszystkie repliki bedą identyczne, natomiast tak jak BigTable dostarcza modele przypominające tabele. Cassandra jest magazynem klucz-wartość. Łączy ona rozproszone technologie Dynamo oraz model danych z Google BigTable. Podobnie ja Dynamo zakłada, iż po odpowiednio długim czasie bez nowych zmian wszystkie repliki bedą identyczne, natomiast tak jak BigTable dostarcza modele przypominające tabele.
  
-Cassandra została ​otawra ​przez Facebooka w 2008 roku. Aktualnie rozwijana jest przez Apache oraz współpracowników z różnych firm.+Cassandra została ​otwarta ​przez Facebooka w 2008 roku. Aktualnie rozwijana jest przez Apache oraz współpracowników z różnych firm. 
 + 
 +====== Instalacja i Konfiguracja ====== 
 + 
 + ​Poniższy opis dotyczy instalacji i konfiguracji na systemie linuksowym a konkretniej na Debianie. W innych systemach operacyjnych kroki te przebiegają analogicznie. Debian został wybrany ze względu na częste wykorzystywanie go jako OS dla serwera baz danych. 
 + 
 +===== Apache Thrift ===== 
 + 
 +Thrift wykorzystywany jest do tworzenie skalowalnych,​ multiplatformowych usług webowych. Generuje klienty RPC w dowolnym języku (z pośród C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, OCaml) które mogą komunikować się z tym samym serwerem RPC. Dzięki takiemu podejściu Cassandra może być dostępna w łatwy i szybki sposób z pośród wielu języków programowania. 
 + 
 + 
 +instalacja dodatkowych pakietów na debianie 
 + 
 +    * libboost-all-dev 
 +    * bison 
 +    * flex 
 + 
 +konfiguracja (bez wsparcia dla ruby): 
 + 
 +<​code="​bash">​ 
 +./configure --disable-gen-rb --without-ruby 
 +make 
 +make install 
 +</​code>​ 
 + 
 +do poprawnego działania z pythonem należy jeszcze ręcznie zainstalować biblioteki:​ 
 +<​code>​ 
 +cd lib/py 
 +python setup.py install 
 +</​code>​ 
 + 
 +linki:\\ 
 +tutorial do thrifta [[http://​wiki.apache.org/​thrift/​Tutorial]]\\ 
 + 
 +===== Cassandra ===== 
 + 
 +najprostsza instalacja polega na rozpakowaniu tarballa z plikami cassandry i skonfigurowaniu ścieżek dostępu do logów i do danych w pliku conf/​storage-conf.xml 
 + 
 +Jeżeli nie chcemy zmieniać defaultowych ścieżek wystarczy że stworzymy poniższe katalogi tak aby odpowiadały tym zdefiniowanym:​ 
 + 
 +<​code="​bash">​ 
 + sudo mkdir -p /​var/​log/​cassandra 
 + sudo chown -R `whoami` /​var/​log/​cassandra 
 + sudo mkdir -p /​var/​lib/​cassandra 
 + sudo chown -R `whoami` /​var/​lib/​cassandra 
 +</​code>​ 
 + 
 +Uruchmienie pojedynczego węzła: 
 + 
 +<​code="​bash">​ 
 +bin/​cassandra -f  # -f loguje na stdout 
 +</​code>​ 
 + 
 +testowanie węzła poprzez konsole cli: 
 + 
 +<​code="​bash">​ 
 +bin/​cassandra-cli --host localhost --port 9160 
 +</​code>​
  
 ====== Model ====== ====== Model ======
Linia 226: Linia 283:
 </​code>​ </​code>​
  
-Jak już wspomnieliśmy wyżej każda kolumna musi zawierać pole timestamp. Pierwszą rzeczą którą robimy jest stworzenie ​ zmiennej przechowującej czas utworzenia. Jest ona używana do rozwiązywania konfliktów gdy mamy kilka podobnych kluczy. Dlatego nie należy nigdy ustawiać takich samych wartości tego pola; najczęściej stosuje się liczbę milisekund które upłynęły od roku 1970. +Jak już wspomnieliśmy wyżej każda kolumna musi zawierać pole **timestamp**. Pierwszą rzeczą którą robimy jest stworzenie ​ zmiennej przechowującej czas utworzenia. Jest ona używana do rozwiązywania konfliktów gdy mamy kilka podobnych kluczy. Dlatego nie należy nigdy ustawiać takich samych wartości tego pola; najczęściej stosuje się liczbę milisekund które upłynęły od roku 1970. 
 W następnej linii tworzymy mapę w której będziemy umieszczać wiersze. ​ Kluczem w naszej mapie będzie String który jest nazwą ColumnFamily czyli naszą „tabelą” zdefiniowaną wcześniej w pliku konfiguracyjnym. Wartością mapy będzie lista specjalnej struktury mogącej przechowywać Columnę lub SuperColumnę,​ u nas to będą jak już wcześniej wspomnieliśmy Columny czyli konstrukcja przechowująca trzy pola. W następnej linii tworzymy mapę w której będziemy umieszczać wiersze. ​ Kluczem w naszej mapie będzie String który jest nazwą ColumnFamily czyli naszą „tabelą” zdefiniowaną wcześniej w pliku konfiguracyjnym. Wartością mapy będzie lista specjalnej struktury mogącej przechowywać Columnę lub SuperColumnę,​ u nas to będą jak już wcześniej wspomnieliśmy Columny czyli konstrukcja przechowująca trzy pola.
  
 W kolejnych ​ liniach tworzymy ​ instacje naszych Column: country, population i area oraz wstawiamy do nich odpowiednie wartości przesłane jako argumenty funkcji, a następnie każdą Columne dodajemy do listy. W kolejnych ​ liniach tworzymy ​ instacje naszych Column: country, population i area oraz wstawiamy do nich odpowiednie wartości przesłane jako argumenty funkcji, a następnie każdą Columne dodajemy do listy.
  
-Na końcu używamy metody batch_insert do zapisania wszystkich danych jednorazowo w bazie. W przypadku gdybyśmy chcieli zapisać tylko pojedynczą Columne należy użyć metody insert. Jako parametry dla metody batch_insert wykorzystujemy klucz naszej tabeli czyli miasto do którego odnoszą się wszystkie dane zapisane w strukturze Column, nazwę schematu oraz mapę o której mówiliśmy wcześniej. Ostatnim parametrem jest tzw. ConsistencyLevel który jest wykorzystywany przy wszystkich operacjach zapisu oraz czytania z bazy i wskazuje kiedy żądanie klienta zostaje wykonane. Typ ALL mówi, że zapis powinien się odbyć przed udzieleniem odpowiedzi klientowi. Dokładne znaczenie każdego ​ parametru jest wyjaśnione na stronie wiki Cassandry.+Na końcu używamy metody ​**batch_insert** do zapisania wszystkich danych jednorazowo w bazie. W przypadku gdybyśmy chcieli zapisać tylko pojedynczą Columne należy użyć metody ​**insert**. Jako parametry dla metody batch_insert wykorzystujemy klucz naszej tabeli czyli miasto do którego odnoszą się wszystkie dane zapisane w strukturze Column, nazwę schematu oraz mapę o której mówiliśmy wcześniej. Ostatnim parametrem jest tzw. **ConsistencyLevel** który jest wykorzystywany przy wszystkich operacjach zapisu oraz czytania z bazy i wskazuje kiedy żądanie klienta zostaje wykonane. Typ **ALL** mówi, że zapis powinien się odbyć przed udzieleniem odpowiedzi klientowi. Dokładne znaczenie każdego ​ parametru jest wyjaśnione na stronie wiki Cassandry ​[[http://​wiki.apache.org/​cassandra/​API#​ConsistencyLevel]].
  
 ==== Odczyt z bazy ==== ==== Odczyt z bazy ====
Linia 264: Linia 321:
 </​code>​ </​code>​
  
-KeyRange jest używane do wyspecyfikowania jaki zakres kluczy chcemy wyciągnąć z bazy. W naszym przypadku w rzeczywistości nie definiujemy zakresu a jedynie ilość wierszy które chcemy wczytać z bazy, dlatego w konstruktorze przekazujemy liczbę 3 co odpowiada trzem wierszom.+**KeyRange** jest używane do wyspecyfikowania jaki zakres kluczy chcemy wyciągnąć z bazy. W naszym przypadku w rzeczywistości nie definiujemy zakresu a jedynie ilość wierszy które chcemy wczytać z bazy, dlatego w konstruktorze przekazujemy liczbę 3 co odpowiada trzem wierszom.
  
-SliceRange jest strukturą przechowującą informacje o zakresie, kolejności oraz ilości dla zapytania które zwraca wiele kolumn. Można ją utożsamiać z poleceniami LIMIT oraz ORDER BY z języka SQL. Metoda setStart ustawia kolumnę ​ od której powinniśmy zacząć pobieranie danych. Pusta tablica byte oznacza rozpoczęcie od pierwszej kolumny. Metoda setFinish ustawia Columne na której powinniśmy skończyć pobieranie danych. Pusta tablica byte oznacza odzyskanie wszystkich Column dopóki nie uzyskamy wartości count. +**SliceRange** jest strukturą przechowującą informacje o zakresie, kolejności oraz ilości dla zapytania które zwraca wiele kolumn. Można ją utożsamiać z poleceniami LIMIT oraz ORDER BY z języka SQL. Metoda ​**setStart** ustawia kolumnę ​ od której powinniśmy zacząć pobieranie danych. Pusta tablica byte oznacza rozpoczęcie od pierwszej kolumny. Metoda ​**setFinish** ustawia Columne na której powinniśmy skończyć pobieranie danych. Pusta tablica byte oznacza odzyskanie wszystkich Column dopóki nie uzyskamy wartości count. 
-SliceRange posiada jeszcze jedną funkcje setCount której nie użyliśmy tutaj, a oznaczającą liczbę Column które chcemy zwrócić – coś jak LIMIT w SQL.+SliceRange posiada jeszcze jedną funkcje ​**setCount** której nie użyliśmy tutaj, a oznaczającą liczbę Column które chcemy zwrócić – coś jak LIMIT w SQL.
  
-Następnie dzięki SlicePredicate ustawiamy dane które chcemy odzyskać, u nas jest to zdefiniowany wcześniej przy użyciu SliceRange pewien zakres kolumn.+Następnie dzięki ​**SlicePredicate** ustawiamy dane które chcemy odzyskać, u nas jest to zdefiniowany wcześniej przy użyciu SliceRange pewien zakres kolumn.
  
-W końcu dzięki metodzie get_range_slices wczytujemy dane i przypisujemy je do listy obiektów KeySlice. Jest to obiekt przechowujący ​ odzyskane wiersze zawierający klucz i kolumny należące do danego wiersza.+W końcu dzięki metodzie ​**get_range_slices** wczytujemy dane i przypisujemy je do listy obiektów ​**KeySlice**. Jest to obiekt przechowujący ​ odzyskane wiersze zawierający klucz i kolumny należące do danego wiersza.
  
  
Linia 298: Linia 355:
 Otrzymany rezultat wygląda następująco:​ Otrzymany rezultat wygląda następująco:​
  
-Dodaje miasta +  ​Dodaje miasta 
-Wyciągam dane z bazy:+  Wyciągam dane z bazy:
   Key: '​Warszawa'​   Key: '​Warszawa'​
   name: '​area',​ value: '​51724',​ timestamp: 1276876711965   name: '​area',​ value: '​51724',​ timestamp: 1276876711965
Linia 504: Linia 561:
 </​code>​ </​code>​
  
-===== Hello World w pythonie =====+====== Hello World w pythonie =====
 + 
 +===== Testowanie cassandry w pythonie ===== 
  
   * generujemy interfejs do cassandry   * generujemy interfejs do cassandry
Linia 524: Linia 584:
   * Możemy przetestować jego działanie:   * Możemy przetestować jego działanie:
  
-<path="​bash">​+<code="​bash">​
 ./​Cassandra-remote -h localhost:​9160 describe_version ./​Cassandra-remote -h localhost:​9160 describe_version
 ./​Cassandra-remote -h localhost:​9160 describe_keyspace Keyspace1 ./​Cassandra-remote -h localhost:​9160 describe_keyspace Keyspace1
 </​code>​ </​code>​
  
-  * Hello World+===== implementacja ​Hello World =====
  
-wystarczy skopiować kod z Cassandra-remote ​i odpowiednio użyć go kodzie programu ​:)+Została wykonana na podstawie wygenerowanego pliku Cassandra-remote
 + 
 +Konfiguracja ​pliku conf/​storage-conf.xml 
 +<​code="​xml">​ 
 +    <​Keyspace Name="​Dictionary">​ 
 +      <​ColumnFamily Name="​Words"​ 
 +                    ColumnType="​Super"​ 
 +                    CompareWith="​UTF8Type"​ 
 +                    CompareSubcolumnsWith="​UTF8Type"​ 
 +                    RowsCached="​10000"​ 
 +                    KeysCached="​50%"​ 
 +                    Comment="​A column family with supercolumns,​ whose column and subcolumn names are UTF8 strings"/>​ 
 +      <​ReplicaPlacementStrategy>​org.apache.cassandra.locator.RackUnawareStrategy</​ReplicaPlacementStrategy>​ 
 + 
 +      <!-- Number of replicas of the data --> 
 +      <​ReplicationFactor>​1</​ReplicationFactor>​ 
 + 
 +      <​EndPointSnitch>​org.apache.cassandra.locator.EndPointSnitch</​EndPointSnitch>​ 
 +    </​Keyspace>​ 
 +</​code>​ 
 + 
 +<​code="​python">​ 
 +#​!/​usr/​bin/​env python 
 + 
 +import sys 
 +import time 
 +import pprint 
 +from urlparse import urlparse 
 +from thrift.transport import TTransport 
 +from thrift.transport import TSocket 
 +from thrift.transport import THttpClient 
 +from thrift.protocol import TBinaryProtocol 
 + 
 +import Cassandra 
 +from ttypes import * 
 + 
 +pp = pprint.PrettyPrinter(indent = 2) 
 +host = '​localhost'​ 
 +port = 9160 
 +uri = ''​ 
 +framed = False 
 +http = False 
 +argi = 1 
 + 
 +if len(sys.argv)>​1 and sys.argv[argi] == '​-h'​: 
 +  parts = sys.argv[argi+1].split(':'​)  
 +  host = parts[0] 
 +  port = int(parts[1]) 
 +  argi += 2 
 + 
 + 
 +if http: 
 +  transport = THttpClient.THttpClient(host,​ port, uri) 
 +else: 
 +  socket = TSocket.TSocket(host,​ port) 
 +  if framed: 
 +    transport = TTransport.TFramedTransport(socket) 
 +  else: 
 +    transport = TTransport.TBufferedTransport(socket) 
 +protocol = TBinaryProtocol.TBinaryProtocol(transport) 
 +client = Cassandra.Client(protocol) 
 +transport.open() 
 + 
 + 
 +class Dict: 
 +    def translate(self,​ lang_from, word_from, lang_to): 
 +        colPath = ColumnPath("​Words",​ lang_from, lang_to) 
 +        try: 
 +            ret = client.get('​Dictionary',​ word_from, colPath, ConsistencyLevel.ONE,​) 
 +            if ret: 
 +                print "​translate " + word_from + " (" + lang_from + " - " +lang_to+"​):​ " + ret.column.value 
 +        except NotFoundException:​ 
 +            print "there is no translate for " + word_from + " (" + lang_from + " - " +lang_to+"​)"​ 
 + 
 +    def getAllTranslates(self,​ lang_from, word_from):​ 
 +        colParent = ColumnParent("​Words",​ lang_from) 
 +        slPred = SlicePredicate(None,​ SliceRange('',''​)) 
 +        ret = client.get_slice('​Dictionary',​ word_from, colParent, slPred, ConsistencyLevel.ONE,​) 
 +        print "all transalte for word " + word_from + " (" + lang_from + "​):"​ 
 +        for item in ret: 
 +            print " ​ translate " + word_from + " (" + lang_from + " - " +item.column.name+"​):​ " + item.column.value 
 +         
 + 
 +    def addWord(self,​ lang_from, lang_to, word_from, word_to): 
 +        colPath = ColumnPath("​Words",​ lang_from, lang_to) 
 +        timestamp = int(time.time()) 
 +        ret = client.insert('​Dictionary',​ word_from, colPath, word_to, timestamp, ConsistencyLevel.ONE,​) 
 +        if ret is None: 
 +            print "​inserted word "​+word_from+"​ ("​+lang_from+"​)"​ + " - " +word_to+"​ ("​+lang_to+"​)"​ 
 +        else: 
 +            print ret 
 + 
 +    def removeWord(self,​ lang_from, lang_to, word_from):​ 
 +        colPath = ColumnPath("​Words",​ lang_from, lang_to) 
 +        timestamp = int(time.time()) 
 +        ret = client.remove('​Dictionary',​ word_from, colPath, timestamp, ConsistencyLevel.ONE,​) 
 +        if ret is None: 
 +            print "​removed word " + word_from + " ("​+lang_from+"​ - "​+lang_to+"​)"​ 
 + 
 + 
 + 
 +dic = Dict() 
 +dic.addWord("​pl","​en","​dom","​home"​) 
 +dic.addWord("​pl","​de","​dom","​house"​) 
 +dic.addWord("​pl","​cz","​dom","​holpiczka"​) 
 + 
 +print 
 + 
 +dic.removeWord("​pl","​de","​dom"​) 
 + 
 +print  
 + 
 +dic.translate("​pl",​ "​dom",​ "​en"​) 
 +dic.translate("​pl",​ "​dom",​ "​cz"​) 
 +dic.translate("​pl",​ "​dom",​ "​de"​) 
 + 
 +print 
 + 
 +dic.getAllTranslates("​pl","​dom"​) 
 + 
 +transport.close() 
 +</​code>​
  
 ====== Wady oraz zalety ====== ====== Wady oraz zalety ======
Linia 549: Linia 730:
   * Odporna na uszkodzenia – dane są automatycznie replikowane do wielu węzłów. Zepsute węzły mogą być zastąpione bez żadnego przestoju.   * Odporna na uszkodzenia – dane są automatycznie replikowane do wielu węzłów. Zepsute węzły mogą być zastąpione bez żadnego przestoju.
   * Elastyczna – wydajność zapisywania i odczytywania wzrasta liniowo wraz z dodawaniem nowych maszyn bez żadnego przestoju lub przerw w działaniu aplikacji.   * Elastyczna – wydajność zapisywania i odczytywania wzrasta liniowo wraz z dodawaniem nowych maszyn bez żadnego przestoju lub przerw w działaniu aplikacji.
 +  * Wytrzymała - Cassandra jest odpowiednia dla aplikacji, które nie mogą sobie pozwolić na utratę danych, nawet gdy całe centrum danych padnie
 +  * "​Sprawdzona"​ - mimo wciąż niezbyt wielkiej popularności z Cassandry korzystają takie firmy jak Digg, Facebook, Twitter, Reddit, Rackspace, Cloudkick, Cisco, SimpleGeo, Ooyala, OpenX, i wiele innych posiadających duże zbiory danych. Największy klaster danych zawiera ponad 100TB danych na ponad 150 urządzeniach.
   ​   ​
 +
 ==== Pozostałe możliwości Cassandry ==== ==== Pozostałe możliwości Cassandry ====
  
pl/dydaktyka/ztb/2010/projekty/nosql_casandra/start.1277846624.txt.gz · ostatnio zmienione: 2019/06/27 15:56 (edycja zewnętrzna)
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0