PHP e CASSANDRA
Ivan Rosolen
Graduado em Sistemas de Informação
Pós-graduado em Gerência de Projetos
Desenvolvedor a 10+ anos
Autor de vários PHPT (testes para o PHP)

Gerente de Projetos na

Arizona
CASSANDRA
O que? De onde? Quem?
NoSQL
Amazon Dynamo
Google Big Table

Facebook
Pontos Positivos
- Alta escalabilidade e disponibilidade
- Sem um único ponto de falha
- Baseado em colunas (wide-column)
- Rendimento de escrita muito alto
- Rendimento de leitura bom
- Consistência ajustável e suporte a replicação
Colunas
- Modelar os dados do jeito que você vai buscar, desnormalizado

[KeySpace][ColumnFamily][Key][SuperColumn][SubColumn]
Database = [KeySpace]
Tabela

= [ColumnFamily]

Linha

= [Key]

Valores = [Column][SuperColumn][SubColumn]
Keyspace 1
Column Family 1

RowKey 1

Name
Value
Timestamp

Name
Value
Timestamp

Name
Value
Timestamp

RowKey 2

Name
Value
Timestamp

Name
Value
Timestamp

Name
Value
Timestamp
Cases
NoSQL at Netflix

http://goo.gl/dtkRw1
2011 Cassandra SF: Cassandra at Twitter Presentation

http://goo.gl/Z6akmx
C* Summit 2013: Cassandra at Instagram

http://goo.gl/UtCMH9
Mais...
http://www.planetcassandra.org/Company/ViewCompany
Devo Usar?
- Algum outro NoSQL não aguentou (MongoDB)
- Precisa de um modelo de dados mais rebuscado?
- Precisa de uma escrita ABSURDA?
- Está disposto a reformular sua aplicação?
As vezes muito trabalhoso dependendo da arquitetura

- Está disposto a gastar $$?
PHP
Dependências
Cassandra
http://cassandra.apache.org
- Não recomendado usar o java 7 ou o OpenJDK
- Oracle Java SE Runtime Environment (JRE) 6
- Apache disponibiliza “binary tarballs” e “Debian
packages”
- Java Native Access (JNA) é necessário para
servidores de produção pois melhora a utilização
de memória do Cassandra
- Cassandra-Cli
- CQL - Cassandra Query Language
http://cassandra.apache.org/doc/cql/CQL.html
Criando
cassandra-cli
create keyspace Palestra
with placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy'
and strategy_options = {replication_factor:1};
use Palestra;
create column family Users;

cqlsh
cqlsh:demo> select * from “Users”;
Thrift
http://thrift.apache.org
- Habilitar APC para melhor performace
- Dependências / Install
http://thrift.apache.org/docs/install/

- Módulo nativo do PHP (phpize)
cd ext/thrift_protocol
phpize
./configure
make
sudo make install
PHPCassa
- Compatível com Cassandra 0.7 até 1.2
- PHP 5.3+
- CQL 2.0
Links
https://github.com/thobbs/phpcassa
https://groups.google.com/forum/#!forum/phpcassa
http://thobbs.github.io/phpcassa/
http://itsallabtamil.blogspot.com.br/2012/03/cassandra-phpcassa-composite-types.html
http://www.fuzzy.cz/en/articles/php-and-cassandra-twissandra/
Criando
<?php
require_once(__DIR__.'/../lib/autoload.php');
use phpcassaConnectionConnectionPool;
use phpcassaColumnFamily;
use phpcassaSystemManager;
use phpcassaSchemaStrategyClass;
$sys = new SystemManager('127.0.0.1');
$sys->create_keyspace('Palestra', array(
"strategy_class" => StrategyClass::SIMPLE_STRATEGY,
"strategy_options" => array('replication_factor' => '1')));
$sys->create_column_family('Palestra', 'Users');
$sys->close();
Sem PHPCassa
<?php
$GLOBALS['THRIFT_ROOT'] = '/usr/share/php/Thrift';
require_once $GLOBALS['THRIFT_ROOT'].'/packages/cassandra/Cassandra.php';
require_once $GLOBALS['THRIFT_ROOT'].'/packages/cassandra/cassandra_types.php';
require_once $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php';
require_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php';
require_once $GLOBALS['THRIFT_ROOT'].'/transport/TFramedTransport.php';
require_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php';
try {
$socket = new TSocket('127.0.0.1', 9160);
$transport = new TBufferedTransport($socket, 1024, 1024);
$protocol = new TBinaryProtocolAccelerated($transport);
$client = new CassandraClient($protocol);
$transport->open();
$keyspace = 'Palestra';
$keyUserId = "user0";
$columnPath = new cassandra_ColumnPath();
$columnPath->column_family = 'Users';
$columnPath->super_column = null;
$columnPath->column = 'email';
$timestamp = time();
$consistency_level = cassandra_ConsistencyLevel::ZERO;
$value = 'user@email.com';
$client->insert($keyspace, $keyUserId, $columnPath, $value, $timestamp, $consistency_level);
$transport->close();
} catch (TException $tx) {
print 'TException: '.$tx->why. ' Error: '.$tx->getMessage() . "n";
}
Com PHPCassa
<?php
require_once(__DIR__.'/../lib/autoload.php');
use phpcassaConnectionConnectionPool;
use phpcassaColumnFamily;
$pool = new ConnectionPool('Palestra', array('127.0.0.1'));
$users = new ColumnFamily($pool, 'Users');
$users->insert('user0', array("email" => "user@email.com"));
$pool->close();
<?php
require_once(__DIR__.'/../lib/autoload.php');
use phpcassaConnectionConnectionPool;
$servers = array(“192.168.229.170:9160”,”192.168.229.171:9160”,”192.168.229.172:9160);
$pool

