Introduction
In this article, I'm going to discuss the Redis and use cases on using it as a Primary Database to store our data.
- Introduction to Redis
- Redis Datatypes
- Pros and cons of using Redis as DB
- Setting up Redis in a Container
- Using Redis as a Primary database with .NET 8 Web API.
Prerequesities
- Visual Code
- .NET 8 SDK
- Redis Desktop Manager. You can download it from the URL(https://redis.io/resources/tools/)
- Docker Desktop
- Packages
- Microsoft.Extensions.Caching.stackExchangeRedis
- StackExchange.Redis
Introduction to Redis
Redis is an in-memory datastore, and key-value datastore, and is used mostly for the caching layer. Because Redis stores data in-memory, it allows for very fast read and write operations which are well-suited for low-latency access to the data. You will have questions like the Redis stores the data in-memory but when the system reboots we'll lose the data.
To solve the issue of data persistence, Redis provides different mechanisms such as snapshots and append-only files (AOF). These mechanisms allow you to persistently store the data on disk, ensuring that it can be recovered even after a system reboot. You can learn more about Redis Persistence in theURL
Mostly Redis is used as a Cache layer but we can also use it as a Database to reduce the other call to the complex database systems. Redis using the Document database model where it stores the data in documents mostly in JSON format. You can also know more about from the URL
Redis Datatypes
Redis provides a handful of data types that allow us to solve problems from caching, queuing, and event processing.
- Strings: representing a sequence of bytes
- Lists - Lists of strings
- Sets - Unordered collection of unique string
- Hashes - record types modeled as collections of field-value pairs
You'll learn more about the data types from the URL
Pro's of using Redis as DB
- High Performance
- Versatile DataStructure
- Low Latency
- Scalability
Con's of using Redis as DB
- Data Durability
- Limited Query Capabilities
- Memory Constraints
Setting up Redis in a Container
Make sure that, Docker Desktop is running and open Visual Studio 2022.
Choose "Create a New Project" --> Click the "ASP.NET Core Web API" and then click "Next".
On the Configure page, enter the Project name and then press "next".
On the Additional information page, choose the information as per the screenshot and choose "Create".
Now, Create "docker-compose.yaml" file to hold the configuration for our Redis and paste the below code.
version: '3.8'
services:
redis:
image: redis:alpine
container_name: redisStudentAPI
ports:
- 6379:6379
After that, open the Developer Powershell prompt from the Tools -> Command line -> Developer Powershell.
Then navigate inside the Project folder and enter the command to run the YAML file "docker compose up -d"
Open the docker desktop, and navigate to the containers you can see the container created from the YAML file. Also, you can run the 'docker ps' to see the running containers.
To interact with the Redis Server, you need to run the below command with the container ID.
docker exec -it <container_id> /bin/sh
The basic setup of Docker is done and we can able to interact with Redis via the command line.
Now, we are going to see more about the string data types because we are going to store the key, and value pair as strings
Strings
It's the simplest type of value to be associated with a key and a one-to-one mapping between key & value.
We can set the value using the Set<key> <value> and also get the using GET <key>
You can also delete the key using the Del <key>
Now, you need to install the necessary packages from the NuGet Package Manager.
Add the configuration in the Program.cs files
Programs.cs
builder.Services.AddSingleton<IConnectionMultiplexer>(options =>
ConnectionMultiplexer.Connect(("127.0.0.1:6379")));
builder.Services.AddScoped<IStudentRepository, StudentRepository>();
Create a Models Folder and Create a file for our Model Student.cs then paste the code.
Student.cs
namespace StudentAPIWithRedisDB.Models
{
public class Student
{
public string Id { get; set; } = $"student:{Guid.NewGuid().ToString()}";
public required string StudentName { get; set; } = string.Empty;
}
}
Then copy and Paste the below code on the Respection files.
StudentRepository.cs
using StudentAPIWithRedisDB.Models;
namespace StudentAPIWithRedisDB.Data
{
public interface IStudentRepository
{
IEnumerable<Student> GetAllStudents();
Student? GetStudentById(string id);
void AddStudent(Student student);
Student? UpdateStudent(Student student);
Student? DeleteStudent(string id);
}
}
StudentRepository.cs is the implementation of the IStudentRespository.cs interface and all its methods.
using StackExchange.Redis;
using StudentAPIWithRedisDB.Models;
using System.Text.Json;
namespace StudentAPIWithRedisDB.Data
{
public class StudentRepository : IStudentRepository
{
private readonly IConnectionMultiplexer _redis;
public StudentRepository(IConnectionMultiplexer redis)
{
_redis = redis;
}
public void AddStudent(Student student)
{
if(student == null)
{
throw new ArgumentOutOfRangeException(nameof(student));
}
var db = _redis.GetDatabase();
var serializedStudent = JsonSerializer.Serialize(student);
db.StringSet(student.Id, serializedStudent);
}
public Student? DeleteStudent(string id)
{
var db = _redis.GetDatabase();
var student = db.StringGet(id);
if (student.IsNullOrEmpty)
{
return null;
}
db.KeyDelete(id);
return JsonSerializer.Deserialize<Student>(student);
}
public IEnumerable<Student> GetAllStudents()
{
var db = _redis.GetDatabase();
var studentKeys = db.Multiplexer.GetServer(_redis.GetEndPoints().First()).Keys(pattern: "student:*");
var students = new List<Student>();
foreach (var key in studentKeys)
{
var studentJson = db.StringGet(key);
if (!studentJson.IsNullOrEmpty)
{
var student = JsonSerializer.Deserialize<Student>(studentJson);
students.Add(student);
}
}
return students;
}
public Student? GetStudentById(string id)
{
var db = _redis.GetDatabase();
var student = db.StringGet(id);
if(student.IsNullOrEmpty)
{
return null;
}
return JsonSerializer.Deserialize<Student>(student);
}
public Student UpdateStudent(Student student)
{
var db = _redis.GetDatabase();
var id = student.Id;
if (db.KeyExists(id))
{
var updatedStudentJson = JsonSerializer.Serialize(student);
db.StringSet(id, updatedStudentJson);
return student;
}
else
{
return null;
}
}
}
}
StudentsController.cs
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using StudentAPIWithRedisDB.Data;
using StudentAPIWithRedisDB.Models;
namespace StudentAPIWithRedisDB.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class StudentsController : ControllerBase
{
private readonly IStudentRepository _studentRepository;
public StudentsController(IStudentRepository studentRepository)
{
_studentRepository = studentRepository;
}
[HttpGet("{Id}", Name = "GetStudentById")]
public ActionResult<Student> GetStudentById(string Id)
{
var student = _studentRepository.GetStudentById(Id);
if(student == null)
{
return NotFound();
}
return Ok(student);
}
[HttpPost]
public ActionResult<Student> AddStudent(Student student)
{
_studentRepository.AddStudent(student);
return CreatedAtRoute(nameof(GetStudentById), new { Id = student.Id }, student);
}
[HttpGet(Name = "GetAllStudents")]
public ActionResult<Student> GetAllStudents()
{
var students = _studentRepository.GetAllStudents();
return Ok(students);
}
[HttpDelete("{id}")]
public ActionResult<Student> DeleteStudent(string id)
{
var student = _studentRepository.DeleteStudent(id);
if(student == null)
{
return NotFound();
}
return Ok(student);
}
[HttpPatch]
public ActionResult<Student> UpdateStudent(Student student)
{
var studentToUpdate = _studentRepository.GetStudentById(student.Id);
if(studentToUpdate == null)
{
return NotFound();
}
_studentRepository.UpdateStudent(student);
return NoContent();
}
}
}
Now, run the application you can able to see the endpoints showing on the browser using Swagger.
Also, it would help if you opened the Redis Desktop Manager to see the data. Initially, it'll have 16 databases without any data.
Once, you hit the create endpoint it'll automatically create a record in the DB0.
CREATE
For easy testing purposes, I have used the Postman to test the endpoints.
Pass the name only, then it'll automatically create an ID with the name of the student and the suffix with the new Guid
And the document is created on the DB0.
GetStudentById
For this, you need to copy the ID from the document. Then pass it on the request URL.
and it returns the value based on the ID.
GetAllStudents
It returns all the documents available in the Database.
Update
You need to pass the ID and the updated value. So that, it'll update based on the ID.
Once, you refresh the manager then you'll see the updated value.
Delete
For deleting a user, kindly pass the ID, then it'll remove the document from the Student DB.
And the document is deleted from the file.
Previously, I had the two documents on the Student's table but now the first one is deleted.
That'll this is a simple way of showing the usage of Redis as a Database in our application. Here, we have reduced the Cache and stored the data directly to the Redis and also retrieved and made changes to it. Likewise, you can also apply the same to your application.