A challenge that some organizations face when moving to the cloud is how best to migrate or integrate old legacy infrastructure with restrictive licensing to an environment that offers a breadth of functionality and pay-as-you-go pricing. AWS provides many options to help customers in their analysis and planning. One common approach is to establish a hybrid environment between an existing data center and AWS.

Within a hybrid environment, one of the challenges you might face is remducing the latency associated with on-premises resources such as databases, appliances, and internal systems. A lot of solutions can address this. This blog post illustrates one of them: how to use caching to reduce latency, increase performance, and improve fault tolerance at the same time.

Scenario: high latency on the customer’s main application

In the scenario we’re looking at, the customer was experiencing high latency on their main application, which was affecting daily operations. This application is an online medical library with search capabilities, driven by a database. The following diagram shows the original architecture. On review, we saw that the problem was an overloaded database due to a high number of queries from a search engine. In addition, the results from the queries were so large that they saturated the customer’s low-speed network link, affecting the response time.

One solution that can solve this issue, which we don’t discuss in this post, is to move the database to Amazon RDS and enable read-only instances. However, the licensing terms of the customer’s database prevented moving it to AWS. Another challenge in moving the database is the integration between application and database. The system was in production, and it wasn’t feasible to rewrite the entire application to a different database engine that had no licensing restrictions.

Proposed solution: an in-memory cache based on Amazon ElastiCache

Because the issue involves latency to the backend database, we propose an in-memory cache based on Amazon ElastiCache to reduce network latency and to offload the database pressure. This solution dramatically reduces the data retrieval latency. It also scales request volume considerably, because Amazon ElastiCache can deliver extremely high request rates, measured at over 20 million per second. The following diagram shows the proposed architecture. With the cache inside the VPC along with the web servers and application servers, the application doesn’t have to constantly go from AWS to the local data center. This change makes the physical distance between servers irrelevant.

Another benefit of this solution is the added availability and scale for the workload. With this architecture, you can continue running queries against the application even if the source database fails. This result is because results are stored and retrieved from cache.

The new architecture should greatly improve the customer experience.

Some background on ElastiCache

Amazon ElastiCache is a fully managed, low-latency, in-memory data store that is compatible with Redis and Memcached. ElastiCache removes most administrative tasks associated with managing Redis and Memcached, allowing you to focus on your business and data. The service improves the performance of web applications by allowing you to retrieve information from fast, managed, in-memory data stores, instead of relying entirely on slower disk-based databases. ElastiCache automatically detects and replaces failed nodes, reducing the overhead associated with self-managed infrastructures. ElastiCache thus provides a resilient system that mitigates the risk of overloaded databases, which slow website and application load times.

Know before you start

As part of the proposed solution, this blog post guides you through the process of creating an ElastiCache cluster. To do so, you need the following resources:

Access to the AWS Management Console.

One or more web servers and application servers running on AWS

The web and application server IP addresses to grant access to the cluster

One database with access credentials running on-premises

Server address and login credentials for this database

Git to download and deploy the demo, whose source code is hosted on GitHub

The software stack used for the post and demo is as follows:

Apache as web server

PHP as application server

MySQL as database server

If you don’t have such an environment, a demo to deploy the complete environment is included to test the solution. The demo includes an Amazon EC2 web instance, ElastiCache cluster, and RDS MySQL database.

MySQL is used as database engine in the demo. However, after you download the source code you can customize the code to use with your preferred database.

Setting up an Amazon EC2 security group

Before creating an ElastiCache cluster, you need a security group to control access to the cluster. A security group acts as a virtual firewall that controls the traffic for your cluster.

To create the security group, sign in to the AWS console and go to the EC2 service page. There, choose Security Groups in the navigation pane, and then choose Create Security Group, as seen in the following diagram.

If you have multiple VPCs, you need to select the VPC that contains your web and application instance. For Source, provide the private IP address of your web servers or application servers to access the cache cluster.

The port number depends on the ElastiCache engine selected. In this post, we use the default port for Redis (6379), as shown in the following diagram.

Setting up an ElastiCache cluster

To activate the ElastiCache cluster, follow the steps listed:

Sign in to AWS console and go to the ElastiCache service page. The first time you go to that page, you see a Get Started screen. Choose Get Started Now to create your first cluster as seen in the following screenshot.

If you already have cache clusters in your account, choose the Create button available in the ElastiCache dashboard.

When you first create your cluster, you have the option of selecting which engine you want:

Redis, an in-memory data store for use as a fast database, cache, message broker, and queue. ElastiCache for Redis offers Multi-AZ with auto-failover, and an enhanced Redis running underneath that provides improved robustness and stability. This engine is widely popular and used for multiple use cases such as web apps, gaming, mobile, eCommerce, IoT, and more.

