\chapter{Cluster de Banco de Dados}
\label{clusterdados}
Na maioria das aplicações que se encontram em produção os dados da aplicação são armazenados em um servidor de banco de dados. Dessa forma o banco de dados se torna um componente crítico na solução da aplicação, uma interrupção no serviço de banco de dados, ou uma pequena corrupção dos dados pode afetar totalmente a integridade da aplicação.

Existem muitas formas de se trabalhar com banco de dados de forma a se obter maior performance e/ou para obter outras características desejáveis que não estão disponíveis facilmente nos SGDBs mais conhecidos. 

Algumas das áreas de pesquisa e desenvolvimento de bancos de dados mais avançados são apresentadas a seguir.

% \section{Os Bancos de Dados}


\textbf{\textit{Design} de bancos de dados distribuídos}.\\

O \textit{design} de banco de dados distribuídos responsivo é uma preocupação básica para os sistemas de informação. Em redes com grande largura da banda, latência e processamento local são os fatores mais significativos para consultas e atualização de dados no que se refere ao tempo de resposta do sistema. O processamento paralelo de consultas pode ser usado para minimizar os efeitos, particularmente se for considerado no momento do \textit{design} do sistema de banco de dados. A replicação e a localização dos dados na rede que faz o paralelismo ser efetivamente utilizado. O \textit{design} de banco de dados distribuído pode ser visto como um problema de otimização que requer soluções a vários problemas que possuem relação com: a fragmentação de dados, a alocação de dados, e a otimização local.


\textbf{Processamento de consultas distribuído}.\\

Em sistemas distribuídos de grande escala, é freqüentemente difícil achar um plano ótimo para consultas distribuídas: sistemas distribuídos podem ficar muito grandes, envolvendo milhares de parques computacionais  heterogêneos. Como novos bancos de dados podem ser adicionados/removidos do sistema, fica mais difícil para o ``processador de consulta"~ manter estatísticas precisas das relações participantes armazenadas nos diferentes sites e das operações de consulta relacionadas. Também, como a carga de trabalho dos vários servidores de processamento e a velocidade de transmissão dos links entre eles flutuam durante o tempo de processamento dos trabalhos, há a necessidade de mecanismos de consulta distribuídos, que dinamicamente se adaptem a grandes ambientes distribuídos.


\textbf{Controle de Concorrência}.\\

O Controle de concorrência (CC) permite os usuários acessar um banco de dados distribuído mantendo a impressão que está acessando o banco de dados em um sistema dedicado.

Para isto, são necessários mecanismos de CC que intercalem a execução de um conjunto de transações debaixo de certas regras de consistência, enquanto maximizam a capacidade de execução concorrente do sistema. As duas principais categorias de mecanismos de CC são:

\begin{itemize}
\item \textbf{Concorrência Otimizada} - Retardo da sincronização das transações até que as operações sejam executadas de fato. Conflitos são menos prováveis mas não serão conhecidos até que eles aconteçam, tornando operações de \textit{rollback} mais caras.
\item \textbf{Pessimista} - As execuções potencialmente concorrentes de transações são sincronizadas no início de seus ciclos execução. Desta forma, fica mais fácil realizar o bloqueio, entretanto os problemas devem ser conhecidos anteriormente para diminuir os custos de \textit{rollbacks}.
\end{itemize}


\textbf{Processamento de Transações}.\\


Transações distribuídas provêem unidades de execução segura que permitem que várias operações sejam executadas em ''locais'' diferentes e provêem a preservação da consistência dos dados de um estado de execução para outro. Um protocolo comum para assegurar cumprimento correto de uma transação distribuída é o de ''execução em duas fases''~ (\textit{two-phase commit} - 2PC). Enquanto o 2PC é normalmente aplicado para transações que são executadas em um curto período de tempo, ele se torna impraticável para transações distribuídas de grande escala por causa do lock de recursos disponíveis/utilizados concorrentemente.  Para isto, existem diferentes propostas, como a de dividir a execução de processos que ocupam muito tempo em sucessões menores de tarefas atômicas e a definição de mecanismos de compensação.



\textbf{Replicação de Dados}.\\

O desafio fundamental na replicação de dados é manter um baixo custo nas atualizações enquanto se assegura a consistência dos parques computacionais do cluster. A dificuldade do problema aumenta significativamente em ambientes de larga escala devido a latência alta e a probabilidade de quedas da rede. As duas principais categorias de técnicas de replicação de banco de dados são:

\begin{itemize}
\item \textbf{Replicação síncrona} - implica em um protocolo de ``commit"~ atômico ao longo do qual assegura consistência alta às custas de transações mais lenta e a presença de \textit{deadlocks}.
\item \textbf{Replicação assíncrona} - as atualizações são processadas periodicamente por todos os nós do cluster, permitindo um processo de transação mais eficiente, ao custo de uma baixa garantia da consistência global dos dados.
\end{itemize}

%Também existe a proposta de replicação baseada em grupo de comunicações, para usufruir da vantagem da rica semântica das primitivas dos grupos de comunicação enquanto se utiliza de garantias de relaxadas de isolamento, para reduzir a possibilidade de ``deadlocks"~ e congestionamento de mensagens, assim,  aumentando o desempenho do sistema.


\textbf{Integração de Dados}.\\

Conflitos diferentes surgem da representação descoordenada de conceitos ao se integrar fontes de dados autônomas e distribuídas. Exemplos destes conflitos são: tipo de dados, estrutura, conflito de nomes, atributos perdidos, e conflitos de generalização. Todos estes conflitos podem ser estaticamente endereçados entre eles, durante integração dos esquemas de dados ou dinamicamente na geração de visão/consultas. De acordo com a arquitetura de integração, e a estratégia de manipulação de consultas, sistemas de integração de banco de dados podem ser:

\begin{itemize}
\item \textbf{Sistema de Multi-banco de dados} - coleção de bancos de dados integrados nos quais cada DBMS mantém controle em cima de seus bancos de dados locais, mas coopera com a federação aceitando operações globais.
\item \textbf{Sistema de mediador} - bancos de dados são integrados, através de um componente de mediação que executa tradução de dados em um modelo de dados canônico comum.
\item \textbf{Sistemas de Metadados} - consultas são formuladas dinamicamente em cada banco de dados pela interação com um dicionário de metadados global.
\end{itemize}



Existem vários tipos de ``clusters"~ de banco de dados:
	 
\begin{itemize}

\item Banco de dados distribuídos: Nesse tipo de banco de dados os dados são distribuídos em um conjunto de servidores. O acesso ao banco de dados é direcionado ao servidor onde se encontra o dado.

\item Banco de dados em alta disponibilidade: Dois ou mais servidores em cluster de alta disponibilidade (MASTER/SLAVE), onde um servidor MASTER é responsável pelo serviço e os servidores SLAVE ficam aguardando a falha do MASTER para assumirem o serviço.

\item Banco de dados em alta disponibilidade e distribuídos: É um cluster de banco de dados onde as duas tecnologias anteriores estão presentes, criando um banco de dados escalável e tolerante a falhas.

\end{itemize}

 Possíveis tecnologias de cluster de banco de dados:
\begin{itemize}
\item Gerenciamento do cluster na aplicação: Nessa alternativa o gerenciamento do cluster é realizado na aplicação que acessa o banco de dados. A aplicação que controla a distribuição e replicação dos dados. Vantagem: Pode ser Independente de sistema de banco de dados. Desvantagem: É dependente da aplicação que está acessando o banco de dados. Exemplo de solução: Sequoia (ver \ref{section_sequoia}), compatível e possui a mesma sintaxe do JDBC e para ser utilizado em uma aplicação que é escrita em java são necessários poucos ajustes na aplicação. Capaz de ``clusterizar"~ \textbf{qualquer} banco de dados ODBC.

 \item Gerenciamento do Cluster no próprio banco de dados: Nesta alternativa o gerenciamento do cluster é implementado através de uma ferramenta interna do próprio sistema de banco de dados. Vantagem: Possui maior integração com o sistema de banco de dados, sistema mais robusto de integridade de dados, maior integração com o sistema de banco de dados. Desvantagem: É dependente do sistema de banco de dados. Exemplos: Solução Proprietária: \textit{Oracle Real Aplication Cluster} (RAC), Soluções Livres: Mysql Cluster(ver \ref{section_mysql}), PGcluster (ver \ref{section_pgcluster}).
 
 \item Criação de um \textit{Proxy} de banco de dados: Semelhante ao gerenciamento na aplicação, só que neste caso é criado um serviço ``falso"~ (\textit{honeypot}) onde são feitas as conexões e o gerenciamento da distribuição das requisições para os servidores de banco de dados reais.

 \item LVS + Filesystem distribuído e compartilhado: Em última instância banco de dados é arquivo armazenado em disco, essa idéia consiste em ter um sistema de arquivos único entre os servidores, que suporte acesso de escrita compartilhado (implementação via \textit{software} das funcionalidades de uma SAN - \textit{Storage Area Network}) e um sistema que realize o balanceamento de conexões TCP/ip entre os servidores. Funcionamento: Quando um usuário tenta realizar uma operação de escrita no banco de dados, ele é direcionado através do LVS para um dos servidores de dados, onde é processada a requisição como se o banco não estivesse em cluster. Após a escrita ter sido armazenada em disco todos os outros servidores serão capazes de reconhecer transparentemente as alterações realizadas. Um problema nesse tipo de solução é o \textit{cache} do servidor de banco de dados que tem de ser reduzido para o mínimo possível (\textit{Atomic Operations}, \textit{Atomic Transactions}).
 \end{itemize}

