Extend the PHP MySQL Web Application Series 2

Source: Internet
Author: User
Keywords build php mysql web application php mysql applications simple database application in php mysql

In the previous article, it introduces the steps of PHP tuning and load balancing.

Delay from database

This method actually has only one major flaw (other than ensuring that it always communicates with the correct MySQL database), and that is the delay from the database. The slave database will not immediately have the same data as the master database. As mentioned earlier, any command that changes the database will basically be replayed on the slave database. This means that after an update on the master database, it will take a while (hopefully this is very short) for the slave database to reflect. Usually, this time is a few milliseconds, but if your server is overloaded, the latency from the database will increase greatly.

The main change to the code is that you cannot write to the main database and then immediately try to read it back. This is a common practice if you use SQL numeric operations, default values, or triggers in place. After initiating the write command, your code may not know the value on the server, so you want to read it back in order to continue processing. A common example is as follows:

<?php
$master->exec('update users set posts += 1');
$results = $slave->query('select posts from users');
?>

Even if the fastest setting can be achieved, the desired effect cannot be achieved. You cannot replay the update from the database before executing the query, you will get the wrong number of posts. Therefore, in such cases, you need to find workarounds. In the worst case, you can query the data on the main database, but this goes against the original intention of "isolation consideration". A better solution is to try to "estimate" the data. For example, in an example showing that a user newly added a post, you only need to read the number of posts first, and then manually add one before returning the value to the user. If an error happens to be caused by adding multiple posts at the same time, the error is limited to this one Web page. For other users who read the value, the database is correct.

Multiple MySQL slave databases
Now, the next logical step is to horizontally expand the capacity of the MySQL database by adding more slave databases. A master database can handle any number of slave computers—within some extreme limits. Although few systems will encounter this situation, the theoretical limitation is that a master database cannot handle a large number of slave databases.

As I said before, one of the benefits of using a master-slave configuration is isolation considerations. In addition, when most web applications generate each page, the operation of adding data is less than the demand for accessing data, so the read load is higher. This means that your scalability considerations are usually read access. This is exactly the problem of adding more slave databases. Each slave database added will increase the database capacity, just like adding more web servers to PHP.

Now, this will have a potential impact on you. How to determine which database to connect to? When you have only one database, the decision is simple. This is very simple even when there is only one slave database. But to properly balance the database load, you need to connect to many different servers.

One can deploy two main solutions to solve this problem. The first solution is to equip each Web server you have with a dedicated MySQL slave database. This is the simplest solution, and therefore the solution that is more commonly deployed. You can think of it as the following:

In the image above, you can see a load balancer with three web servers. Each Web server communicates with its own slave database, and these slave databases obtain data from a master database. It is very simple to determine which database the Web server is accessing, because it is no different from the single slave database scenario-you only need to configure each Web server to connect to a different database as its slave database.

However, when actually deploying this solution, another step is usually required: a computer is equipped to act as both a Web server and a slave database. This will greatly simplify the situation, because when connecting from the database will be directly connected to "localhost", thus achieving a built-in balance.

However, this simple method also has a very big drawback, so I always avoid it: you will eventually tie the scalability of the Web server to the MySQL slave database. Isolation considerations are still a big deal in the expansion task. The expansion requirements for the Web server and the slave database are usually independent of each other. Your application may only need three Web servers, but if the database is intensive, you need 20 slave databases. Or, in the case of PHP and logic intensive, you may need 3 slave databases and 20 web servers. If you bind the two together, you need to add a new Web server and a new slave database at the same time. This also means increased maintenance overhead.

Combining the Web server and the slave database on the same computer also means that you will over-utilize the resources of each computer. In addition, you cannot obtain specific hardware that meets the needs of each service. Generally, the requirements of the database computer (large and fast I/O) are different from the requirements of the PHP slave server (high-speed CPU).

The solution to the above problem is to cut off the relationship between the Web server and the MySQL slave database and randomize the connection between the two. In this case, each request sent to a Web server randomly (or using the selected algorithm) will choose to connect to a different slave database.

This method allows separate expansion of the Web server and the slave database. It even supports smart algorithms, which calculates which slave database to connect to according to the logic most suitable for the application.

There is another benefit not discussed: stability. Through random connection, you can stop a slave database so that your application will ignore it and choose another slave database to connect.

Usually, you need to write code in the application to select the database to connect to. There are some ways to avoid this task, for example, placing all slave databases behind a load balancer and then connecting to the load balancer. However, establishing logic in PHP code can give programmers the greatest future scalability. The following example shows some basic database selection code to accomplish this task:

<?php

class DB {
    // Configuration information:
    private static $user ='testUser';
    private static $pass ='testPass';
    private static $config = array(
        'write' =>
            array('mysql:dbname=MyDB;host=10.1.2.3'),
        'read' =>
            array('mysql:dbname=MyDB;host=10.1.2.7',
                  'mysql:dbname=MyDB;host=10.1.2.8',
                  'mysql:dbname=MyDB;host=10.1.2.9')
        );

    // Static method to return a database connection:
    public static function getConnection($server) {
        // First make a copy of the server array so we can modify it
        $servers = self::$config[$server];
        $connection = false;
        
        // Keep trying to make a connection:
        while (!$connection && count($servers)) {
            $key = array_rand($servers);
            try {
                $connection = new PDO($servers[$key],
self::$user, self::$pass);
            } catch (PDOException $e) {}
            
            if (!$connection) {
                // We couldn't connect. Remove this server:
                unset($servers[$key]);
            }
        }
        
        // If we never connected to any database, throw an exception:
        if (!$connection) {
            throw new Exception("Failed: {$server} database");
        }
        
        return $connection;
    }
}

// Do some work

$read = DB::getConnection('read');
$write = DB::getConnection('write');

...

?>

Of course, you may want (and should) make various enhancements to the above code before applying it to production. You may want to log connection failures for each database. The configuration should not be stored as a static class variable, because the configuration cannot be changed without changing the code. In addition, in this setting, all servers are treated equally. Consider the idea of increasing the "weight" of servers so that less traffic can be allocated to some servers. Finally, you may want to encapsulate this logic into a larger database abstraction class to provide you with greater flexibility.

to sum up
By following the steps in this article, you should be able to successfully build a scalable architecture for PHP applications. In fact, there is not only one solution, which means there is no one-size-fits-all solution. Similarly, there is not only one application solution or framework. Each application needs to solve different bottlenecks and different scaling problems.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.