Monthly Archives: February 2024

Why is Redis so fast?

Redis is an open-source in-memory database/data store, which means that its access is 1000 times faster than random disk access. Unlike traditional databases, Redis holds all the information in memory as opposed to performing continuous reads and writes. This allows for constant-time data access, which is crucial for operations requiring high speed. Redis uses Jemalloc, a general purpose memory allocation library that focuses on offering robust concurrency support as well as minimising memory fragmentation. While this seems rather a nice catchy sentence, minimising memory fragmentation offers several benefits, as follows:

  • Improved performance. Fewer cache misses and potentially higher cache efficiency that can result in faster application execution as more data can be stored in faster-access memory spaces.
  • Efficient usage of memory. By reducing fragmentation, a system can make more efficient use of its available memory. This means that more data can be stored within the same amount of physical memory, reducing the need for expensive memory allocation and deallocation operations.
  • Reduced Memory Waste: Fragmentation leads to “holes” of unused memory scattered throughout the memory space, which can significantly waste valuable memory resources. Minimising fragmentation ensures that these holes are either eliminated or reduced, thus lowering the amount of wasted memory.
  • Predictable Performance: Applications that rely on consistent and predictable performance benefit from reduced memory fragmentation, as it leads to more stable memory usage patterns. This predictability is crucial for real-time systems and high-performance computing applications where timing is critical.
  • Longer Runtime without Degradation: Systems that run for extended periods without restarting (such as servers) can suffer from increased fragmentation over time, which can degrade performance. Allocators that minimise fragmentation can help maintain consistent performance over longer runtimes.
  • Enhanced Stability and Reliability: By ensuring efficient memory usage and reducing the chances of memory allocation failures due to fragmentation, systems can achieve higher stability and reliability. This is particularly important in embedded systems and critical applications where failures can have significant consequences.

The fact that Redis is so fast is, however, due to a combination of factors beyond the speed of in-memory data storage. For example:

  • Single-Threaded Architecture: Redis follows a single-threaded architecture, which removes the need for context switching and synchronisation between threads. This leads to reduced overhead and increased performance. This might seem rather counter-intuitive, but, in simple terms, it means that Redis handles tasks without the complications of multiple threads. This setup, combined with smart use of system features like event loops and I/O multiplexing, allows Redis to efficiently manage many connections and operations at once.
  • Non-Blocking I/O: Redis employs non-blocking I/O techniques, enabling it to manage mutiple connections at once without halting other processes, which helps maintain swift request handling, even when the system is under significant load.
  • Optimised Data Structures: Redis provides optimised data structures like Lists, Sets, Sorted Lists, Hashes, Bitmaps, Bitfields, Streams, etc which are designed to perform specific operations efficiently. For example: with Sorted Sets it is possible set operations such as union, intersection, set difference, and compute cardinality.
  • Lua Scripting: Redis offers Lua scripting support, enabling developers to craft intricate commands and run them directly on the server. This feature minimises network delay and latency and boosts efficiency by executing scripts server-side.

References:

Jemalloc General Purpose Memory Allocator

Lua Scripting

Confused about Parallelism and Concurrency? Stop here!

Rob Pike, one of Golang’s dads, 8 years ago gave one of the best programming talks I am aware of at Heroku’s Waza conference titled: “Concurrency is not Parallelism”. The beauty of this talk is his clear compare and contrast exercise between Concurrency and Parallelism whereby Concurrency is defined as:

“Programming as the composition of independently executing processes”

as opposed to Parallelism that is:

“Programming as the simultaneous execution of (possibly related) computations”

Enjoy the video, it is pure gold!

https://www.youtube.com/watch?v=oV9rvDllKEg
Slides: https://go.dev/talks/2012/waza.slide#1

Also the illuminating talk at Google I/0 2012 on Concurrency patter: https://www.youtube.com/watch?v=f6kdp27TYZs

A try-catch business in Go

An interesting article on how to use try-catch in Go. Go treats errors as normal return values, promoting a more predictable and straightforward control flow. This provides illustrates Go’s approach to error handling by reading a file and handling a panic situation, emphasising the use of defer and recover for managing fatal errors.

https://matheuspolitano.medium.com/how-use-try-catch-mechanism-in-golang-b1f97de62b9b

6 Prometheus Monitoring Mistakes to avoid

From Julius Volz, co-founder or prometheus.io and PromLabs, 6 mistakes to avoid if you are new, or even not so much, to Prometheus:

High Cardinality, aka the number of unique time series as stored in the db;

Aggregating too many labels/dimensions – usage of the aggregation operators such as by;

Unscoped Metric Selectors – this would cause conflicts if we do not target the specific endpoint or service we are interested in;

Missing for Durations in Alerting Rules – to protect against data that might present gaps;

Short Rate windows – to calculate a trend Prometheus needs at least 2 samples, therefore too short windows might not provide you with the required samples;

Using rate with the wrong metric type – For example, rate, irate and increase only work with counters!

https://www.youtube.com/watch?v=NEMsO1qeI1s