A área de banco de dados é bastante sensível e as tecnologias estão começando a se consolidar, é necessário realizar muitos testes para se definir qual a melhor tecnologia a ser adotada para cada situação.


% \section{Alta disponibilidade}
\section{Banco de Dados Distribuídos}

\paragraph{Definições}

	\begin{enumerate}
	\item [1.]Segundo C. J. Date \cite{Date95},\\
	Um sistema de banco da dados distribuídos consiste em uma coleção de locais, conectados por alguma rede de comunicação e que:
	\begin{enumerate}
		\item [a.] Cada um dos locais é um sistema de banco de dados completo com seus próprios direitos, mas
		\item [b.] Os bancos de dados locais trabalham em conjunto para que os usuários que acessam os dados de qualquer outro local da rede possa acessar os dados de forma transparente.
	\end{enumerate}

	\item [2.] Um banco de dados distribuído é um banco de dados que está sob o controle de um sistema de administração de banco de dados central, no qual dispositivos de armazenamento (\textit{storage}) são anexados a um computador. O armazenamento pode ser em  vários computadores  localizados no mesmo local físico, ou dispersos em uma rede de computadores interconectados.

O banco de dados, pode ser distribuído fisicamente através de múltiplos locais. Um banco de dados distribuído é dividido em várias partes ou fragmentos. Essas partes ou fragmentos do banco de dados distribuído podem ser replicadas, para por exemplo criar ambientes de redundância, RAID, ou mesmo copias para \textit{Data Warehouse}.

Além de replicação e fragmentação em banco de dados distribuídos, existem várias outras tecnologias para \textit{design} de banco de dados distribuídos. Por exemplo, autonomia local, tecnologias de bancos de dados distribuídos síncronos e assíncronos. A implementação destas tecnologias podem e definitivamente dependem das necessidades das áreas de negócios e de a sensibilidade e confidenciabilidade dos dados a serem armazenados no banco de dados.


\section{Replicação de Banco de Dados}

Um banco de dados replicado é um sistema de bancos de dados com cópias distribuídas em  uma ou mais máquinas. Este tipo de sistema oferece alta disponibilidade e tolerância a falhas, já que não há apenas uma única cópia dos dados, e melhoria de desempenho, posto que as requisições não onerarão apenas uma fonte de dados.

Para se implementar a replicação em bancos de dados podem ser usados dois métodos levando-se em consideração a maneira como é feita a propagação de uma atualização.

Uma primeira aproximação é chamada replicação síncrona, ou seja uma atualização (modificação fruto de uma operação de UPDATE, INSERT ou DELETE, por exemplo) só é consumada se for realizada em todos os nós que compõem o sistema. Isto significa que o cliente terá de esperar até que todas as instâncias do banco de dados sejam modificadas para receber uma confirmação, garantindo a integridade da informação entre os nós.

A outra aproximação é realizar a atualização de maneira assíncrona, ou seja as modificações são difundidas entre os nós após ser efetivada em um servidor e a resposta ser enviada ao cliente. O tempo de resposta, se comparado ao método anterior é menor, porém isto pode gerar inconsistências entre as replicas.

Uma maneira de se contornar estes problemas é restringir as atualizações a um único nó, chamado cópia primária ou MASTER, o que impede que atualizações em um mesmo objeto sejam feitas em duas máquinas diferentes. Todas as operações de modificação no banco serão enviadas para esta máquina que cuidará de propagar as modificações. A contrapartida para este modelo é permitir atualizações em qualquer banco que componha o sistema, não introduzindo uma réplica privilegiada mas requerendo um sistema que resolva conflitos de possíveis inconsistências.

O uso de \textit{middleware} (\textit{software} interface entre os clientes e o sistemas de bancos de dados) se tornou um atrativo, já que permite a construção de sistemas replicados sem a necessidade de modificação do sistema de gerenciamento de banco de dados, nem no banco de dados em si. Em sistemas desta natureza as requisições são enviadas ao \textit{middleware} que se encarrega de propagá-las às réplicas de maneira a prover controle de replicação e balanceamento de carga.

Dentre os bancos de dados livres dois vem se sobressaindo no ambiente corporativo, o Mysql\cite{mysql} e o Postgresql\cite{postgresql}, dos quais veremos alguns detalhes sobre a clusterização e replicação de dados.

\section{PostgreSQL}

O PostgreSQL é um SGBD (Sistema Gerenciador de Banco de Dados) objeto-relacional de código aberto, com mais de 15 anos de desenvolvimento. É extremamente robusto e confiável, além de ser extremamente flexível e rico em recursos. Ele é considerado objeto-relacional por implementar, além das características de um SGBD relacional, algumas características de orientação a objetos, como herança e tipos de dados personalizados. A equipe de desenvolvimento do PostgreSQL sempre teve uma grande preocupação em manter a compatibilidade com os padrões SQL92/SQL99/SQL2003 (Postgresql-BR \cite{postgresql}).

As capacidades de Replicação e Clusterização são feitas através de \textit{middlewares} externos próprios para o PostgreSQL, como o PGpool e o PGcluster, que são detalhados a seguir.

% e o q existe de replicação e cluster nele e para ele, e dae emenda nos middlewares.

\subsection{PGpool}

PGpool\cite{pgpool} é um \textit{middleware} para PostgreSQL, distribuído sob licença BSD, que se situa entre os clientes e os servidores de banco de dados provendo alta disponibilidade, replicação e balanceamento de carga. Além destas características em comum com outros sistemas similares, PGpool adicionalmente salva as conexões com os servidores PostgreSQL por ele coordenados (PGpool atualmente trabalha apenas com dois servidores PostgreSQL), reutilizando-as quando uma nova conexão com mesmas propriedades (nome de usuário, banco de dados, protocolo) chega, reduzindo sobrecarga de conexão e aumentando a taxa de transferência de todo o sistema. %PGpool funciona apenas com dois servidores de bancos de dados.

Como sistema de replicação de dados, PGpool permite \textit{backup} em tempo real de bancos de dados, enviando as mesmas declarações SQL para ambos os servidores, podendo ser considerado um sistema de replicação síncrona. Apesar disto algumas instruções SQL são dependentes do servidor no qual são executadas como funções aleatórias, OID, XID e \textit{timestamp}, não sendo replicadas com o mesmo valor para ambos servidores.

Se algum problema torna um dos servidores PostgreSQL indisponível, o PGpool tenta continuar o serviço com o servidor ainda ativo, este modo é chamado `` modo degenerado". Inconvenientemente, o PGpool não oferece nenhum método para voltar um servidor com problemas de novo no cluster, sendo necessário que os bancos sejam sincronizados novamente. A melhor maneira é desativar o servidor ativo, sincronizar os arquivos do Postgresql via \textit{rsync}, por exemplo, reiniciar os bancos e o PGpool.

O PGpool envia uma query para o `` master"~ que envia para o `` slave"~ antes do `` master"~ completar a query. Isto pode aumentar a performance (desempenho) mas acrescenta o risco de ``deadlock". Para balancear performance e risco, PGpool pode operar de duas formas:

\begin{enumerate}[1)]
\item modo ``\textit{restrict}": Neste modo, PGpool espera a conclusão da query no nó \textit{master} para depois envia-la para o secundário. Este é o modo de operação padrão e mais seguro do PGpool.

\item palavra chave /*STRICT*/: Visando performance, o modo restrict pode ser desabilitado através do ajuste da diretiva `` PGpool\_restrict" na configuração do PGpool. Para inibir ''deadlocks'', deve-se inserir a /*STRICT*/ no inicio de cada query passível de produzir ''deadlock'', como por exemplo:

\begin{verbatim}
/*STRICT*/ LOCK TABLE t1;
\end{verbatim}
\end{enumerate}

Caso algum ''deadlock'' ocorra, não sendo detectado pelo próprio PostgreSQL, PGpool abortará a sessão se um dos nós não responderem por um certo intervalo de tempo configurável.

