How to Implement Memcached in C# ASP.NET MVC Project?

Introduction

In modern web applications, performance and scalability are crucial. One of the effective ways to enhance performance is by using caching. Memcached, an open-source, high-performance, distributed memory caching system, is widely used. This article will walk you through implementing Memcached in a C# ASP.NET MVC project.

MVC Project

What is Memcached?

Memcached is a distributed memory object caching system designed to speed up dynamic web applications by reducing database load. It stores data in memory, allowing for faster access compared to retrieving data from a database.

Example use

Consider an e-commerce website with a large product catalog. Every time a user searches for products, the application queries the database, which can be slow due to the volume of data and complexity of the queries. By using Memcached, the application can cache the results of common queries. When a user searches for a frequently requested product, the application retrieves the data from Memcached instead of the database, resulting in much faster response times.

How Memcached Works?

  1. In-Memory Data Storage: Memcached stores data directly in memory (RAM), providing substantially faster access times than traditional disk-based storage options such as databases or file systems. This approach allows for near-instantaneous retrieval of cached data, greatly improving the performance of applications that require rapid access to frequently used information. By leveraging the speed of in-memory storage, Memcached helps reduce latency and enhances the overall user experience.
  2. Distributed Architecture: Memcached's distributed architecture enables it to be deployed across multiple servers, creating a robust and scalable caching solution. This setup allows Memcached to handle large volumes of data efficiently while providing fault tolerance. In the event of a server failure, the distributed nature of Memcached ensures that other servers in the cluster can continue to serve requests without interruption. This redundancy and scalability make Memcached an ideal choice for high-availability environments.
  3. Key-Value Store: At its core, Memcached operates as a simple key-value store. Data is stored using a unique key, which can then be used to retrieve the associated value quickly. This straightforward mechanism is a primary reason for Memcached's speed and efficiency. The simplicity of the key-value store model reduces overhead and complexity, enabling rapid data access and management, which is particularly beneficial for applications that demand high-performance caching solutions.
  4. Cache Eviction Policy: Memcached employs the LRU eviction policy that helps in managing memory. LRU policy is used to remove the least recently used items by the cache when it gets full so as to make space for new data. By using this approach, only relevant and frequently accessed information will be maintained in memory enhancing its efficiency and efficacy. Memcached optimally performs even as a data set enlarges and changes over time through constant efforts at controlling memory usage.

Use Cases for Memcached

  1. Database Query Caching: Caching the results of expensive database queries can significantly reduce the time needed to fetch data that doesn't change often.
  2. Session Storage: Storing session data in Memcached improves the performance of user authentication and session management processes.
  3. API Response Caching: By caching API responses, applications can avoid redundant calls and reduce latency, enhancing overall performance.
  4. Page Caching: For dynamic websites, caching entire pages or page fragments can greatly speed up page load times.
  5. Object Caching: Frequently accessed objects, such as user profiles or configuration settings, can be cached to minimize database access and improve efficiency.

Setting up the Memcached server

Follow the below steps to set up the Memcached server on your system.

Step 1. Installation

To install WSL (Windows Subsystem Linux), follow the below command in the command prompt.

sudo apt update
sudo apt install memcached

Step 2. Running Memcached server

To run the Memcached server on WSL, enter the below command in the command prompt.

memcached

Step 3. Check the status of Memcached

To check the status of Memcached, enter the below command in the command prompt.

ps aux | grep memcached

Now, that we have set up our Memcached server, it's time to set up Memcached in our project.

Setting Up Memcached in ASP.NET MVC project

You can set up this in a new project or create a new project to set up Memcached. I have an existing project in which I will set up memcached.

Step 1. Adding Memcached Client library to the project

To use Memcached we need a client library. 'EnyimMemcached' is a popular choice. So, we will use this in our project.

Now, let's install this package in our project.

  1. Click 'Project' and select 'Manage NuGet Packages'.
  2. In 'Browse', enter 'EnyimMemcached' in the search box.
  3. Select it and click 'Install'.
  4. A popup window will open, click, 'I accept'. Once installed, it will show in Packages under Dependency.

Step 2. Configuring Memcached Client

In program.cs file, add the below code

builder.Services.AddEnyimMemcached(options =>
{
    options.AddServer("localhost", 11211); 
      ...                                    
});

You can replace the above with your Memcached server details and also add more servers if you have a Memcached cluster. This configuration specifies that the Memcached server is running on localhost and listening on port '11211'.

Step 3. Initializing and Using Memcached in your application

Add the below-using statements.

using Enyim.Caching;
using Enyim.Caching.Memcached;

Now, in the constructor, add the below code.

 private readonly IMemcachedClient _memcachedClient;
 public EmployeeController(IMemcachedClient memcachedClient)
 {
     .....
     _memcachedClient = memcachedClient;
 }

In this snippet, I’m defining a private, read-only field '_memcachedClient' for working with Memcached. In the 'EmployeeController' constructor, I’m injecting an 'IMemcachedClient' instance and assigning it to this field, ensuring that the controller can use the caching service.

Step 4. Implementing Caching in Your Controllers

[HttpGet]
public async Task<IActionResult> AllEmployees()
{
    try
    {
        var cachedResult = await _memcachedClient.GetAsync<List<Employees>>("AllEmployees");
        List<Employees> employeeList;
        if (cachedResult == null || cachedResult.Message == "Not found")
        {
            using (SqlConnection con = new SqlConnection(_connectionString))
            {
                await con.OpenAsync();
                var result = await con.QueryAsync<Employees>("GetEmployees", commandType: CommandType.StoredProcedure);
                employeeList = result.ToList();
                await _memcachedClient.StoreAsync(StoreMode.Set, "AllEmployees", employeeList, TimeSpan.FromMinutes(10));
            }
        }
        else
        {
            employeeList = cachedResult.Value;
        }
        return View(employeeList);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        return RedirectToAction("Index", "Home");
    }
}

When a request is made to fetch all employees, I start by checking if the data is already cached in Memcached. This is done using '_memcachedClient.GetAsync<List<Employees>>("AllEmployees")'. If the cache is empty or indicates that the data isn't found, I then connect to the SQL Server. I open a connection and execute a stored procedure named `GetEmployees` to retrieve the employee data from the database. Once I have the list of employees, I store this data in the cache with a 10-minute expiration time to improve performance for future requests.

If the data was found in the cache, I skip the database query and use the cached list directly. Finally, I return the list of employees to the view for display. If any errors occur during this process, I catch the exceptions, log the error message to the console, and redirect the user to the home page to handle the issue gracefully.

Conclusion

Integrating Memcached into your C# ASP.NET MVC project can significantly improve application performance by reducing database load and providing fast data access. By following the steps outlined in this article, you can set up and utilize Memcached effectively in your project. Here, i have shown only basic functionalities, but you can extend this and use it according to your own needs.