= new ConnectionPool ('Palestra',$servers);

$pool->close();
$sys = new SystemManager('127.0.0.1');
$pool = new ConnectionPool('Palestra', array('127.0.0.1'));
$users = new ColumnFamily($pool, 'Users');
$users->truncate();
$sys->drop_keyspace("Palestra");
$pool->close();
$sys->close();
Insert e Batch Insert
$users->insert('user0', array("name" => "ivan", "state" => "SP"));
$users->insert('user1', array("name" => "elton", "state" => "SC"));

$users->batch_insert(array("user3" => array("name" => "er"),
vvvvvvvvvvv"user4" => array("name" => "calvin")));
Select e Multi Select
$user = $users->get('user0');
$name = $user["name"];
echo "Nome do usuário $namen";

$columnNames = array('name', 'state');
$user = $users->get('user0',$column_slice = null, $column_names=$columnNames);
$many = $users->multiget(array('user0', 'user1'));
foreach($many as $user_id => $columns) {
echo "Estado do $user_id: ".$columns["state"]."n";
}

$users->get_count('user0');
// retorna 2
Where e Limit
<?php
require_once(__DIR__.'/../lib/autoload.php');
use phpcassaConnectionConnectionPool;
use phpcassaColumnFamily;
use phpcassaColumnSlice;
$pool = new ConnectionPool('Palestra', array('127.0.0.1'));
$letters = new ColumnFamily($pool, 'Letras');
$columns = array(1 => "a", 2 => "b", 3 => "c", 4 => "d", 5 => "e");
$letters->insert('linha', $columns);
…….
$pool->close();
// Where >= 2
$slice = new ColumnSlice(2);
print_slice($letters->get('linha', $slice));
// Between 2 and 4
$slice = new ColumnSlice(2, 4);
print_slice($letters->get('linha', $slice));
// Limit 3
$slice = new ColumnSlice('', '', $count=3);
print_slice($letters->get('linha', $slice));
// 3 últimas
$slice = new ColumnSlice('', '', $count=3, $reversed=true);
print_slice($letters->get('linha', $slice));
// 2 últimas antes do 4
$slice = new ColumnSlice(4, '', $count=2, $reversed=true);
print_slice($letters->get('linha', $slice));
Delete
<?php
require_once(__DIR__.'/../lib/autoload.php');
use phpcassaConnectionConnectionPool;
use phpcassaColumnFamily;
$pool = new ConnectionPool('Palestra', array('127.0.0.1'));
$users = new ColumnFamily($pool, 'Users');
$users->remove("user4");
$users>remove("user0", array("state"));
$users->truncate();
$pool->close();
Referências / Links
Planet Cassandra
http://www.planetcassandra.org/

Cassandra Summit 2013
http://www.youtube.com/watch?v=Qz6ElTdYjjU&list=PLqcm6qE9lgKJzVvwHprow9h7KMpb5hcUU

Using Cassandra with PHP
https://pressflow.atlassian.net/wiki/display/PF/Using+Cassandra+with+PHP

DataStax
http://www.datastax.com/docs

DataStax Data modeling
http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/ddl/ddl_anatomy_table_c.html

Apache Cassandra Wiki
http://wiki.apache.org/cassandra/ArticlesAndPresentations

Quadrinho de como o Cassandra Funciona
http://blogs.atlassian.com/2013/09/do-you-know-cassandra

Pandra
https://github.com/mjpearson/Pandra

Cassandra PHP Client Library
https://github.com/kallaspriit/Cassandra-PHP-Client-Library/

Cassandra PDO
https://github.com/Orange-OpenSource/YACassandraPDO

Php e Cassandra