Memcached, a high-performance memory object caching system designed to accelerate dynamic web applications. Some examples of integration are Drupal, WordPress, and Joomla, among others.

In this post, we use Redis instead of Memcached for its support of complex data types, persistence of key store, encryption in transit and at rest, and backup and restore capabilities. For more information on choosing the best engine, see Choosing an Engine in the ElastiCache User Guide.

For the Redis engine, we have two options to choose from:

Redis (nonclustered mode): Redis 2.8.x and Redis 3.2.x. This mode is used when you need complex data types, in-memory datasets, persistence of your key store, replication, automatic failover, and backup and restore capabilities. It supports multiple databases.

Redis (clustered mode): This mode provides all the functionality of Redis 2.8.x but is structured as a single database with data partitioning support.

To keep things simple, in this post Redis (nonclustered) instead of Redis (clustered). This choice lets us focus on the main idea of network latency reduction and performance optimization. In production for applications with large volumes of data, we recommend using Redis (clustered mode) to enable data partitioning.

For our solution, we use Redis 4.0.10 or later because it’s the only Redis version that supports encryption in transit and at rest right now.

In the next step, we choose a number of options. These include the type of node, which is directly associated with the amount of memory needed for storage. Options here also include the version of Redis (in case we have an old client version) and the number of replicas in our ElastiCache cluster. Each group of ElastiCache instances is called a cluster, even if it’s just a single node.

The number of replicas indicates the number of items in a collection of read replicas. Applications use these read replicas to read from, which improves read throughput and guards against data loss in case of a node failure.

The following screenshot shows the Redis settings that you choose in this step. In the Advanced Redis settings section, shown in the following screenshot, we can enable Multi-AZ failover. This feature provides high availability through automatic failover to a read replica in case of failure of the primary node.

The first time you create a cluster, you need to create a subnet group. A subnet group is a collection of subnets (typically private) within the VPC where your ElastiCache cluster runs. To achieve fault tolerance, it’s a good practice to use at least two subnets, each of the two in a different Availability Zone.

Leave the Preferred availability zone(s) as No preference, so ElastiCache distributes the Redis cluster’s nodes among several Availability Zones. In the Security section, shown in the following screenshot, you choose the security group that you previously created to grant access to the cluster to web servers and application servers. Also, because the application works with medical information, you enable encryption in transit and at rest here to protect the data. More information about encryption in transit and at rest is available in the Now You Can Use Amazon ElastiCache for Redis with In-Transit and At-Rest Encryption to Help Protect Sensitive Information post on the AWS Security Blog.

When you enable the Redis AUTH option, a Redis AUTH token is required. This option improves data security by requiring the user to enter a password before they are granted permission to execute Redis commands. Find more information about authenticating users with AUTH in Authenticating Users with AUTH (Redis) in the ElastiCache User Guide. The next step is to choose the values for the backup window for our cluster. The backup window is the time period when ElastiCache takes a daily snapshot for persistence. Here you can also select the retention period for backups. You can see the available options in the following screenshot. Leave all the other parameters unmodified, and choose Create to create the cluster. You can see cluster creation status in the following screenshot. A few minutes later, the cluster is ready for use. In the following screenshot, you can see that the cluster is ready to use. You can also see the endpoint (the address to which we connect to use the cluster), along with the other details.

Integrating your application

To finish the implementation, the next step is to configure your application to add Redis support. This process is application-dependent, so we don’t cover it in this post.

Next, you deploy a full environment with a sample PHP application so you can test the performance gains using Amazon ElastiCache for Redis.

Deploying a full environment with a sample PHP application

So you can test the solution, we provide an AWS CloudFormation template to deploy the environment and its dependencies. AWS CloudFormation gives developers and systems administrators an easy way to create and manage a collection of related AWS resources, provisioning and updating them in an orderly and predictable fashion.

The template creates the next resources:

An Amazon EC2 instance and Apache web server with PHP and phpredis extension

An Amazon ElastiCache for Redis cluster

An Amazon RDS MySQL database

The Redis client library Predis, which includes support for TLS/SSL

A sample PHP application to test queries performance

There are a number of Redis clients and extensions for many languages such as Java, PHP, Ruby, Python, and so on. For this demo, we use the phpredis extension. The source code is hosted on GitHub, so you need Git to download the source code.

To download the source code, run the git clone command on an EC2 instance or your workstation:

git clone https://github.com/awslabs/elasticache-hybrid-architecture-demo

