For the database layer, scaling the database out to more instances is not as simples as just running multiple copies of the database instance. For the web and API
layers, the instances really do not need to know anything about the other instances in that layer. There could be a single, several or many web and API instances and the application would run the same way.
So, how can the database layer be improved? The database layer is scaled out, but it is scaled on a much smaller level. Where the web and API layers may have
hundreds of instances, the database layer may only have a few instances. The database instances often replicate data so that each instance is identical to the other. It is how the data is replicated that makes the database layer more complex. There are a couple different ways that the database layer can be put together to provide redundancy and increased performance.
One of the more popular methods for scaling the database layer is to run a Galera Cluster for MySQL. A Galera Cluster allows multiple MySQL instances to
communicate to each other and replicate data. It runs in multimaster mode, which means that read/write communication can occur with any instance in the cluster. When a transaction is committed, the data is replicated to all instances and
returns successfully only when that data was written to all of the databases successfully (see Figure 5.5).
Figure 5.5
Another method for scaling the database layer is to run a MySQL Cluster.
Generally, MySQL Clusters are setup in two different sets of nodes, the SQL nodes and the data nodes. The API layer talks to the SQL nodes, which determines where the data is stored and then makes the necessary queries to the appropriate data nodes. The data can be split into smaller chunks, called partitions, and stored on a subset of the data nodes. Replication occurs within pairs of data nodes within the cluster. The more data nodes there are, the more partitions there are, spreading the data across the entire cluster (see Figure 5.6).
Figure 5.6
One advantage of running a MySQL Cluster is that it can scale to more instances. The more instances that are added, the more the data can be spread across that cluster. However, MySQL Cluster is more sensitive to latencies and requires more CPU and network resources to run efficiently. The application may also need to be reworked to take advantage of the partitioning of data, otherwise, a single query could hit every data node and result in a potentially worse performance.
For Galera MySQL Cluster, it requires very little change from the application point of view. There is no data partitioning, so every instance has a complete copy of the data. This can also be a drawback, however, since the more instances there are in the cluster, the more data that has to be replicated to every other instance. This is generally why Galera Clusters are small, usually at least three instances, but not much larger. Another consideration when running a Galera Cluster is that there always has to be at least 50 percent of the instances running in the cluster at any point in time. If the cluster drops below 50 percent, the entire cluster stops and the database goes offline. It can sometimes be difficult to bring the cluster back online without making changes to the cluster configuration files. This is why a cluster needs to have at least three instances in it. If one instance is lost, there is
still majority in the cluster to keep it operational.
Yet another method combines the concept of a cluster above with multiple read- only databases on the back-end. This is typically called a write-master/read-slave setup. If the application needs to write data, the writes always go to the write- master database. If the application needs to read data, then the reads are farmed out to any number of available read-slaves. The write-master could be set up as a Galera Cluster or MySQL Cluster, which the read-slaves could be setup as
standalone MySQL servers in a non-clustered setup. It is not uncommon to see the read-slaves use caching software, such as with Memcached, to further speed up reads. A load balancer could be used to evenly distribute reads across all the read- slaves. When a read-slave is initially launched, it can pull down whatever data from the write-master it needs to have and once all the data is loaded and verified, it can add itself to the read-slave collective and take on traffic. This model is more complicated, but it does provide more flexibility in regards to scaling (see Figure 5.7).
Figure 5.7
The above examples use MySQL as the example database. Other databases can also be put into the OpenStack cloud as well, and with similar types of
configurations. For example, MongoDB and PostgreSQL support native clustering and replication. Some databases even have native support for the master-
write/read-slave model. In general, you should research what types of capabilities the chosen database solution has and take advantage of whatever high availability options it provides.
Finally, it would be remiss to point out another potential database layer
improvement, which is to take advantage of Database-as-a-Service (DBaaS). In OpenStack, this is Trove, which was discussed previously in Chapter 2. If there is a DBaaS solution available for the OpenStack cloud, take a look at what features it provides and how it can be leveraged in the application. Offloading the database piece to another service simplifies the application tremendously and provides the additional high availability and data protection needed without having to reinvent the wheel.