One place for hosting & domains

      Cache

      How To Speed Up Static Web Pages with Varnish Cache Server on Ubuntu 20.04


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Varnish is a versatile reverse HTTP proxy that caches responses from backend servers in memory so they are served quickly when requested again. It uses HTTP headers to determine whether to cache the responses to a particular request. By default, it does not cache responses with cookies because those are considered client-specific requests; however you can change this setting in the configuration file.

      Besides acting as a caching server, Varnish can be used as a:

      • Web application firewall
      • DDoS attack defender
      • Load balancer
      • Quick fix for unstable backends
      • HTTP router

      There are three locations where the HTTP cache can be saved:

      • Browser: This cache is saved on users’ browsers. It is user-specific and can be used to serve content instead of sending requests to web sites.
      • Proxy: A proxy is an intermediate server that sits between users and servers. It is usually deployed by ISPs and can be used to cache responses that will be requested by multiple users.
      • Reverse Proxy: This kind of proxy is created by the web site’s administrator and can be used to serve content from the network’s edge instead of sending requests to back end servers. This is the kind of cache you will create in this tutorial.

      Note: For more information about HTTP caching, see this tutorial on HTTP headers and caching strategies.

      In this tutorial, you will set up Varnish as a caching reverse proxy server. You’ll then test the setup with Varnish against a non-caching configuration using wrk.

      Prerequisites

      To complete this tutorial, you will need:

      Step 1 — Installing Varnish And Apache

      To start, you’ll install Apache and Varnish. First update apt-get, and then install Apache with these commands:

      • sudo apt-get update
      • sudo apt-get install apache2 -y

      You’ll see output indicating that Apache is being installed.

      After the Apache installation process is complete, install Varnish with this command:

      • sudo apt-get install varnish -y

      You’ll see output indicating that Varnish is being installed.

      Next, make sure both packages installed correctly. First, use this command to check the status of Apache:

      • sudo systemctl status apache2

      The output will look similar to this:

      Output

      root@ubuntu-s-1vcpu-2gb-fra1-01:~# sudo systemctl status apache2 ● apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2021-08-04 18:58:39 UTC; 4min 10s ago Docs: https://httpd.apache.org/docs/2.4/ Main PID: 2279 (apache2) Tasks: 55 (limit: 2344) Memory: 5.0M CGroup: /system.slice/apache2.service ├─2279 /usr/sbin/apache2 -k start ├─2281 /usr/sbin/apache2 -k start └─2282 /usr/sbin/apache2 -k start Aug 04 18:58:39 ubuntu-s-1vcpu-2gb-fra1-01 systemd[1]: Starting The Apache HTTP Server... Aug 04 18:58:39 ubuntu-s-1vcpu-2gb-fra1-01 apachectl[2278]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' di> Aug 04 18:58:39 ubuntu-s-1vcpu-2gb-fra1-01 systemd[1]: Started The Apache HTTP Server.

      Press the Q key to exit the status command.

      Next, check the status of Varnish with this command:

      • sudo systemctl status varnish

      The output will look similar to this:

      Output

      root@ubuntu-s-1vcpu-2gb-fra1-01:~# sudo systemctl status varnish ● varnish.service - Varnish HTTP accelerator Loaded: loaded (/lib/systemd/system/varnish.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2021-08-04 18:59:09 UTC; 4min 41s ago Docs: https://www.varnish-cache.org/docs/6.1/ man:varnishd Main PID: 3423 (varnishd) Tasks: 217 (limit: 2344) Memory: 10.7M CGroup: /system.slice/varnish.service ├─3423 /usr/sbin/varnishd -j unix,user=vcache -F -a :6081 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m └─3447 /usr/sbin/varnishd -j unix,user=vcache -F -a :6081 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m Aug 04 18:59:09 ubuntu-s-1vcpu-2gb-fra1-01 systemd[1]: Started Varnish HTTP accelerator. Aug 04 18:59:10 ubuntu-s-1vcpu-2gb-fra1-01 varnishd[3423]: Debug: Version: varnish-6.2.1 revision 9f8588e4ab785244e06c3446fe09bf9db5dd8753 Aug 04 18:59:10 ubuntu-s-1vcpu-2gb-fra1-01 varnishd[3423]: Version: varnish-6.2.1 revision 9f8588e4ab785244e06c3446fe09bf9db5dd8753 Aug 04 18:59:10 ubuntu-s-1vcpu-2gb-fra1-01 varnishd[3423]: Debug: Platform: Linux,5.4.0-73-generic,x86_64,-junix,-smalloc,-sdefault,-hcritbit Aug 04 18:59:10 ubuntu-s-1vcpu-2gb-fra1-01 varnishd[3423]: Platform: Linux,5.4.0-73-generic,x86_64,-junix,-smalloc,-sdefault,-hcritbit Aug 04 18:59:10 ubuntu-s-1vcpu-2gb-fra1-01 varnishd[3423]: Debug: Child (3447) Started Aug 04 18:59:10 ubuntu-s-1vcpu-2gb-fra1-01 varnishd[3423]: Child (3447) Started Aug 04 18:59:10 ubuntu-s-1vcpu-2gb-fra1-01 varnishd[3423]: Info: Child (3447) said Child starts Aug 04 18:59:10 ubuntu-s-1vcpu-2gb-fra1-01 varnishd[3423]: Child (3447) said Child starts

      If you do not see both services up and running, wait a few minutes until they are fully loaded, and keep both of them running.

      Now that you have Apache2 Varnish, installed, you’ll give Varnish something to serve, in this case Apache’s static web page.

      Step 2 — Configuring Varnish To Serve Apache’s Static Web Page

      In the previous step, you installed Varnish, and next you’ll need to configure it. By default, Varnish listens on port 6081 and connects to a local web server on port 8080. You’ll change that to serve the Apache static site from Apache server.

      First, you’ll change Varnish’s listening port to 8080. Usually you would want the listening port to be 80, but because you are running Apache and Varnish on the same server, you’ll use port 8080 for Varnish and port 80 for Apache.

      There is no configuration option to change the listening port for Varnish, so you’ll do it using the command line. You’ll create a file called customexec.conf in a new directory called varnish.service.d in /etc/systemd/system/ that will change the default ports.

      Use the mkdir command to create the new directory:

      • sudo mkdir /etc/systemd/system/varnish.service.d

      Use your favorite text editor to create a new file called customexec.conf :

      • sudo nano /etc/systemd/system/varnish.service.d/customexec.conf

      In customexec.conf, add the following content:

      /etc/systemd/system/varnish.service.d/customexec.conf file

      [Service] ExecStart= ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F -a :8080 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m

      In this file you are changing the Service section of the Varnish configuration. First you remove the old value for the ExecStart option, and then you assign a new value for it.

      The new value specifies the binary file used to run Varnish with the following options:

      • -j: Specifies the jailing mechanism to use. Varnish jails are used to reduce the permissions for the varnish process over various platform-specific methods. Here you’re using the unix mechanism and the user vcache to limit the permissions. This is default for varnish on Ubuntu systems.

      • -F: Indicates that the server should run in the foreground, because systemd expects the main process to keep running so it can track it, and not fork a new process and die.

      • -a: This flag is used to specify the IP address and port for accepting client connections. The IP in this case is empty, which means the server will accept all IPs. The port is set to 8080.

      • -T: This flag specifies the IP address and port for management interface, in this case localhost and port 6082.

      • -f: This flag specifies the default VCL file for Varnish configuration. You will edit this file later in this tutorial to configure Varnish to connect to the Apache server.

      • -S: This flag specifies a shared secret file for authorizing access to the management interface. The /etc/varnish/secret value is the default for Varnish on Ubuntu. You will not use the secret file in this tutorial.

      • -s: This flag indicates where and how to store objects. The value malloc,256m is the default one for Vanish. It means to store various Varnish objects in memory using the malloc system call and a maximum size of 256 megabytes. Other possible values are default, which uses umem when malloc is not available, or file, which stores objects in a file on the disk.

      Save and close the customexec.conf file. Then execute this command to reload the systemd services file from disk:

      • sudo systemctl daemon-reload

      Then restart Varnish for changes to take effect.

      • sudo systemctl restart varnish

      You won’t see any output from these last two commands. To make sure that Varnish is now listening on port 8080, use the netstat command to display all listening TCP sockets on the server.

      • sudo netstat -ltnp | grep 8080

      You’ll see output that looks like this:

      Output

      tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 18689/varnishd tcp6 0 0 :::8080 :::* LISTEN 18689/varnishd

      Now that Varnish is running and listening to port 8080, you need to edit the default configuration file located at /etc/varnish/default.vcl:

      • sudo nano /etc/varnish/default.vcl

      Navigate to the backend default block, and then change .port to 80, as shown here:

      default.vcl file

      # Default backend definition. Set this to point to your content server. backend default { .host = "127.0.0.1"; .port = "80"; }

      Save and close the default.vcl file, then restart Varnish with this command:

      • sudo systemctl restart varnish

      If everything is fine, there won’t be any output. Open http://your_server_ip:8080 in your browser, and you’ll see the Apache static site, opened using Varnish.

      You now have Apache and Varnish running together on the same Droplet, with Apache listening to port 80 and Varnish to port 8080. Next, you’ll compare the response times of both servers using the wrk tool.

      Step 3 — Testing Varnish Using wrk

      wrk is a modern HTTP benchmarking tool. It is written in C, and can be used to load test web servers with many requests per second. In this step, you’ll use wrk to run tests against Apache and Varnish and then compare the results.

      First you’ll need to install wrk by building it from source. Start by installing some build tools for C and git, which are required for building wrk from source:

      • sudo apt-get install build-essential libssl-dev git unzip -y

      Then clone the git repository for wrk into the wrk directory:

      • git clone https://github.com/wg/wrk.git wrk

      Change to that new directory:

      Build the wrk executable with the make command:

      Copy wrk to the /usr/local/bin directory so you can access it from anywhere in your directory structure:

      • sudo cp wrk /usr/local/bin

      Now that you have wrk installed, use it to test the responsiveness of Apache with this command:

      • wrk -t2 -c1000 -d30s --latency http://server_ip/

      This command uses the following arguments:

      • -t2: This means run two threads.
      • -c1000: Keep 1000 HTTP connections open.
      • -d30s: Run the test for 30 seconds.
      • --latency: Print latency statistics.

      Wait 30 seconds until the test is done, and you’ll see output similar to this:

      output

      Running 30s test @ http://68.183.115.151/ 2 threads and 1000 connections Thread Stats Avg Stdev Max +/- Stdev Latency 44.45ms 104.50ms 1.74s 91.20% Req/Sec 8.29k 1.07k 12.40k 71.00% Latency Distribution 50% 11.59ms 75% 22.73ms 90% 116.16ms 99% 494.90ms 494677 requests in 30.04s, 5.15GB read Socket errors: connect 0, read 8369, write 0, timeout 69 Requests/sec: 16465.85 Transfer/sec: 175.45MB

      In this test, the average latency is 44.45ms, there were 494,677 total requests, 8,369 read errors, and 69 timeout errors. The exact numbers will vary in your installation.

      Now run the same test again for the Varnish server using this command:

      • wrk -t2 -c1000 -d30s --latency http://server_ip:8080/

      Wait 30 seconds until the test is done, and you’ll see output similar to this:

      output

      Running 30s test @ http://68.183.115.151:8080/ 2 threads and 1000 connections Thread Stats Avg Stdev Max +/- Stdev Latency 14.41ms 13.70ms 602.49ms 90.05% Req/Sec 6.67k 401.10 8.74k 83.33% Latency Distribution 50% 13.03ms 75% 17.69ms 90% 24.72ms 99% 58.22ms 398346 requests in 30.06s, 4.18GB read Socket errors: connect 0, read 19, write 0, timeout 0 Requests/sec: 13253.60 Transfer/sec: 142.48MB

      The output you see will likely be somewhat different, but the latency will be lower for Varnish than for Apache. In this case, the average latency is 14.41ms, there were 398,346 total requests, and no errors.

      In these tests, with Apache the average response time was 44.45ms with 8,438 errors, while Varnish achieved an increase in speed to 14.41ms, and also had no errors. This is because Varnish cached the response in memory and served it for later requests, unlike Apache, which needs to read from disk almost every time the resource is requested.

      Conclusion

      In this tutorial, you configured Varnish as a reverse proxy caching server for a static web site. You saw how to use basic HTTP caching to improve performance, and you used wrk to run load tests for the Apache and Varnish servers to compare the results.

      You’ve seen that the Varnish cache server speeds up your static site by serving content from main memory and not requesting it from the back end Apache server every time a new request arrives. For more information about other uses of Varnish, see the official documentation.



      Source link

      How To Set Up Redis as a Cache for MySQL with PHP on Ubuntu 20.04


      The author selected Girls Who Code to receive a donation as part of the Write for DOnations program.

      Introduction

      Redis (Remote Dictionary Server) is a fast open-source, in-memory database that you can use as a key-value store for a highly scalable and performance-oriented system. Some of Redis’ use cases include: caching, high-speed transactions, real-time analytics, live notifications, machine learning, searching, and queue/job processing. Since Redis is an in-memory key-value store, its performance makes it suitable for caching data in your application.

      Caching is storing data temporarily in a high-speed storage layer (for example, in a computer RAM) to serve data faster when clients make the same future requests. This enhances the re-use of previously computed data instead of fetching it each time from the disk.

      When you’re working with PHP and MySQL, using Redis as a cache improves your application performance because Redis stores data in RAM, which is several times faster than a hard disk (HDD) or a solid-state drive (SSD). Caching also reduces database costs—that is, the number of round trips made to the back-end database—and avoids overloading the backend.

      Caching data is an integral design feature when you’re designing web applications with higher reads than writes. Such applications include blogs, online stores, and social media sites.

      In this tutorial, you’ll use Redis to cache MySQL data with PHP on Ubuntu 20.04.

      Prerequisites

      To complete this tutorial, you’ll need the following:

      Step 1 — Installing the Redis Library for PHP

      To begin you’ll install the php-redis extension, which will allow you to use PHP to communicate with Redis. Run the following commands to update your server and install the extension:

      • sudo apt update
      • sudo apt install php-redis

      Confirm the installation and restart the Apache web server to load the extension:

      • sudo systemctl restart apache2

      Now that you have installed your dependencies, you’ll set up your database.

      Step 2 — Setting Up a Test Database, Table, and Sample Data

      In this step, you’ll create a MySQL database to store data permanently to disk. You’ll also create some tables and a user account with full privileges to the database.

      First, log in to your MySQL server as a root user:

      Enter the root password of your MySQL server that you set up in the LAMP prerequisite. Then, press ENTER to continue.

      Next, create a test_store database with the following command:

      • CREATE database test_store;

      Make sure the action is successful by confirming the output:

      Output

      Query OK, 1 row affected (0.00 sec)

      Next, create a user for your database. We’ll call this user test_user in this tutorial. Replace PASSWORD with a strong password as well:

      • CREATE USER 'test_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'PASSWORD';

      Then grant test_user full privileges to the test_store database with:

      • GRANT ALL PRIVILEGES ON test_store.* TO 'test_user'@'localhost';

      Finally run the following command to reload the grant tables in MySQL:

      Ensure you get the following output after each successful command:

      Output

      Query OK, 0 rows affected (0.01 sec)

      End the MySQL root session:

      You’ll receive the word Bye and the system will take you back to the server’s command line interface.

      Log back in to the MySQL server with the credentials for the test_user that you just created:

      Enter the password for the test_user to proceed. Then, switch to the test_store database when you’re in the mysql> prompt:

      Ensure you receive the following output:

      Output

      Database Changed.

      Next, you’ll create a products table with three columns. You’ll use the product_id column to uniquely identify each product. To avoid assigning the IDs manually, you’ll use the AUTO_INCREMENT keyword. Then, you’ll use the BIGINT data type for the product_id column to support a large data set. The BIGINT data type can hold a minimum value of -2^63 and a maximum value of 2^63 - 1.

      The product_name field will hold the actual names of your items. In this case, a VARCHAR data type with a length of 50 characters will be enough. The last column in the products table is the price—you’ll use the DOUBLE data type to accommodate prices with decimals (for example, 16.33).

      To create the products table, run the following command:

      • CREATE table products
      • (
      • product_id BIGINT PRIMARY KEY AUTO_INCREMENT,
      • product_name VARCHAR(50),
      • price DOUBLE
      • ) Engine = InnoDB;

      You will receive the following output:

      Output

      Query OK, 0 rows affected (0.01 sec)

      Now you’ll populate the products table with some records for testing purposes.

      You don’t need to enter data to the product_id column manually since the AUTO_INCREMENT column will complete this. Run the following commands one by one:

      • INSERT INTO products(product_name, price) VALUES ('Virtual Private Servers', '5.00');
      • INSERT INTO products(product_name, price) VALUES ('Managed Databases', '15.00');
      • INSERT INTO products(product_name, price) VALUES ('Block Storage', '10.00');
      • INSERT INTO products(product_name, price) VALUES ('Managed Kubernetes', '60.00');
      • INSERT INTO products(product_name, price) VALUES ('Load Balancer', '10.00');

      After running each command, ensure you get this output:

      Output

      Query OK, 1 row affected (0.00 sec)

      Verify the data using the SELECT command:

      You will receive output similar to the following:

      Output

      +------------+-------------------------+-------+ | product_id | product_name | price | +------------+-------------------------+-------+ | 1 | Virtual Private Servers | 5 | | 2 | Managed Databases | 15 | | 3 | Block Storage | 10 | | 4 | Managed Kubernetes | 60 | | 5 | Load Balancer | 10 | +------------+-------------------------+-------+ 5 rows in set (0.00 sec)

      End the MySQL session for the test_user:

      Once you’ve set up the test_store database, products table, and test_user, you’ll code a PHP script to retrieve data from the MySQL database and cache it to Redis.

      Step 3 — Designing a PHP Script for Fetching and Caching MySQL Data

      In this step, you’ll create a PHP script for retrieving the sample data that you’ve created in the previous step.

      When you run the script for the first time, it will read the data from MySQL (that is, from disk) and then cache it to Redis. As a result subsequent reads of the products’ data will be from Redis (that is, from system RAM). System memory is multiple times faster than even the fastest solid-state drive, thus data will be retrieved faster from the Redis cache than reading from the system disk.

      Note: While you might not get any performance boost, since you are retrieving just a few records from the MySQL database, several benchmarks prove that retrieving cached data from Redis is several times faster than reading it from MySQL when dealing with several hundred thousand records.

      Create a products.php file in the root directory of your website:

      • sudo nano /var/www/html/products.php

      To start, enter the following information to connect and create an instance of Redis and store it as an object in a $redis variable.

      The address 127.0.0.1 connects to the localhost. You may change this value if you’re running Redis from a remote server. Remember to replace REDIS_PASSWORD with the specific password for Redis set in the /etc/redis/redis.conf configuration file.

      Also, enter the appropriate port number. By default, Redis runs on port 6379:

      /var/www/html/products.php

      <?php
      
      $redis = new Redis();
      $redis->connect('127.0.0.1', 6379);
      $redis->auth('REDIS_PASSWORD');
      

      Note: In this guide, the $redis->auth('REDIS_PASSWORD') command sends your password to Redis in plain text. In a production environment, you may consider securing end-to-end communication between Redis and the client server running PHP code with a more powerful access control layer, such as TLS (Transport Layer Security). Also, when configuring your Redis password in the /etc/redis/redis.conf file, make sure you set a long and strong value to prevent brute-force attacks.

      The next step is initializing a PHP variable you’ll use as a key in Redis.

      As mentioned earlier in this guide, Redis acts as a key-value database and therefore you must have a unique key for the data that you intend to store and retrieve from it.

      So, define a PRODUCTS key by adding the following information to the /var/www/html/products.php file. You are free to use any name in place of PRODUCTS key.

      Your PHP script will use this key to cache information to Redis once data gets retrieved from the MySQL database:

      /var/www/html/products.php

      ...
      $key = 'PRODUCTS';
      

      Next, include a conditional PHP if...else statement to check if the PRODUCTS key exists in Redis:

      /var/www/html/products.php

      ...
      if (!$redis->get($key)) {
          $source="MySQL Server";
          $database_name="test_store";
          $database_user="test_user";
          $database_password = 'PASSWORD';
          $mysql_host="localhost";
      
          $pdo = new PDO('mysql:host=" . $mysql_host . "; dbname=" . $database_name, $database_user, $database_password);
          $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      
          $sql  = "SELECT * FROM products";
          $stmt = $pdo->prepare($sql);
          $stmt->execute();
      
          while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
             $products[] = $row;
          }
      
          $redis->set($key, serialize($products));
          $redis->expire($key, 10);
      
      } else {
           $source = "Redis Server';
           $products = unserialize($redis->get($key));
      
      }
      
      echo $source . ': <br>';
      print_r($products);
      

      If the key doesn’t exist in Redis, the script connects to the database that you created earlier, queries the products table, and stores the data in Redis using the $redis->set($key, serialize($products)) command.

      The $redis->expire($key, 10); command sets the expiration to 10 seconds. You may tweak this value depending on your cache policy.

      The $source variable helps you to identify the source of the data once it is echoed as an array at the end of the script using the echo $source and print_r($products) commands.

      Once you’ve put everything together, your /var/www/html/products.php file will be as follows:

      /var/www/html/products.php

      <?php
      
      $redis = new Redis();
      $redis->connect('127.0.0.1', 6379);
      $redis->auth('REDIS_PASSWORD');
      
      $key = 'PRODUCTS';
      
      if (!$redis->get($key)) {
          $source="MySQL Server";
          $database_name="test_store";
          $database_user="test_user";
          $database_password = 'PASSWORD';
          $mysql_host="localhost";
      
          $pdo = new PDO('mysql:host=" . $mysql_host . "; dbname=" . $database_name, $database_user, $database_password);
          $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      
          $sql  = "SELECT * FROM products";
          $stmt = $pdo->prepare($sql);
          $stmt->execute();
      
          while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
             $products[] = $row;
          }
      
          $redis->set($key, serialize($products));
          $redis->expire($key, 10);
      
      } else {
           $source = "Redis Server';
           $products = unserialize($redis->get($key));
      
      }
      
      echo $source . ': <br>';
      print_r($products);
      
      

      Save and close the file.

      You’ve now set up a PHP script that will connect to MySQL and cache data to Redis. You’ll test your script in the next step.

      Step 4 — Testing the PHP Script

      To test if Redis is caching data from the MySQL database, you’ll enter the path of the PHP script in a browser window. Remember to replace your_server_IP with the public IP address of your server, like so: http://your_server_IP/products.php.

      When you run the script for the first time, you will receive the following output that displays data from the MySQL database because, at this point, the PHP script has not yet cached any data in Redis:

      MySQL Server
      Array ( [0] => Array ( [product_id] => 1 [product_name] => Virtual Private Servers [price] => 5 ) [1] => Array ( [product_id] => 2 [product_name] => Managed Databases [price] => 15 ) [2] => Array ( [product_id] => 3 [product_name] => Block Storage [price] => 10 ) [3] => Array ( [product_id] => 4 [product_name] => Managed Kubernetes [price] => 60 ) [4] => Array ( [product_id] => 5 [product_name] => Load Balancer [price] => 10 ) )
      

      Once you run the script again, you’ll get an output confirming that it’s reading data from Redis, which is acting as a cache for MySQL.

      Redis Server
      Array ( [0] => Array ( [product_id] => 1 [product_name] => Virtual Private Servers [price] => 5 ) [1] => Array ( [product_id] => 2 [product_name] => Managed Databases [price] => 15 ) [2] => Array ( [product_id] => 3 [product_name] => Block Storage [price] => 10 ) [3] => Array ( [product_id] => 4 [product_name] => Managed Kubernetes [price] => 60 ) [4] => Array ( [product_id] => 5 [product_name] => Load Balancer [price] => 10 ) )
      

      Remember that the key will expire after 10 seconds and data will again be retrieved from MySQL.

      Conclusion

      In this guide, you’ve used Redis to cache MySQL data with PHP on Ubuntu 20.04. You may use the coding in this guide to set up a caching mechanism for your MySQL data, which is especially useful for high-traffic web applications.

      You can check out our Redis topic page for more educational resources. Or, learn more about coding in PHP with further tutorials and content on the PHP topic page.



      Source link

      Como otimizar consultas do MySQL com o cache do ProxySQL no Ubuntu 16.04


      O autor selecionou a Free Software Foundation para receber uma doação como parte do programa Write for DOnations.

      Introdução

      O ProxySQL é um servidor proxy com reconhecimento de SQL que pode ser posicionado entre seu aplicativo e seu banco de dados. Ele oferece muitos recursos, como o de balancear carga entre vários servidores de MySQL e servir como uma camada de cache para consultas. Este tutorial irá se concentrar no recurso de cache do ProxySQL e como ele pode otimizar as consultas para o seu banco de dados do MySQL.

      O cache do MySQL ocorre quando o resultado de uma consulta é armazenado para que, quando essa consulta for repetida, o resultado possa ser retornado sem a necessidade de classificar o banco de dados. Isso pode aumentar significativamente a velocidade das consultas comuns. Em muitos métodos de cache, porém, os desenvolvedores precisam modificar o código do seu aplicativo, o que poderia introduzir um bug na base de códigos. Para evitar essa prática propensa a erros, o ProxySQL permite que você configure o cache transparente.

      No cache transparente, apenas os administradores do banco de dados precisam alterar a configuração do ProxySQL para habilitar o cache para as consultas mais comuns. Tais alterações podem ser feitas através da interface de administrador do ProxySQL. Tudo o que o desenvolvedor precisa fazer é conectar-se ao proxy que reconhece o protocolo. O proxy decidirá se a consulta pode ser atendida a partir do cache sem chegar ao servidor de back-end.

      Neste tutorial, você usará o ProxySQL para configurar o cache transparente de um servidor MySQL no Ubuntu 16.04. Em seguida, você testará seu desempenho usando o mysqlslap – com e sem o cache, no intuito de demonstrar o efeito do cache e quanto tempo ele pode poupar na execução de várias consultas semelhantes.

      Pré-requisitos

      Antes de iniciar este guia, você precisará do seguinte:

      Passo 1 — Instalando e configurando o servidor MySQL

      Primeiro, você instalará o servidor MySQL e o configurará para ser usado pelo ProxySQL como um servidor de back-end para atender consultas de clientes.

      No Ubuntu 16.04, o mysql-server pode ser instalado usando este comando:

      • sudo apt-get install mysql-server

      Pressione Y para confirmar a instalação.

      Em seguida, você será solicitado a digitar sua senha de usuário root do MySQL. Digite uma senha forte e salve-a para usar mais tarde.

      Agora que você tem seu servidor MySQL pronto, irá configurá-lo para que o ProxySQL funcione corretamente. Você precisa adicionar um usuário monitor para o ProxySQL monitorar o servidor MySQL, uma vez que o ProxySQL escuta o servidor de back-end através do protocolo da SQL, em vez de usar uma conexão TCP ou pedidos pelo método GET do HTTP – para garantir que o back-end esteja funcionando. O monitor usará uma conexão SQL fictícia para determinar se o servidor está ativo ou não.

      Primeiro, faça login no shell do MySQL:

      O parâmetro -uroot, conecta você através do usuário root do MySQL e o -p solicita a senha do usuário root. Esse usuário root é diferente do usuário root do seu servidor e a senha é a que você digitou quando instalou o pacote mysql-server.

      Digite a senha do root e pressione ENTER.

      Agora, você criará dois usuários, um chamado monitor para o ProxySQL e outro que você usará para executar consultas de clientes e conceder-lhes os privilégios corretos. Este tutorial nomeará esse usuário como sammy.

      Crie o usuário monitor:

      • CREATE USER 'monitor'@'%' IDENTIFIED BY 'monitor_password';

      A consulta CREATE USER é usada para criar um novo usuário que pode se conectar a partir de IPs específicos. Usar % denota que o usuário pode se conectar a partir de qualquer endereço IP. IDENTIFIED BY define a senha para o novo usuário; digite qualquer senha que quiser, mas certifique-se de lembrá-la para uso posterior.

      Com o usuário monitor criado, crie o usuário sammy:

      • CREATE USER 'sammy'@'%' IDENTIFIED BY 'sammy_password';

      Em seguida, conceda privilégios aos seus novos usuários. Execute o seguinte comando para configurar o monitor:

      • GRANT SELECT ON sys.* TO 'monitor'@'%';

      A consulta GRANT é usada para dar privilégios aos usuários. Aqui, você concedeu privilégios somente de SELECT em todas as tabelas no banco de dados sys para o usuário monitor; ele precisa apenas desse privilégio para escutar o servidor de back-end.

      Agora, conceda ao usuário sammy todos os privilégios em relação a todos os bancos de dados:

      • GRANT ALL PRIVILEGES on *.* TO 'sammy'@'%';

      Isso permitirá que o sammy faça as consultas necessárias para testar seu banco de dados mais tarde.

      Aplique as alterações de privilégios, executando o seguinte:

      Por fim, saia do shell do mysql:

      Agora, você instalou o mysql-server e criou um usuário para ser usado pelo ProxySQL para monitorar seu servidor MySQL e outro para executar consultas de clientes. Em seguida, você instalará e configurará o ProxySQL.

      Passo 2 — Instalando e configurando o servidor ProxySQL

      Agora, você pode instalar o servidor ProxySQL, que será usado como uma camada de cache para as suas consultas. Uma camada de cache existe como uma parada entre os servidores do seu aplicativo e os servidores de back-end do banco de dados; ela é usada para se conectar ao banco de dados e salvar os resultados de algumas consultas em sua memória para acesso rápido mais tarde.

      A página de lançamentos do ProxySQL no Github oferece arquivos de instalação para distribuições comuns do Linux. Para este tutorial, você usará o wget para baixar o arquivo de instalação do ProxySQL versão 2.0.4 do, Debian:

      • wget https://github.com/sysown/proxysql/releases/download/v2.0.4/proxysql_2.0.4-ubuntu16_amd64.deb

      Em seguida, instale o pacote usando o dpkg:

      • sudo dpkg -i proxysql_2.0.4-ubuntu16_amd64.deb

      Assim que estiver instalado, inicie o ProxySQL com este comando:

      • sudo systemctl start proxysql

      Verifique se o ProxySQL iniciou corretamente com este comando:

      • sudo systemctl status proxysql

      Você receberá um resultado semelhante a este:

      Output

      root@ubuntu-s-1vcpu-2gb-sgp1-01:~# systemctl status proxysql ● proxysql.service - LSB: High Performance Advanced Proxy for MySQL Loaded: loaded (/etc/init.d/proxysql; bad; vendor preset: enabled) Active: active (exited) since Wed 2019-06-12 21:32:50 UTC; 6 months 7 days ago Docs: man:systemd-sysv-generator(8) Tasks: 0 Memory: 0B CPU: 0

      Agora, é hora de conectar o seu servidor ProxySQL ao servidor MySQL. Para tanto, utilize a interface administrativa SQL do ProxySQL, a qual, por padrão, escuta a porta 6032 no localhost e tem admin como seu nome de usuário e senha.

      Conecte-se à interface executando o seguinte:

      • mysql -uadmin -p -h 127.0.0.1 -P6032

      Digite admin quando for solicitado a inserir uma senha.

      -uadmin define o nome de usuário como admin e o sinalizador -h especifica o host como localhost. A porta é 6032, especificada com o sinalizador -P.

      Aqui, você teve que especificar claramente o host e a porta porque, por padrão, o cliente MySQL se conecta usando um arquivo de socket local e a porta 3306.

      Agora que você se conectou ao shell mysql como admin, configure o usuário monitor para que o ProxySQL possa usá-lo. Primeiro, use consultas SQL padrão para definir os valores de duas variáveis globais:

      • UPDATE global_variables SET variable_value='monitor' WHERE variable_name='mysql-monitor_username';
      • UPDATE global_variables SET variable_value='monitor_password' WHERE variable_name='mysql-monitor_password';

      A variável mysql-monitor_username especifica o nome de usuário do MySQL que será usado para verificar se o servidor de back-end está ativo ou não. A variável mysql-monitor_password aponta para a senha que será usada ao se conectar ao servidor de back-end. Use a senha que criou para o nome de usuário monitor.

      Toda vez que fizer uma alteração na interface administrativa do ProxySQL, precisará usar o comando LOAD (carregar) correto para aplicar as alterações na instância do ProxySQL em execução. Você alterou variáveis globais do MySQL,assim, carregue-as no RUNTIME para aplicar as alterações:

      • LOAD MYSQL VARIABLES TO RUNTIME;

      Em seguida, SAVE (salve) as alterações no banco de dados em disco para manter as alterações entre as reinicializações. O ProxySQL usa seu próprio banco de dados do SQLite local para armazenar suas próprias tabelas e variáveis:

      • SAVE MYSQL VARIABLES TO DISK;

      Agora, você dirá ao ProxySQL sobre o servidor de back-end. A tabela mysql_servers detém as informações sobre cada servidor de back-end ao qual o ProxySQL pode conectar-se e onde pode executar consultas. Assim, adicione um novo registro usando uma instrução SQL padrão INSERT, com os seguintes valores para hostgroup_id, hostname e port:

      • INSERT INTO mysql_servers(hostgroup_id, hostname, port) VALUES (1, '127.0.0.1', 3306);

      Para aplicar as alterações, execute LOAD e SAVE novamente:

      • LOAD MYSQL SERVERS TO RUNTIME;
      • SAVE MYSQL SERVERS TO DISK;

      Por fim, você dirá ao ProxySQL qual usuário se conectará ao servidor de back-end; defina o sammy como o usuário e substitua sammy_password pela senha que criou anteriormente:

      • INSERT INTO mysql_users(username, password, default_hostgroup) VALUES ('sammy', 'sammy_password', 1);

      A tabela mysql_users contém informações sobre os usuários usados para se conectar aos servidores de back-end; você especificou o username (nome de usuário), password (senha) e default_hostgroup (grupo de host padrão).

      LOAD e SAVE as alterações:

      • LOAD MYSQL USERS TO RUNTIME;
      • SAVE MYSQL USERS TO DISK;

      Então, saia do shell do mysql:

      Para testar se você consegue se conectar ao seu servidor de back-end usando o ProxySQL, execute a seguinte consulta teste:

      • mysql -usammy -h127.0.0.1 -p -P6033 -e "SELECT @@HOSTNAME as hostname"

      Nesse comando, você usou o sinalizador -e para executar uma consulta e fechar a conexão. A consulta imprime o nome do host do servidor de back-end.

      Nota: por padrão, o ProxySQL usa a porta 6033 para escutar as conexões de entrada.

      O resultado ficará parecido com este, sendo o your_hostname substituído pelo seu nome de host:

      Output

      +----------------------------+ | hostname | +----------------------------+ | your_hostname | +----------------------------+

      Para aprender mais sobre a configuração do ProxySQL, consulte o Passo 3 sobre Como usar o ProxySQL como um balanceador de carga para o MySQL no Ubuntu 16.04.

      Até aqui, você configurou o ProxySQL para usar seu servidor MySQL como um back-end e se conectou ao back-end usando o ProxySQL. Agora,você está pronto para usar o mysqlslap para comparar o desempenho das consultas sem cache.

      Passo 3 — Testando o uso do mysqlslap sem o cache

      Neste passo, você fará download de um banco de dados de teste para que possa executar consultas nele com o mysqlslap, no intuito de testar a latência sem o armazenamento em cache, definindo um parâmetro de comparação para a velocidade das suas consultas. Você também irá explorar como o ProxySQL mantém os registros das consultas na tabela stats_mysql_query_digest.

      O mysqlslap é um cliente de emulação de carga que é usado como uma ferramenta de teste de carga para o MySQL. Ele pode testar um servidor MySQL com consultas geradas automaticamente ou com algumas consultas personalizadas, executadas em um banco de dados. Ele vem instalado no pacote do cliente MySQL, de modo que não é necessário instalá-lo; em vez disso, você irá baixar um banco de dados apenas para fins de teste, no qual você poderá usar o mysqlslap.

      Neste tutorial, você usará uma amostra de banco de dados de funcionários. Você vai usar essa amostra de banco de dados de funcionários porque ela apresenta um conjunto grande de dados que pode ilustrar as diferenças na otimização das consultas. O banco de dados tem seis tabelas, mas os dados que ele contém têm mais de 300.000 registros de funcionários. Isso ajudará você a emular uma carga de trabalho de produção em grande escala.

      Para baixar o banco de dados, clone primeiro o repositório do Github usando este comando:

      • git clone https://github.com/datacharmer/test_db.git

      Em seguida, acesse o diretório test_db e carregue o banco de dados no servidor MySQL usando estes comandos:

      • cd test_db
      • mysql -uroot -p < employees.sql

      Esse comando usa o redirecionamento da shell para ler as consultas em SQL no arquivo employees.sql e as executa no servidor MySQL para criar a estrutura do banco de dados.

      Você verá um resultado como este:

      Output

      INFO CREATING DATABASE STRUCTURE INFO storage engine: InnoDB INFO LOADING departments INFO LOADING employees INFO LOADING dept_emp INFO LOADING dept_manager INFO LOADING titles INFO LOADING salaries data_load_time_diff 00:00:32

      Assim que o banco de dados for carregado no seu servidor MySQL, teste se o mysqlslap está funcionando com a seguinte consulta:

      • mysqlslap -usammy -p -P6033 -h127.0.0.1 --auto-generate-sql --verbose

      O mysqlslap tem sinalizadores semelhantes aos do cliente mysql; aqui estão os usados neste comando:

      • -u – especifica o usuário usado para se conectar ao servidor.
      • -p – solicita a senha do usuário.
      • -P – conecta-se usando a porta especificada.
      • -h – conecta-se ao host especificado.
      • --auto-generate-sql – permite que o MySQL faça testes de carga, usando suas próprias consultas geradas.
      • --verbose – faz o resultado mostrar mais informações.

      Você irá obter um resultado similar ao seguinte:

      Output

      Benchmark Average number of seconds to run all queries: 0.015 seconds Minimum number of seconds to run all queries: 0.015 seconds Maximum number of seconds to run all queries: 0.015 seconds Number of clients running queries: 1 Average number of queries per client: 0

      Nesse resultado, você pode ver o número médio, mínimo e máximo de segundos gastos para executar todas as consultas. Isso lhe dará uma ideia sobre o tempo necessário para executar as consultas feitas por um certo número de clientes. Nesse resultado, apenas um cliente foi usado para executar consultas.

      Em seguida, descubra quais consultas o mysqlslap executou no último comando, examinando o stats_mysql_query_digest do ProxySQL. Isso nos dará informações como o resumo das consultas, que é uma forma normalizada da instrução em SQL que poderá ser referenciada mais tarde para habilitar o armazenamento em cache.

      Acesse a interface de administração do ProxySQL com este comando:

      • mysql -uadmin -p -h 127.0.0.1 -P6032

      Depois, execute esta consulta para encontrar informações na tabela stats_mysql_query_digest:

      • SELECT count_star,sum_time,hostgroup,digest,digest_text FROM stats_mysql_query_digest ORDER BY sum_time DESC;

      Você verá um resultado similar ao seguinte:

      +------------+----------+-----------+--------------------+----------------------------------+
      | count_star | sum_time | hostgroup | digest             | digest_text                      |
      +------------+----------+-----------+--------------------+----------------------------------+
      | 1          | 598      | 1         | 0xF8F780C47A8D1D82 | SELECT @@HOSTNAME as hostname    |
      | 1          | 0        | 1         | 0x226CD90D52A2BA0B | select @@version_comment limit ? |
      +------------+----------+-----------+--------------------+----------------------------------+
      2 rows in set (0.01 sec)
      

      A consulta anterior seleciona os dados da tabela stats_mysql_query_digest, a qual contém informações sobre todas as consultas executadas no ProxySQL. Aqui, você tem cinco colunas selecionadas:

      • count_star: o número de vezes que essa consulta foi executada.
      • sum_time: tempo total em milissegundos que essa consulta levou para executar.
      • hostgroup: o grupo de hosts usado para executar a consulta.
      • digest: um resumo da consulta executada.
      • digest_text: a consulta em si. No exemplo deste tutorial, a segunda consulta é parametrizada usando sinais de ? no lugar de parâmetros de variável. select @@version_comment limit 1 e select @@version_comment limit 2 são, portanto, agrupados juntos como a mesma consulta e com o mesmo resumo.

      Agora que você sabe como verificar os dados de consulta na tabela stats_mysql_query_digest, saia do shell do mysql:

      O banco de dados que baixou contém algumas tabelas com dados de demonstração. Agora, você testará consultas na tabela dept_emp, selecionando quaisquer registros cujo from_date formaior que 2000-04-20 e registrando o tempo médio de execução.

      Use este comando para executar o teste:

      • mysqlslap -usammy -P6033 -p -h127.0.0.1 --concurrency=100 --iterations=20 --create-schema=employees --query="SELECT * from dept_emp WHERE from_date>'2000-04-20'" --verbose

      Aqui, você está usando alguns sinalizadores novos:

      • --concurrency=100: define o número de usuários a simular, neste caso 100.
      • --iterations=20: faz com que o teste seja executado 20 vezes e calcula os resultados de todos elas.
      • --create-schema=employees: aqui você selecionou o banco de dados employees (funcionários).
      • --query="SELECT * from dept_emp WHERE from_date>'2000-04-20'": aqui você especificou a consulta executada no teste.

      O teste levará alguns minutos. Após terminar, você receberá resultados semelhantes ao seguinte:

      Output

      Benchmark Average number of seconds to run all queries: 18.117 seconds Minimum number of seconds to run all queries: 8.726 seconds Maximum number of seconds to run all queries: 22.697 seconds Number of clients running queries: 100 Average number of queries per client: 1

      Seus números podem ser um pouco diferentes. Mantenha esses números em algum lugar para compará-los com os resultados obtidos após habilitar o armazenamento em cache.

      Após testar o ProxySQL sem armazenar em cache, é hora de executar o mesmo teste novamente; mas, desta vez, com o armazenamento em cache habilitado.

      Neste passo, o armazenamento em cache nos ajudará a diminuir a latência ao executar consultas semelhantes. Aqui, você identificará as consultas executadas, pegará seus resumos da tabela stats_mysql_query_digest do ProxySQL e os usará para habilitar o armazenamento em cache. Em seguida, você testará novamente para verificar a diferença.

      Para habilitar o armazenamento em cache, você precisa conhecer os resumos das consultas que serão armazenadas em cache. Faça login na interface de administração do ProxySQL, usando este comando:

      • mysql -uadmin -p -h127.0.0.1 -P6032

      Depois, execute esta consulta novamente para obter uma lista das consultas executadas e seus resumos:

      • SELECT count_star,sum_time,hostgroup,digest,digest_text FROM stats_mysql_query_digest ORDER BY sum_time DESC;

      Você receberá um resultado semelhante a este:

      Output

      +------------+-------------+-----------+--------------------+------------------------------------------+ | count_star | sum_time | hostgroup | digest | digest_text | +------------+-------------+-----------+--------------------+------------------------------------------+ | 2000 | 33727110501 | 1 | 0xC5DDECD7E966A6C4 | SELECT * from dept_emp WHERE from_date>? | | 1 | 601 | 1 | 0xF8F780C47A8D1D82 | SELECT @@HOSTNAME as hostname | | 1 | 0 | 1 | 0x226CD90D52A2BA0B | select @@version_comment limit ? | +------------+-------------+-----------+--------------------+------------------------------------------+ 3 rows in set (0.00 sec)

      Examine a primeira linha. Trata-se de uma consulta que foi executada 2000 vezes. Essa é a consulta executada anteriormente como parâmetro de comparação. Pegue seu resumo e guarde-o para ser usado na adição de uma regra de consulta para o armazenamento em cache.

      As próximas consultas vão adicionar uma nova regra de consulta ao ProxySQL que fará a correspondência entre o resumo da consulta anterior e colocará um valor cache_ttl para ela. O cache_ttl é o número de milissegundos em que o resultado ficará armazenado em memória cache:

      • INSERT INTO mysql_query_rules(active, digest, cache_ttl, apply) VALUES(1,'0xC5DDECD7E966A6C4',2000,1);

      Nesse comando, você está adicionando um novo registro à tabela mysql_query_rules; essa tabela contém todas as regras aplicadas antes de executar uma consulta. Nesse exemplo, você está adicionando um valor à coluna cache_ttl, que fará com que a consulta – que foi combinada por determinado resumo – seja armazenada em cache pelo tempo (em milissegundos) especificado nessa coluna. Coloque 1 na coluna de aplicação para garantir que a regra seja aplicada às consultas.

      LOAD e SAVE essas alterações e, em seguida, saia do shell mysql:

      • LOAD MYSQL QUERY RULES TO RUNTIME;
      • SAVE MYSQL QUERY RULES TO DISK;
      • exit;

      Agora que o armazenamento em cache está habilitado, execute novamente o teste para verificar o resultado:

      • mysqlslap -usammy -P6033 -p -h127.0.0.1 --concurrency=100 --iterations=20 --create-schema=employees --query="SELECT * from dept_emp WHERE from_date>'2000-04-20'" --verbose

      Isso dará um resultado similar ao seguinte:

      Output

      Benchmark Average number of seconds to run all queries: 7.020 seconds Minimum number of seconds to run all queries: 0.274 seconds Maximum number of seconds to run all queries: 23.014 seconds Number of clients running queries: 100 Average number of queries per client: 1

      Aqui, você consegue ver a grande diferença em tempo médio de execução: o tempo baixou de 18.117 segundos para 7.020.

      Conclusão

      Neste artigo, você configurou o armazenamento em cache transparente com o ProxySQL para armazenar em cache os resultados das consultas no banco de dados. Também testou a velocidade de consulta com e sem o armazenamento em cache para ver a diferença que o armazenamento em cache pode fazer.

      Neste tutorial, você usou um nível de armazenamento em cache. Você também poderia tentar fazer o armazenamento em cache baseado na Web, o qual fica na frente de um servidor Web e armazena em cache as respostas a pedidos semelhantes, enviando a resposta de volta para o cliente, sem chegar aos servidores de back-end. É bem parecido com o armazenamento em cache do ProxySQL, porém em um outro nível. Para aprender mais sobre o armazenamento em cache baseado na Web, acesse o artigo Noções básicas de armazenamento em cache baseado na Web: terminologia, cabeçalhos de HTTP e primer de estratégias de armazenamento em cache.

      O servidor MySQL também tem seu próprio cache de consulta; você pode aprender mais sobre isso em nosso tutorial sobre Como otimizar o MySQL com o cache de consulta no Ubuntu 18.04.



      Source link