To deploy the web server (the EC2 instance), you need an EC2 key pair. If you don’t have a key pair yet, go to the EC2 console, choose Key Pairs, and create a new key pair. In this process, you’re prompted save the private key. Keep the private key file secure, because it can be used to log in to the web instance to customize the sample PHP file.

Note: Amazon doesn’t keep a copy of your private key. If you lose a private key, there is no way to recover it.

To deploy the template, go to the CloudFormation console and create a new stack as shown in the following screenshot. Choose Upload a template to Amazon S3, choose Browse to explore the elasticache-hybrid-architecture-demo directory downloaded from GitHub, and then choose the file cloudformation-template.yaml. Them choose Next, as shown in the following screenshot.

Give a name to the stack and replace parameters as required. To keep things simple, parameters are grouped into sections. You only need to replace parameters in the Main Configuration section:

Your IP address: The EC2 instance security group opens an HTTP port to this IP address only. Don’t forget to include /32 at the end of your IP address.

Key name: This is the key pair used to log in into Amazon EC2 instance created by the template. Don’t forget to choose your key pair.

DB password: The password to log in into the new RDS database created by the template, this password is also required by the sample PHP application.

Cache Token: The token used to protect communication between the EC2 instance and ElastiCache cluster.

VPC: VPC where the EC2, ElastiCache cluster, and RDS instances are deployed.

Subnet: The subnet where web instance is deployed

Except for the database password, all parameters are used to preconfigure the demo.php script.

The template includes parameters to allow you to change tags, instances sizes, engines, engine versions, and more. However, you can accept the defaults right now and choose Next to continue, as shown in the following screenshot.

Choose Next in the Options screen, shown in the following screenshot, and review your configuration. The template creates an IAM resource for the EC2 instance. Thus, don’t forget to select the check box I acknowledge that AWS CloudFormation might create IAM resources, as shown in the following screenshot. Otherwise, the deployment fails.

Choose Create to create the stack. Wait until the stack status changes from CREATE_IN_PROGRESS to CREATE_COMPLETE.

In the Outputs tab, shown in the following screenshot, you have the addresses of the resources created by the template. DemoScript provides the URL you must open in your web browser to access the sample PHP application.

Using the sample PHP application

In your web browser, open the DemoScript URL to access the sample PHP application. The form is prefilled with database credentials used during template deployment. The database password is required each time you access the address. The following screenshot shows the sample application interface.

With this application, you can run queries to compare response times from database (with no cache) and response times from the cache.

By default, no data is loaded into the database. Use the Load Sample button to create a sample table called crimes and to load sample data into it. The dataset is open data of crimes in Los Angeles between 2012 and 2015. Once the load process finishes, you can run queries such as SHOW, SELECT, and DESCRIBE right from the PHP application.

When you choose Test Query, an AJAX request is sent to the script run.php. This script receives the query, generates a hash to use as a key to consult the cache, and checks if the key already exists in cache. If the key exists in the cache, the script returns the result from the cache without connecting to the database. If the key isn’t found in the cache, the script connects to the database, runs the query, saves the result into the cache, and returns the result from database.

The first time you run a query, the PHP application returns the result directly from the database because the key is not in the cache yet. This first run is shown in the following screenshot. When you run the query twice, the second execution is considerably faster, because the result returns from the cache instead of the database. The following screenshot shows the result from the cache. You can use the Clear Cache button to clear the Redis cache to run queries directly against the database.

Security advice

This post focuses on hybrid architectures, so all the scripts can be used (with customizations) in your environment. However, you should take the appropriate security measures to protect your data. In a production environment, you should enable encryption, use least-needed-access for security groups, and follow other standard security practices. You can find more information about ElastiCache and AWS security on these pages:

Amazon ElastiCache Data Security and Compliance in the ElastiCache User Guide

AWS Cloud Security on the AWS website

Conclusion

Amazon ElastiCache is an effective solution to reduce latency in hybrid architectures with workloads on AWS. At the same time, you can use ElastiCache to increase performance and add fault tolerance in case your database fails. To learn more about the current Amazon ElastiCache use cases, check case studies of customers, such as McDonald’s, Airbnb, Duolingo, Expedia, and Hudl.

Next step: Try it for yourself and let us know what you find from using high-performance in-memory caching!

About the Author

Angel Leon is Senior Solutions Architect at Amazon Web Services responsible for Enterprise Accounts in Public Sector. He has been working for eight years in Government having a full cloud dedication in cloud solutions in the last 5 years. He is a pioneer for cloud adoption solutions for customers in Public Sector and Commercial Sectors across Latin America & Caribbean.