Para propósitos de balanceamento de carga (configurável pelo parâmetro ``load\_balance\_mode"~ no arquivo de configuração), as consultas ``SELECT" são distribuídas entre o nó \textit{master} e o \textit{slave} de maneira aleatória, para aumentar performance.

É importante notar que mesmo instruções \lq\lq SELECT\rq\rq podem introduzir alterações em bancos chamando funções que podem modificá-los. Em casos como este não se deve usar o balancemanto de carga, sendo necessário se usar espaços em branco antes da \textit{query} para que ela não seja distribuída.

Eis uma lista de vantagens no uso do PGpool:

\begin{enumerate}[.]
\item Não é necessário modificações na aplicação.

\item Qualquer linguagem pode ser usada.

\item O número de conexões com o PostgreSQL pode ser limitado.

\item Tolerância a falhas. Caso ocorra falha em um servidor PostgreSQL, o outro assume automaticamente.

\item Replicação.

\item Balanceamento de carga, consultas somente leitura podem ser distribuídas entre os servidores.
\end{enumerate}


Desvantagens:

\begin{enumerate}[.]
\item Sobrecarga. Todos os acesso ao PostgreSQL passam pelo PGpool o que pode reduzir um pouco a performance (de 1 a 15\% de acordo com os desenvolvedor em testes feitos com pgbench).

\item Nem todos protocolos da \textit{libpq} são suportados:
	\begin{enumerate}[1]
	\item Nenhum método de autenticação exceto ``trust" e ``clear text password" em modo de replicação.
	
	\item Em modo não replicado só são aceitos ``trust", ``clear text password", ``crypt" e ``md5".
	
	\item Controle de acesso via pg\_hba.conf não é suportado.
	\end{enumerate}

\item Sem controle de acesso, qualquer um pode acessar PGpool, o que pode ser impedido via \textit{iptables}, por exemplo.
\end{enumerate}

\subsubsection{PGpool-II}

PGpool-II é um projeto que herdou as características do PGpool, mas que suporta múltiplas instâncias do PostgreSQL (128 nós, expansível via recompilação do código-fonte) e processamento paralelo nos múltiplos nós, o que aumenta muito a performance.

A arquitetura do PGpool-II consiste, em um ``System DB"~ que processa as informações administrativas e operações agregadas, e múltiplos nós de dados onde são armazenados os dados. Novos dados serão incluídos/alterados no nó DB baseado em regras de particionamento pré-definido. Uma regra de particionamento é definida por funções SQL e são armazenadas no ``System DB", que é outro servidor PosgreSQL.
A arquitetura do PGpool-II é ilustrada na figura \ref{fig:pgpool-arch} que se segue.

\begin{figure}[!htb]
\centering
\includegraphics[scale=1.3]{imagens/pgpool-arch-small.png}
\caption{Sistema de balanceamento de carga}
\label{fig:pgpool-arch}
\end{figure}

\subsection{PGcluster}
\label{section_pgcluster}
PGCluster\cite{pgcluster} é um conjunto de modificações para o código fonte do PostgreSQL que permite a montagem de um sistema de replicação síncrono \textit{multi-master}, garantindo replicação consistente e balanceamento de carga para bancos de dados baseados em PostgreSQL. A replicação síncrona garante que dados sejam replicados sem que haja atraso e a característica de ser \textit{multi-master} permite que dois ou mais nós de armazenamento possam receber requisições de usuários ao mesmo tempo.


O sistema é composto por três tipos de máquinas:

\begin{enumerate}[.]
\item \textbf{servidor de balanceamento (\textit{Load Balancer}):} recebe consultas e as encaminha para os nós de armazenamento. As consultas são distribuídas de acordo com a carga de cada nó. Podendo existir mais de um balanceador de carga.

\item \textbf{servidor de armazenamento (Cluster DB):} máquina que recebe e armazena as consultas em bancos de dados.

\item \textbf{servidor de replicação (\textit{Replicator}):} cuida de manter os dados sincronizados entre os servidores. Mais de um servidor pode ser utilizado, neste caso, outro servidor só assume se o servidor de replicação principal falhar.
% \item \textbf{Nó de armazenamento (Cluster DB):} máquina que hospeda o banco de dados.
% 
% \item \textbf{Load balancer:} máquina que cuida de receber e distribuir as requisições para os nós de armazenamento (de acordo com a carga de cada nó).
% 
% \item \textbf{Replicator:} máquina responsável pela replicação das consultas nos nós de armazenamento (\textbf{cluster db}). Podem ser usadas mais de uma máquina, mas que só assume função se o servidor de replicação principal falhar.
\end{enumerate}

O sistema cumpre as seguintes funções:

\begin{enumerate}[.]

\item \textbf{Balanceamento de carga:} Pela combinação de servidores de armazenamento e servidor de replicação, pode-se criar um sistema onde o PGCluster verificará qual máquina está com menor carga, redirecionando uma possível consulta para ela.

\item \textbf{Alta disponibilidade:} Com a adição de um balanceador de carga, PGCluster configura um sistema de alta disponibilidade. O balanceador de carga e o servidor de replicação separará um nó que ocasionalmente falhe e continuará a servir com o restante do sistema. Assim que a máquina que falhou for reestabelecida ao sistema, os dados serão copiados para ela automaticamente, o mesmo acontece com um novo nó que venha a se integrar ao sistema.
\end{enumerate}

\paragraph{Sistema de Balanceamento de Carga}

Combinando os servidores de armazenamento e servidor de replicação, PGCluster pode distribuir carga de acesso ao banco de dados, verificando qual máquina está com menor carga, redirecionando consultas para ela. A figura \ref{fig:loadcomp} ilustra a estrutura de balanceamento de carga.
\begin{figure}[!htb]
\centering
\includegraphics[scale=1.3]{imagens/loadcomp.png}
\caption{Sistema de balanceamento de carga}
\label{fig:loadcomp}
\end{figure}

\paragraph{Sistema de Alta disponibilidade}

Adicionalmente, PGCluster pode prover um sistema de Alta Disponibilidade pela adição de um balanceador de carga. Quando uma falha ocorre em um servidor de armazenamento, os servidores de balanceamento e de replicação separam o componente falho e continuam servindo com o restante do sistema. Isto é feito sem que haja interrupção do mesmo.
A figura \ref{fig:hacomp} ilustra a estrutura de Alta Disponibilidade para o PGcluster.

Quando uma máquina que falhou é recolocada no sistema, os dados são copiados para ela automaticamente, o mesmo acontecendo quando um servidor de armazenamento novo é adicionado.
\begin{figure}[!htb]
\centering
\includegraphics[scale=1.3]{imagens/hacomp.png}
\caption{Sistema de alta disponibilidade}
\label{fig:hacomp}
\end{figure}
\newpage


\subsection{Slony}
\label{slony}

%QQISSO% promoção pra que ? ta pobre
Slony\cite{slony} é um sistema de replicação `` master"~ para  ``muitos slaves"~ que suporta cascateamento e transformação de ``slaves"~ para `` master"~, possui capacidade para replicar grandes bancos de dados em até doze servidores \textit{slave}. O Slony foi criado para atender a \textit{data centers} e \textit{sítios de backup} onde todos os nós devem estar disponíveis a qualquer momento.

Há alguns modelos distintos de replicação de bancos de dados, é difícil que um modelo se adapte à todas as necessidades. O modelo implementado no Slony-I é chamado de replicação assíncrona usando \textit{triggers} para coletar as atualizações, onde uma origem comum é replicada em múltiplas cópias incluindo cópias cascateadas.


Em algumas situações, Slony não é aconselhável:

\begin{enumerate}[.]
\item Sistemas com conectividade ruim

\item Replicação em nós com certa imprevisibilidade na conexão.

\item Sistemas cuja configuração mude de maneira aleatória.

\item Sistemas onde \textit{schemas} de bancos de dados podem ser mudados arbitrariamente.
\end{enumerate}

Slony é um sistema de replicação independente de versão do PostgreSQL, permitindo ser iniciado ou parado sem a necessidade de ciclos de dump/reload.

Dentre as coisas que Slony não é:

\begin{enumerate}[.]
\item Não é um sistema de gerenciamento de rede.

\item Não possui nenhuma funcionalidade para detectar falha de nó, nem muda um nó \textit{master} para outro, embora isso possa ser conseguido em conjunção com outras ferramentas.

\item Não é um sistema de replicação \textit{multi-master}, mas há planos para transformá-lo em \textit{multi-master} na versão 2, muito embora seja um projeto separado e ainda encontre-se em desenvolvimento.
\end{enumerate}


\paragraph{Modelos de replicação}

Há alguns modelos distintos de replicação de bancos de dados, é difícil que um modelo se adapte à todas as necessidades. O modelo implementado no Slony-I é chamado de replicação assíncrona usando \textit{triggers} para coletar as atualizações, onde uma origem comum é replicada em múltiplas cópias incluindo cópias cascateadas.

Slony não propaga mudanças em \textit{schemas}, nem replica grandes objetos. Slony coleta as atualizações com \textit{triggers}, sendo que apenas tabelas e seqüencias são replicadas.


\section{Mysql}
\label{mysql}
\label{section_mysql}
O MySQL é um servidor de bancos de dados SQL (\textit{Structured Query Language} - Linguagem Estruturada para Pesquisas) muito rápido, multi-tarefa e multi-usuário. O Servidor MySQL pode ser usado em sistemas de produção com alta carga e missão crítica bem como pode ser embutido em programa de uso em massa. MySQL é uma marca registrada da MySQL AB \cite{mysql}.


\subsection{Replicação em MySQL}

Uma das dificuldades no trabalho com grandes bancos de dados MySQL é a manutenção de backup seguro sem a necessidade do desligamento do sistema. Um backup online, poderia deixar o sistema lento além de causar inconsistências de dados, já que tabelas podem estar sendo modificadas enquanto o backup é feito. O problema de inconsistência poderia ser resolvido com a paralização do banco, entretanto deixaria os usuários do sistema sem acesso ao serviço. O backup é de fato uma medida necessária, mas a paralização diária do sistema é inaceitável. Um método alternativo simples para se assegurar backups confiáveis mantendo disponível o sistema é a replicação do MySQL.

A replicação é uma configuração onde um servidor MySQL, conhecido neste contexto como \textit{master}, armazena dados e gerencia as conexões dos clientes enquanto outro (ou outros) servidores mantêm uma cópia completa dos dados do \textit{master}, duplicando as consultas SQL executadas no \textit{master} logo que elas aconteçem.

O sistema de replicação MySQL permite que múltiplos servidores \textit{slave} mantenham seus dados sincronizados com um único servidor \textit{master}. Entre as vantagens da replicação estão a facilidade de backup e recuperação, além de dar melhor suporte a grandes aplicações. É possível se conseguir escabilidade linear enviando as requisições de escrita (INSERT, UPDATE, DELETE) para o servidor \textit{master} e as conexões de leitura (SELECT) para os servidores \textit{slave}.

Replicação oferece robustez, velocidade e vantagens administrativas:

\begin{enumerate}[.]
\item A robustez é incrementada com uma configuração \textit{master}/\textit{slave}, caso ocorra algum problema com o \textit{master}, um \textit{slave} pode assumir seu lugar.

\item Melhora no tempo de resposta aos clientes pode ser conseguida dividindo a carga para o processamento das consultas do clientes entre \textit{master} e \textit{slaves}. As consultas SELECT podem ser enviadas aos slaves para reduzir a carga do processamento de consultas no \textit{master}. Declarações que impliquem em modificações devem ser enviadas ao \textit{master} para manter os dados sincronizados.

\item Outro benefício do uso da replicação é que backups de bancos de dados podem ser realizados sem interromper o \textit{master}. O \textit{master} continua os processos de atualização enquanto o backup é feito.
\end{enumerate}


\subsubsection{O Processo de Replicação}

Quando o sistema de replicação esta sendo utilizado, quaisquer declarações SQL são executadas no servidor \textit{master}. MySQL grava estas declarações em um \textit{log} binário (bin.log) juntamente com um número que identifica sua posição no \textit{log}. O servidor \textit{slave}, com certa freqüência, verifica este \textit{log} em busca de mudanças. Se uma mudança é encontrada, o \textit{slave} a copia para seu \textit{log} de vigilância (relay.log). Além disso, o \textit{slave} grava um novo número de identificação posicional em um arquivo (\textit{master}.info). O \textit{slave}, então, volta a verificar o \textit{master}, quando alguma alteração é encontrada ela é executada e gravada no relay.log. Como salvaguarda, através de uma \textit{thread} SQL o \textit{slave} compara seus dados com os dados do \textit{master}. Se a comparação se mostrar inconsistente, o processo de replicação para e uma mensagem de erro é gravada no \textit{log} de erro do \textit{slave} (error.log). Se o resultado for satisfatório (os dados estiverem corretos), um novo número de identificação de \textit{log} é gravado no relay-log.info e o \textit{slave} espera por outra mudança em seu arquivo relay.log.

O processo parece complicado à primeira vista, mas é rápido e não ocupa significativamente o \textit{master}, além de assegurar replicação confiável, sendo também muito simples de configurar, significando algumas poucas linhas adicionais ao arquivo de configuração do MySQL (my.cnf) em ambos os servidores \textit{master} e \textit{slave}. Se o servidor \textit{slave} é novo, você precisará de uma cópia dos bancos de dados do \textit{master} no \textit{slave} para coloca-lo no ar. Então o problema se resumirá a iniciar o servidor \textit{slave} para começar a replicação.

\subsubsection{Visão geral da implementação da replicação}

A replicação em MySQL é baseada no log binário das alterações feitas nos bancos de dados do servidor \textit{master}. Cada servidor \textit{slave} recebe do \textit{master} as alterações salvas que foram gravadas executando-as em seu conjunto de dados.

É importante frisar que o \textit{log} binário é simplesmente uma gravação começando de um ponto fixo a partir do momento em que este \textit{log} foi habilitado no servidor. Qualquer \textit{slave} precisará de cópias das bases de dados do \textit{master} exatamente como existiam no momento em que o \textit{log} binário foi iniciado, de outra forma a replicação falhará.

Após ser configurado, o servidor \textit{slave} conecta ao \textit{master} e espera por atualizações. Se o \textit{master} cair ou a conexão for perdida, o \textit{slave} continuará tentando se conectar periodicamente até que seja capaz de receber informações sobre modificações. O intervalo padrão é 60 segundos.

\subsubsection{Replicação baseada em coluna}

A propagação de declaração SQL do \textit{master} para o \textit{slave} é o princípio original da replicação em MySQL. Isto é chamado replicação baseada em declaração. A partir da versão MySQL 5.1.5, outro modelo passou a estar disponível, a chamada replicação baseada em coluna. Ao invés de enviar as declarações MySQL para o \textit{slave}, o \textit{master} escreve os eventos em um \textit{log} binário indicando como as colunas individuais das tabelas foram afetadas. A versão 5.1.8 oferece uma terceira opção: a mista, que usa replicação baseada em declaração por padrão e a baseada em coluna em casos particulares.

Adicionalmente à mudança automática do formato de log, um servidor \textit{slave} pode mudar o formato automaticamente. Isto acontece quando um servidor está rodando em modo STATEMENT ou MIXED e encontra uma coluna no \textit{log} binário que foi escrita em formato ROW. Neste caso, o \textit{slave} muda para modo de replicação coluna temporariamente para este evento, voltando para o modo prévio logo após.

Há duas razões para se ajustar o \textit{log} de replicação baseado na conexão:

\begin{enumerate}[.]
\item Com uma \textit{thread} que faz pequenas modificações no banco de dados é preferível usar \textit{log} baseado em coluna. Uma \textit{thread} que realiza updates em várias colunas com uma cláusula WHERE deve usar \textit{log} baseado em declaração por ser mais eficiente gravar no \textit{log} poucas declarações que muitas colunas.

\item Algumas declarações requerem muito tempo de execução no \textit{master}, mas resultam em poucas colunas modificadas. Deve então, ser benéfico replicá-las utilizando-se \textit{log} baseado em coluna.
\end{enumerate}

Há algumas exceção para as quais não se pode mudar o modo de replicação em tempo de execução:

\begin{enumerate}[.]
\item Funções armazenadas e \textit{trigger}.

\item Se o NDB estiver habilitado.

\item Se sessão aberta em modo de replicação em coluna e tabelas estiver temporariamente aberta.
\end{enumerate}

Não é recomendado mudar o modo de replicação em tempo de execução enquanto tabelas temporárias existirem, porque estas tabelas são gravadas no \textit{log} apenas com replicação baseada em declaração, com replicação baseada em coluna elas não serão gravadas no log. Com replicação mista, tabelas temporárias são usualmente gravadas no log, exceções para os casos de funções definidas pelo usuário (UDF) e a função UUID().

\subsubsection{Técnicas avançadas de replicação}

MySQL cluster é uma arquitetura complexa que provê alta disponibilidade e performance. Sua principal vantagem é que cada nó atua como \textit{master} diferente do sistema de replicação em que há um nó \textit{master} e vários \textit{slaves} e as aplicações devem escrever apenas no \textit{master}.

As principais desvantagens do MySQL cluster são:

\begin{enumerate}[.]
\item O banco de dados ficará em memória somente e isto requer mais recursos que um banco de dados MySQL normal. MySQL 5.1 introduz \textit{tablespaces} com a capacidade de armazenar dados não indexados em disco.

\item Algumas características não estão presentes como procura \textit{full-text}, integridade referencial e níveis de isolamento de transação maiores que READ COMMITTED\footnote{Nível de isolamento de transação define a interação e visibilidade do trabalho realizado por transações simultâneas. %O SQL padrão define quatro níveis de isolamento de transação
%\begin{enumerate}[.]
%\item READ UNCOMMITTED: uma transação enxerga as mudanças realizadas por outras transações ainda não finalizadas.
%
%\item READ COMMITTED: 
%\end{enumerate}
}.
\end{enumerate}

Embora em alguns casos MySQL cluster seja uma solução perfeita, a replicação ainda é, na maioria das vezes, a melhor escolha.

Entretanto, replicação também tem seus problemas:

\begin{enumerate}[.]
\item Há a distinção entre \textit{master} e \textit{slaves} e as aplicações devem escrever apenas no \textit{master}.

\item Quanto a tolerância a falhas, quando o \textit{master} cai, há os \textit{slaves} prontos para assumir, mas o processo de detecção de falhas e substituição do \textit{master} requerem intervenção do administrador.
\end{enumerate}

\subsection{MySQL Cluster}

MySQL cluster é tecnologia que habilita ''clusterização'' de bancos de dados em memória sem dependência de \textit{hardware} ou tecnologia específica. MySQL Cluster implementa uma arquitetura distribuída, altamente tolerante a falhas com nenhum ponto único de falha (SPOF), recuperação automática de nós garantindo a confiabilidade de um \textit{mainframe} em \textit{hardware} de baixo custo, constituindo uma solução de alta disponibilidade com excelente custo benefício.

O sistema integra um servidor MySQL padrão com componente para armazenamento clusterizado em memória chamado NDB, consistindo de um conjunto de computadores rodando processos que incluem servidores MySQL, nós de dados para o cluster NDB, servidores de gerenciamento e programas especializados para acesso a dados.

A \textit{engine} de armazenamento NDB pode ser configurada com muitas opções de tolerância a falhas e balanceamento de carga. Cada parte do MySQL cluster é configurada independentemente dos servidores MySQL, sendo que cada parte é considerada um nó\footnote{Em muitos contextos um nó é geralmente uma máquina, mas em MySQL cluster nó é um processo, sendo possível rodar qualquer número de nós em uma única máquina}.

Há três tipos de nós e em uma configuração mínima de um cluster MySQL exige um de cada tipo:

\begin{enumerate}[.]
\item \textbf{Nó de gerenciamento:} Sua função é gerenciar os outros nós do cluster exercendo funções como prover dados de configuração, iniciar e parar outros nós, backup entre outras coisas. Deve ser o primeiro a ser iniciado pois gerencia a configuração dos outros nós.

\item \textbf{Nó de dados:} Este tipo de nó armazena os dados do cluster. Há tantos nós de dados quantas réplicas vezes o número de fragmentos\footnote{No contexto do MySQL Cluster, fragmento é uma parte de um banco de dados, uma tabela dividida entre vários nós para facilitar balanceamento de carga entre as máquinas e nós. Cada fragmento é armazenado como réplicas em outros nós para prover redundância.}.
\item \textbf{Nó SQL:} Este nó acessa os dados do cluster, é um servidor MySQL tradicional que usa a engine de armazenamento NDB.
\end{enumerate}

Num ambiente real de produção, a configuração com três nós não inclui redundância. Para se beneficiar das propriedades de alta disponibilidade do MySQL Cluster é recomendável se usar múltiplos nós de gerenciamento, de dados e de SQL.

% \subsubsection{Limitações do MySQL Cluster}




\end{enumerate}



\section{Middlewares independentes de Banco de Dados}

\subsection{Middleware Sequoia}
\label{sequoia}
\label{section_sequoia}
Os dados aqui apresentados sobre o Sequoia tem como referência a documentação ``User Guide"~ traduzida pela equipe do Ministério do Planejamento, que pode ser obtida no endereço \www{http://guialivre.governoeletronico.gov.br/guiacluster/}


\subsubsection{O que é Sequoia}

O Sequoia é um \textit{middleware} de cluster que permite que qualquer aplicação Java\texttrademark (aplicação standalone, servlet ou container EJB\texttrademark) acessar, transparentemente, um cluster de banco de dados através de JDBC\texttrademark. Não é necessário realizar modificações nas aplicações clientes, nas aplicações servidoras ou no servidor de banco de dados. Basta apenas que os banco de dados sejam acessados pelo Sequoia.

O Sequoia é um projeto livre de código aberto, continuação do projeto C-JDBC (\url{http://c-jdbc.obejctweb.org}) hospedado pelo projeto ObjectWeb Consortium (\url{http://www.objectweb.org}). Sequoia é liberado sob a licença Apache v2 (\url{www.apache.org/licenses/LICENSE-2.0.html}) enquanto C-JDBC é liberado sob a licença \textit{GNU Lesser General Public License} (\url{http://www.gnu.org/copyleft/lesser.html})\\(LGPL).

O Sequoia também provê um driver para aplicações não escritas em Java. O desenvolvimento do driver está na página do projeto Carob (\url{carob.continuent.org}). Um plug-in Eclipse para o Sequoia está disponível na página do projeto Oak (\url{oak.continuent.org}).


\subsubsection{O que eu preciso para usar Sequoia}

Para se usar Sequoia, é necessário o que se segue:

\begin{enumerate}[.]
\item uma aplicação cliente que acesse um banco de dados através de \textbf{JDBC}.

\item uma \textbf{máquina virtual Java\texttrademark} compilada para \textbf{JDK\texttrademark 1.4}(ou mais recente)\footnote{Sequoia pode funcionar com versões mais antigas da máquina virtual, mas não foi testado.}.

\item um banco de dados com driver \textbf{JDBC}(tipo 1, 2, 3 ou 4) ou um driver \textbf{ODBC} para ser usado com \textbf{JDBC-ODBC bridge}.

\item comunicação de rede com suporte a \textbf{TCP/IP} entre os nós do cluster.
\end{enumerate}

\small{Nota: Se sua aplicação cliente não suporta \textbf{JDBC}, você pode usar a API C++ ou o driver ODBC disponibilizado pelo projeto Carob (\url{http://carob.continuent.org})}
\normalsize

\subsubsection{Porque devo usar Sequoia}

Se você tem uma aplicação cliente em Java ou uma aplicação de servidor baseada em Java que acessa um ou mais bancos de dados, a fila do banco de dados torna-se um gargalo para sua aplicação ou um ponto único de falha ou ambas as coisas. O Sequoia pode ajudar a resolver este problema provendo:

\begin{enumerate}[.]
\item Escalabilidade de performance pela adição de nós de banco de dados e balançeamento de carga entre os nós.

\item Alta disponibilidade para o banco de dados: se ocorrer problemas com os nós, O Sequoia oferece tolerância a falhas de maneira transparente usando técnicas de replicação.

\item Incrementa performance com \textit{cache} de consultas de granulosidade fina e pool de conexão transparente.

\item Log de tráfego SQL para monitoramento e análise de performance.

\item Suporte para cluster de bancos heterogêneos.
\end{enumerate}

\subsubsection{Como funciona}

O Sequoia provê arquitetura flexível que permite  alcançar escalabilidade, alta disponibilidade e tolerância a falhas para banco de dados, através do conceito de RAIDb:Array Redundante não-oneroso de banco de dados (\textit{Redundant Array of Inexpensive Databases}). O banco de dados é distribuído e replicado entre vários nós e o Sequoia é responsável por distribuir a carga das consultas entre eles.

O Sequoia dispõe de um driver \textbf{JDBC} genérico para ser usado pelos clientes. Este driver repassa as requisições para o controlador que faz o balanceamento do cluster de banco de dados (leituras são balanceadas e escritas são difundidas). Podendo ser utilizado qualquer SGBD ( Sistema de Gerenciamento de Bancos de Dados Relacionais - \textit{Relational DataBase Management System}) que possua um driver \textbf{JDBC}, isto é valido para todos os bancos de dados em Código Aberto e Comerciais existentes.
\begin{figure}[!htb]
\centering
\includegraphics[scale=1]{imagens/sequoia_principle.png}
\caption{Princípio do Sequoia}
\end{figure}

A arquitetura é completamente aberta permitindo que qualquer um adicione customizações como agendadores de requisições, balanceadores de carga, gerenciadores de conexão, políticas de \textit{caching}, entre outras.

\subsubsection{Qual o custo}

Sob o ponto de vista de \textit{software}, O Sequoia é um \textit{software} de código aberto licenciado sob a Licença Apache v2 significando que seu uso (pessoal ou comercial) é livre de qualquer taxa. Se você estiver usando um SGBD comercial (\textbf{Oracle,DB2,...}), haverá os custos das licenças adicionais para nós extras nos quais você instalará réplicas de seu banco. Mas é possível o uso de bancos de código aberto para hospedar réplicas de seu banco de dados principal.

Máquinas extras são necessárias para maior performance e maior tolerância a falhas. Sendo que o Sequoia foi desenhado para trabalhar com máquinas de baixo custo pois estas são os primeiros alvos de soluções em código aberto de baixo custo, mas ele funciona igualmente bem em grandes máquinas SMP. Uma placa de rede comum é suficiente para uma boa performance.

\subsubsection{Quais modificações são necessárias}

Você \textit{não necessita de qualquer mudança em sua aplicação ou seu banco de dados}.

É necessária, apenas, a atualização da configuração do driver \textbf{JDBC} usado por sua aplicação (usualmente é apenas a atualização de um arquivo de configuração) e os ajustes no arquivo de configuração do Sequoia.

\subsubsection{RAIDb básico}
%%%%
A equipe de desenvolvimento do C-JDBC (antigo nome do projeto Sequoia) criou e implementou o conceito de RAIDb. RAIDb está para bancos de dados assim como RAID está para discos. RAID combina vários discos rígidos de baixo custo em um \textit{array} de discos para obter performance, capacidade e confiabilidade que excedem as capacidades de um disco de grande capacidade. RAIDb visa melhor performance e tolerância a falhas pela combinação de múltiplas instâncias de bancos de dados em um \textit{array} de bancos de dados.

RAIDb objetiva o uso de \textit{hardware} e \textit{software} de baixo custo como cluster de workstations e bancos de dados de código aberto. Clusters de workstations já são alternativa viável se comparadas às máquinas paralelas usadas em pesquisa científica pela vantajosa relação custo/beneficio. Clusters desta natureza podem ser usados para prover alta disponibilidade e escalabilidade em ambientes de bancos de dados.

RAIDb esconde a complexidade da replicação disponibilizando ao cliente através da visão de acesso a um único banco de dados, utilizando-se uma máquina (controller) que é colocada à frente dos recursos disponíveis. Os cliente direcionam suas requisições ao controlador RAIDb que por sua vez as distribui ao seu conjunto de sistemas de gerenciamento de bancos de dados (SGBD).

Os três níveis básicos do RAIDb são:

\begin{enumerate}[.]
\item \textbf{RAIDb-0:} que particiona o banco de dados entre os nós mas não oferece tolerância a falhas.

\item \textbf{RAIDb-1:} para replicação e espelhamento completo.

\item \textbf{RAIDb-2:} que oferece replicação parcial.
\end{enumerate}

Também estão definidos, RAIDb-1ec e RAIDb-2ec que adicionam verificação de erros aos níveis RAIDb-1 e RAIDb-2, respectivamente.

%%%%
% \paragraph{Definição de RAIDb}
% 
% \textbf{RAIDb - Redundant Array of Inexepensive Databases}, anacronismo usado em referência para \textbf{RAID - Redundant Array of Inexpensive Disks}, conceito que objetiva escalabilidade e alta disponibilidade de subsistemas de discos de baixo custo. \textbf{RAIDb} objetiva melhor performance e tolerância a falhas que um banco de dados simples pela combinação de múltiplos e não onerosas instâncias de bancos de dados em um \textit{array} de banco de dados.
% 
% Um dos objetivos de \textbf{RAIDb} é esconder a complexidade da distribuição e prover a clientes a visão de um único banco de dados. Como \textbf{RAID}, um controlador é posto à frente dos recursos escondidos. Os clientes enviam requisições ao controlador \textbf{RAIDb} que faz balanceamento entre os conjuntos de \textbf{SGBD} finais.

\paragraph{RAIDb-0:}
%%%%%%
Com este nível de RAIDb pode-se particionar o banco de dados, distribuindo suas tabelas entre os \textit{backends} (máquina que hospeda o banco). Uma tabela em si não pode ser particionada, mas tabelas diferentes podem estar em diferentes nós. Esta configuração requer no mínimo dois \textit{backends}, provendo escalabilidade de performance mas sem tolerância a falhas.
%%%%
% \textbf{RAIDb-0} consiste em particionamento de tabelas de bancos de dados entre nós \textit{backends}. Uma tabela por si mesma não pode ser particionada mas diferentes tabelas podem ser distribuidas em diferentes nós. \textbf{RAIDb-0} requer, no mínimo, dois \textit{backends} de bancos de dados, provê moderada escalabilidade, mas não oferece tolerância a falhas.

A \textbf{figura} \ref{raidb0} mostra um exemplo de configuração \textbf{RAIDb-0}.
\begin{figure}[!htb]
\centering
\includegraphics[scale=1]{imagens/RAIDb-0.png}
\caption{Exemplo de RAIDb-0}
\label{raidb0}
\end{figure}

\paragraph{RAIDb-1}
%%%%%
% \subsection{RAIDb-1}
% 
RAIDb-1 oferece espelhamento completo com replicação total dos bancos de dados nos \textit{backends}. Este modelo de configuração é o que apresenta melhor tolerância a falhas já que o sistema ainda estará disponível se apenas um nó estiver ativo. A desvantagem é que não há melhoria nos processos de escrita em banco (UPDATE, INSERT, DELETE) já que todos estes tipos de requisições serão enviadas para todos os nós.
% 
% \subsubsection{RAIDb-1ec}
% 
Para assegurar integridade, RAIDb-1ec realiza verificação de erros ao RAIDb-1, objetivando detecção de erros bizarros. Requerendo ao menos 3 nós, esta configuração envia as requisições de escrita para a maioria dos nós que compõem o cluster e as resposta são comparadas. Se há consenso nas respostas, elas são enviadas aos clientes, caso contrário uma mensagem de erro é enviada em resposta a requisição.


%%%%%%%
% \textbf{RAIDb-1} oferece \textit{espelhamento total} ou \textit{replicação total} do banco de dados nos \textit{backends}. Oferece o melhor esquema para tolerância a falhas desde que o sistema ainda fica disponível com um único banckend. Um ponto negativo é que não há melhorias de velocidade nas requisições de escrita (\textbf{UPDATA, INSERT, DELETE}) pois elas são distribuídas para todos os nós.
A \textbf{figura} \ref{raidb1} mostra um exemplo da configuração \textbf{RAIDb-1}.
\begin{figure}[!htb]
\centering
\includegraphics[scale=1]{imagens/RAIDb-1.png}
\caption{Exemplo de RAIDb-1}
\label{raidb1}
\end{figure}

\paragraph{RAIDb-2}
%%%%%%%%
% \subsection{RAIDb-2}
% 
RAIDb-2 é a combinação de RAIDb-0 e RAIDb-1, provendo replicação parcial para diminuir a degradação no processo de replicação de cada tabela do banco de dados e obtendo melhores resultados de leitura e escrita. Este modelo requer que cada tabela esteja disponível em pelo menos 2 nós.
%

% \subsubsection{RAIDb-2ec}
% 
Também implementa verificação de erro como RAIDb-1ec. Opera com um mínimo de 4 nós sendo que 3 deles configuram \textit{quorum} para resposta. A escolha dos nós também é mais complexa que em RAIDb-1ec dada a possibilidade de replicação parcial, embora esta característica garanta uma melhor performance.
%%%%%%%%%
% \textbf{RAIDb-2} é uma mistura de \textbf{RAIDb-0} e \textbf{RAIDb-1}. Provê replicação parcial para diminuir a degradação da replicação de cada tabela de banco de dados para obter melhor rendimento de leitura e escrita. \textbf{RAIDb-2} requer que cada tabela do banco esteja disponível em pelo menos dois nodos.
A \textbf{figura} \ref{raidb2} mostra um exemplo desta configuração.
\begin{figure}[!htb]
\centering
\includegraphics[scale=1]{imagens/RAIDb-2.png}
\caption{Exemplo de RAIDb-2}
\label{raidb2}
\end{figure}

\newpage

\paragraph{Níveis de RAIDb aninhados}

%%%%%%%%%%%%%%%%%%%%%%%%%%
% \subsection{RAIDb aninhados}
% 
% \subsubsection{Escalabilidade Vertical}
% 
É possível utilizar vários níveis de RAIDb ao mesmo tempo para se configurar grandes sistemas ou atender necessidades específicas. Um controlador RAIDb escala um número limitado de bancos de dados, entretanto pode-se cascatear vários controladores para disponibilizar mais \textit{backends}.
% 
Em princípio, não há limite para a profundidade do aninhamento de RAIDb. RAIDb de mesmo nível podem ser aninhados como por exemplo um sistema com RAIDb-1-1 para espelhamento de vários bancos de dados.
% 
% 
% \subsubsection{Escalabilidade Horizontal}
% 
Para evitar que o controlador se torne um ponto único de falha, dois ou mais controladores podem ser usados para atender às requisições. O \textit{middleware} de comunicação de grupo JGroups é usado para sincronizar as modificações nos bancos de maneira distribuída.
% 
Os bancos de dados não necessitam ser compartilhados entre os controladores, mas caso um controlador caia, os bancos associados a ele também ficarão indisponíveis. No caso de \textit{backends} compartilhados, um controlador enviará as requisições aos \textit{backends} informando ao outro controlador assim que as requisições estiverem completadas.

%%%%%%%%%%%%%%%%%%%%%%%%%%
% É possível compor vários níveis de RAIDb para construir configurações de larga escala ou atender necessidades especificas. O próximo exemplo é uma configuração RAIDb-1-0 onde um controlador RAIDb-1 de nível mais alto remete as requisições para três bancos de dados completos implementados em um controlador RAIDb-0.
A figura\ref{raidb10}. mostra um exemplo de uma configuração RAIDb-1-0.
\begin{figure}[!htb]
\centering
\includegraphics[scale=1]{imagens/RAIDb-1-0.png}
\caption{Exemplo de RAIDb-1-0}
\label{raidb10}
\end{figure}

O último exemplo (figura \ref{raidb01}) mostra uma composição RAIDb-0-1. O nível mais alto é um controlador RAIDb-0 e a tolerância a falhas é conseguida graças a cada partição usando controlador RAIDb-1.
\begin{figure}[!htb]
\centering
\includegraphics[scale=1]{imagens/RAIDb-0-1.png}
\caption{Exemplo de RAIDb-0-1}
\label{raidb01}
\end{figure}

\subsubsection{Balanceamento de carga}

O balanceador de carga define a maneira que as requisições serão distribuídas entre os \textit{backends} de acordo com o nível do RAIDb. É possível reforçar um nível de isolamento específico para todas as conexões  (isto não terá efeito se o banco de dados usado não suporta isolamento de transações). Em geral, o nível de isolamento de transação padrão será usado e nenhum reforço será dado às conexões. Os seguintes balanceadores de carga estão disponíveis:

\begin{enumerate}[.]
\item \texttt{SingleDB:} balanceador de carga para um instância única de banco de dados. Disponível se apenas um controlador for usado.

\item \texttt{ParallelDB:} balanceador de carga para ser usado em banco de dados paralelos, como Oracle Parallel Server ou Middle-R. Ambas, escrita e leitura, são balanceadas entre os \textit{backends}, deixando a replicação paralela dos bancos escrever.

\item \texttt{RAIDb-0:} particionamento completo de banco de dados (nenhuma tabela pode ser replicada) com política opcional que específica onde novas tabelas serão criadas.

\item \texttt{RAIDb-1:} espelhamento completo de banco de dados (todas as tabelas são replicadas em qualquer lugar) com política opcional que específica como a consumação de consultas distribuídas (write/commit/rollback) são manipuladas (quando o primeiro, a maioria ou todos os \textit{backends} completam as consultas).

\item \texttt{RAIDb-1ec:} espelhamento completo de banco de dados, como em RAIDb-1, mais verificação de erros para detecção de falhas bizarras.

\item \texttt{RAIDb-2:} replicação parcial (cada tabela deve ser replicada pelo menos 1 vez) com políticas opcionais para criação de novas tabelas (como RAIDb-0) e consumo de consultas distribuídas (como em RAIDb-1).

\item \texttt{RAIDb-2ec:} replicação parcial (como RAIDb-2) com verificação de detecção de erros bizarros.
\end{enumerate}

% O elemento balanceador de carga é definido como:
% \begin{verbatim}
% <!ELEMENT LoadBalancer (SingleDB | ParallelDB | RAIDb-0 |
%  RAIDb-1 | RAIDb-1ec | RAIDb-2 | RAIDb-2ec)>
% <!ATTLIST LoadBalancer
%    transactionIsolation (databaseDefault | readUncommitted |
%    readCommitted | repeatableRead | serializable) "databaseDefault">
% \end{verbatim}
% 
% \paragraph{Balanceamento de carga \texttt{SingleDB}}
% 
% O balanceador de carga \texttt{SingleDB} não necessita de nenhum parâmetro específico. A definição é:
% \begin{verbatim}
% <!ELEMENT SingleDB EMPTY>
% \end{verbatim}
% 
% \paragraph{Balanceamento de carga \texttt{ParallelDB}}
% 
% O balanceador de carga \texttt{ParallelDB} deve ser usado com um agendador de requisições \texttt{SingleDB}. Este balanceador de carga provê duas implementações: \texttt{ParallelDB-RoundRobin} e \texttt{ParallelDB-LeastPendingRequestFirst} que provêem políticas de round robin e menor número de consultas pendentes primeiro para balanceamento de carga, respectivamente. Este balanceador de carga é desenhado para prover balanceamento de carga e tolerância a falhas em cima de banco de dados paralelos como Oracle Parallel Server ou Middle-R. Isto significa que consultas de leitura e escrita são enviadas apenas para \textit{backends} ativos, o banco de dados paralelo é responsável por manter a consistência entre os \textit{backends}. A definição do elemento \texttt{ParallelDB} é:
% \begin{verbatim}
% <!ELEMENT ParallelDB (ParallelDB-RoundRobin |
% ParallelDB-LeastPendingRequestsFirst)>
% 
% <!ELEMENT ParallelDB-RoundRobin EMPTY>
% <!ELEMENT ParallelDB-LeastPendingRequestsFirst EMPTY>
% \end{verbatim}
% 
% Nenhum ajuste específico é requerido para estes balanceadores de carga. Não requerem análise de requisições o que significa que as requisições são apenas repassadas para os \textit{backends} (regras de reescritas ainda são aplicadas mas nenhuma transformação automática é realizada).
% 
% \paragraph{Balanceamento de carga \texttt{RAIDb-0}}
% 
% O balanceador de carga \texttt{RAIDb-0} aceita política para especificar onde novas tabelas serão criadas. A definição do elemento \texttt{RAIDb-0} é dada por:
% \begin{verbatim}
% <!ELEMENT RAIDb-0 (MacroHandling?,CreateTable*)>
% 
% <!ELEMENT CreateTable (BackendName*)>
% <!ATTLIST CreateTable 
%     tableName     CDATA #IMPLIED
%     policy        (random | roundRobin | all) #REQUIRED
%     numberOfNodes CDATA #REQUIRED
% >
%     
% <!-- BackendName simply identifies a backend by its logical name -->
% <!ELEMENT BackendName EMPTY>
% <!ATTLIST BackendName
%     name CDATA #REQUIRED>
% \end{verbatim}
% 
% Se \texttt{MacroHandling} é omitido, um padrão é inserido.
% 
% \texttt{CreateTable} define a política a ser adotada para criação de tabelas novas. Esta política baseia-se na lista de nós \texttt{BackendName} dada, que dever ser um subconjunto do conjunto completo de \textit{backends}. Se a lista for omitida, todos serão usados. Os atributos possuem os seguintes significados:
% 
% \begin{enumerate}[.]
% \item \texttt{numberOfNodes} representa o número de \textit{backends} que serão usados da lista \texttt{BackendName} para aplicação da política, devendo ser 1 para \texttt{RAIDb-0} e nunca maior que o número de nós declarados em \texttt{BackendName}.
% 
% \item \texttt{policy:} funciona da seguinte forma:
% \begin{enumerate}[.]
% \item \texttt{random:} \textit{backends} de \texttt{numberOfNodes} serão aleatoriamente tomados de \texttt{BackendName} e as tabelas neles criadas.
% 
% \item \texttt{roundRobin:} \textit{backends} de \texttt{numberOfNodes} serão tomados de \texttt{BackendName} através de algoritmo de round robin e as tabelas neles serão criadas.
% 
% \item \texttt{all:} as tabelas serão criadas em todos os nós de \texttt{BackendName}, \texttt{numberOfNodes} será ignorada.
% \end{enumerate}
% \end{enumerate}
% 
% Um exemplo de um controlador \texttt{RAIDb-0} com três nós onde novas tabelas são criadas aleatoriamente nos primeiros dois nós:
% \begin{verbatim}
% ...
% <DatabaseBackend name="node1" ...
% <DatabaseBackend name="node2" ...
% <DatabaseBackend name="node3" ...
% ...
% 
% <LoadBalancer>
%   <RAIDb-0>
%     <CreateTable policy="random" numberOfNodes="1">
%       <BackendName name="node1" />
%       <BackendName name="node2" />
%     </CreateTable>
%   </RAIDb-0>
% </LoadBalancer>
% \end{verbatim}
% 
% \paragraph{Balanceamento de carga \texttt{RAIDb-1: espelhamento completo}}
% 
% Um elemento \texttt{RAIDb-1} é definido como:
% \begin{verbatim}
% <!ELEMENT RAIDb-1 (WaitForCompletion?, MacroHandling?,
%  (RAIDb-1-RoundRobin | RAIDb-1-WeightedRoundRobin |
%   RAIDb-1-LeastPendingRequestsFirst))>
% 
% <!ELEMENT RAIDb-1-RoundRobin EMPTY>
% <!ELEMENT RAIDb-1-WeightedRoundRobin (BackendWeight)>
% <!ELEMENT RAIDb-1-LeastPendingRequestsFirst EMPTY>
% 
% <!ELEMENT WaitForCompletion EMPTY>
% <!ATTLIST WaitForCompletion
%     policy (first | majority | all) "first"
%     deadlockTimeoutInMs CDATA "30000"
% >
% 
% <!ELEMENT BackendWeight EMPTY>
% <!ATTLIST BackendWeight
%     name   CDATA #REQUIRED
%     weight CDATA #REQUIRED>
% \end{verbatim}
% 
% Se \texttt{WaitForCompletion} for omitido, o comportamento padrão é retornar o resultado tão logo um backend o tenha feito. \texttt{deadlockTimeout} define o tempo em milisegundos de espera antes de se comece a detecção de \textit{deadlocks}. Isto deve ser, tipicamente, maior que os ajustes de espera do banco de dados. O padrão é 30000ms mas é razoável que seja maior que o tempo de execução da maior consulta. 0 desabilita a detecção de deadlocks.
% 
% Se \texttt{MacroHandling} for omitido, um elemento \texttt{MacroHandling} padrão é adicionado.
% 
% \texttt{RAIDb-1} aceita política para especificar a conclusão de consultas distribuídas. Várias políticas de balanceamento de carga são propostas:
% \begin{enumerate}[.]
% \item \texttt{RoundRobin:} balanceamento round-robin simples. A primeira requisição é enviada para o primeiro nó, a segunda para o segundo, etc... Uma vez que se tenha enviado uma requisição para o último, a próxima será enviada para o primeiro backend e assim por diante.
% 
% \item \texttt{WeightRoundRobin:} o mesmo que é feito acima mas com um peso associado a cada backend. Um backend com peso 2 recebe 2 vezes mais requisições que um backend com peso 1.
% 
% \item \texttt{LeastPendingRequestFirst:} a requisição é enviada para o backend com o menor número de requisições pendentes.
% \end{enumerate}
% 
% A definição do elemento \texttt{RAIDb-1} é dada como seguinte:
% 
% \texttt{WaitForCompletition} define a política a ser adotada na espera de conclusão de requisição. A política funciona da seguinte forma:
% \begin{enumerate}[.]
% \item \texttt{first:} retorna o resultado tão logo um nó o tenha completo.
% 
% \item \texttt{mojority:} retorna o resultado tão logo a maioria dos nós (n/(2+1)) tenha o completo.
% 
% \item \texttt{all:} espera até que todos os nós tenham retornado o resultado para o cliente.
% \end{enumerate}
% 
% \paragraph{Balanceamento de carga \texttt{RAIDb-1ec}}
% 
% \texttt{RAIDb-1} com verificação de erro deve prover política de verificação de erro, como definida mais abaixo. A política opcional \texttt{WaitForCompletition} apenas diz respeito a requisições de escrita (INSERT,DELECT,UPDATE,commit,...).
% 
% \small{\textbf{Nota:} RAIDb-1ec não é operacional em Sequoia v1.alpha.}
% \normalsize
% A definição do elemento \texttt{RAIDb-1ec} é definida como:
% \begin{verbatim}
% <!ELEMENT RAIDb-1ec (WaitForCompletion?, ErrorChecking,
%  (RAIDb-1ec-RoundRobin | RAIDb-1ec-WeightedRoundRobin))>
% <!ATTLIST RAIDb-1ec
%     nbOfConcurrentReads CDATA #REQUIRED>
% 
% <!ELEMENT RAIDb-1ec-RoundRobin EMPTY>
% <!ELEMENT RAIDb-1ec-WeightedRoundRobin (BackendWeight)>
% 
% <!ELEMENT ErrorChecking EMPTY>
% <!ATTLIST ErrorChecking 
%     policy        (random | roundRobin | all) #REQUIRED
%     numberOfNodes CDATA #REQUIRED>
% \end{verbatim}
% 
% A política de verificação de erros (RAIDb-1ec e RAIDb-2ec) é usada para detecção de erros bizarros em nós, que ocorre quando um nó envia resultados estranhos de maneira não determinística. A verificação de erros permite que consultas de leitura sejam enviadas a mais de um banco de dados e os resultados são comparados. A maioria dos nós devem estar de acordo no resultado que será enviado ao cliente. A política de verificação de erros é definida por:
% \begin{enumerate}[.]
% \item \texttt{random:} os \textit{backends} em \texttt{numberOfNodes} são tomados randomicamente; a requisição de leitura é enviada a estes \textit{backends} e o resultado comparado.
% 
% \item \texttt{roundRobin:} \textit{backends} de \texttt{numberOfNodes} são tomados segundo algoritmo round robin; da mesma forma a consulta é enviada aos \textit{backends} e os resultados comparados.
% 
% \item \texttt{all:} a requisição é enviada a todos os \textit{backends} e os resultados comparados.
% \end{enumerate}
% 
% \texttt{numberOfNodes} deve ser maior ou igual a 3.
% 
% \paragraph{Balanceamento de carga \texttt{RAIDb-2: espelhamento distribuído}}
% 
% A definição do elemento \texttt{RAIDb-2} é definida como:
% \begin{verbatim}
% <!ELEMENT RAIDb-2 (CreateTable*, WaitForCompletion?, MacroHandling?,
%  (RAIDb-2-RoundRobin | RAIDb-2-WeightedRoundRobin |
%   RAIDb-2-LeastPendingRequestsFirst))>
% 
% 
% <!ELEMENT RAIDb-2-RoundRobin EMPTY>
% <!ELEMENT RAIDb-2-WeightedRoundRobin (BackendWeight)>
% <!ELEMENT RAIDb-2-LeastPendingRequestsFirst EMPTY>
% \end{verbatim}
% 
% Se \texttt{MacroHandling} for omitido, um elemento padrão \texttt{MacroHandling} é adicionado.
% 
% O balanceador de carga \texttt{RAIDb-2} aceita política que especifique onde novas tabelas serão criadas e como a conclusão de consultas distribuídas é manipulada. Várias políticas de balanceamento de carga são propostas:
% \begin{enumerate}[.]
% \item \texttt{RoundRobin:} balanceamento round-robin simples. A primeira requisição é enviada para o primeiro nó, a segunda para o segundo, etc... Uma vez que se tenha enviado uma requisição para o último, a próxima será enviada para o primeiro backend e assim por diante.
% 
% \item \texttt{WeightRoundRobin:} o mesmo que é feito acima mas com um peso associado a cada backend. Um backend com peso 2 recebe 2 vezes mais requisições que um backend com peso 1.
% 
% \item \texttt{LeastPendingRequestFirst:} a requisição é enviada para o backend com o menor número de requisições pendentes.
% \end{enumerate}
% 
% A definição do elemento \texttt{CreateTable} é dada na seção 10.6.4.3.
% 
% A definição do elemento \texttt{WaitForCompletition} é dada na seção 10.6.6.4
% 
% \paragraph{Balanceamento de carga \texttt{RAIDb-2ec}}
% 
% A política de verificação de erros de \texttt{RAIDb-2ec} é dada da mesma forma que para \texttt{RAIDb-1ec} (seção 10.6.4.5). Os outros elementos são similares aos definidos para controlador \texttt{RAIDb-2} (seção 10.6.4.6)
% 
% \small{\textbf{Nota:} RAIDb-2ec não é operacional em Sequoia v1.0alpha.}
% \normalsize
% 
% A definição do elemento \texttt{RAIDb-2ec} é dada como seguinte:
% \begin{verbatim}
% <!ELEMENT RAIDb-2ec (CreateTable*, WaitForCompletion?, ErrorChecking,
%                      (RAIDb-2ec-RoundRobin |
% 		      RAIDb-2ec-WeightedRoundRobin))>
% <!ATTLIST RAIDb-2ec 
%     nbOfConcurrentReads CDATA #REQUIRED
% >
% 
% <!ELEMENT RAIDb-2ec-RoundRobin EMPTY>
% <!ELEMENT RAIDb-2ec-WeightedRoundRobin (BackendWeight)>
% \end{verbatim}



\subsection{ParGRES}

ParGRES\cite{pargres} é um projeto que tem como objetivo desenvolver um sistema em \textit{software} livre para processar com eficiência consultas pesadas que envolvam grandes quantidades de dados, usando para isso, o SGBD PostgreSQL sobre clusters de PCs. No ParGRES, o processamento da consulta explora o paralelismo intra- e inter-consultas, usando replicação e fragmentação virtual de dados.


O paralelismo do ParGRES é voltado para as consultas pesadas típicas de aplicações OLAP e é proposta uma solução para essa demanda através da implementação de paralelismo intra-consulta em um cluster de Banco de Dados. O paralelismo intra-consulta significa decompor consultas complexas em sub-consultas que serão executadas em paralelo. A idéia é que cada sub-consulta atue em um fragmento de dados diferente. Dessa forma, cada sub-consulta poderá então ser enviada para o nó que possui o respectivo fragmento dos dados. Assim, cada sub-consulta é enviada para um nó diferente e executada em paralelo com as demais. Embora o desenvolvimento tenha sido realizado sobre o PostgreSQL, o paralelismo é baseado no padrão SQL, não sendo dependente de nenhuma característica específica do SGBD (vide \cite{pargrespaper}).

Como as demais soluções para clusters de bancos de dados, o ParGRES consiste em
uma camada intermediária de \textit{software} (\textit{middleware}) que orquestra instâncias de
SGBDs em execução nos diferentes nós do cluster para a implementação de técnicas de
processamento paralelo.


% \section{Cluster para Paralelização de Consultas}
% 
% O desempenho em consultas e transações e uma característica importante para cluster não acadêmicos, assim, quais seriam as tecnologias que permitem uma grande escalabilidade nos clusters

% \subsection{Clusters para OLAP}
% 
% Clusters especializados para Data Warehouse
% 
% Um data warehouse (ou armazém de dados) é um sistema de computação utilizado para armazenar informação relativa às atividades de uma organização em bancos de dados, de forma consolidada. O desenho da base de dados favorece os relatórios e análise de grandes volumes de dados e obtenção de informações estratégicas que podem facilitar a tomada de decisão.
% 
% O data warehouse possibilita a análise de grandes volumes de dados, coletados dos sistemas transacionais (OLTP). São as chamadas séries históricas que possibilitam uma melhor análise de eventos passados para a tomada de decisões presentes e a previsão de eventos futuros. Por definição, os dados em um data warehouse não são voláteis, ou seja, eles não mudam, salvo quando é necessário fazer correções de dados previamente carregados. Os dados então são somente para leitura e não podem ser alterados.



