{"id":67440,"date":"2024-09-30T18:25:40","date_gmt":"2024-09-30T12:55:40","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=67440"},"modified":"2024-10-03T13:05:31","modified_gmt":"2024-10-03T07:35:31","slug":"exploring-garnet-a-next-generation-cache-store-by-microsoft","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/exploring-garnet-a-next-generation-cache-store-by-microsoft\/","title":{"rendered":"Exploring Garnet: A Next-Generation Cache-Store By Microsoft"},"content":{"rendered":"<p>Garnet is an exciting project from Microsoft Research that addresses the ever-growing demand for efficient data storage mechanisms to support interactive web applications and services. Let\u2019s dive into the details:<\/p>\n<h3>Introducing Garnet: A Next-Generation Cache-Store<\/h3>\n<h4>What Is Garnet?<\/h4>\n<p>Garnet is an open-source, next-generation cache-store system designed to offer high performance, extensibility, and low latency. Researchers at Microsoft have been working on Garnet for nearly a decade, aiming to tackle the challenges posed by the rapid advances in interactive web applications and services.<\/p>\n<h4>Key Advantages of Garnet:<\/h4>\n<ol>\n<li><strong>Performance Gains<\/strong>: Garnet has been deployed in various use cases at Microsoft, including the Windows &amp; Web Experiences Platform, Azure Resource Manager, and Azure Resource Graph. Its performance improvements over legacy cache-stores are significant.<\/li>\n<li><strong>Extensibility<\/strong>: Unlike some existing cache systems, Garnet is explicitly designed to be easily extensible by application developers. This means you can build on its capabilities and tailor it to your specific needs.<\/li>\n<li><strong>Rich Feature Set<\/strong>: Garnet supports more than just simple get\/set operations. It offers APIs for raw strings, analytic data structures (like Hyperloglog), and complex data types (such as sorted sets and hash). Additionally, it allows users to checkpoint and recover the cache, create data shards, maintain replicated copies, and even handle transactions.<\/li>\n<li><strong>Thread-Scalable<\/strong>: Garnet scales well within a single node, making it suitable for multi-core architectures.<\/li>\n<li><strong>Open Source<\/strong>: Garnet is now available as an open-source download on GitHub. Microsoft aims to encourage collaboration, academic research, and further development in this critical area by open-sourcing it.<\/li>\n<\/ol>\n<h4>Use Cases and Deployment<\/h4>\n<p>Garnet has already found its way into various Microsoft services, demonstrating its practical applicability. Whether you\u2019re dealing with Windows applications, web experiences, or managing resources in Azure, Garnet can help improve performance and reduce operational costs.<\/p>\n<h3>How to Get Started with Garnet<\/h3>\n<p>If you\u2019re interested in exploring Garnet further, head over to the official Garnet GitHub repository to access the source code, documentation, and community discussions.<\/p>\n<p>Use Docker for localhost work<\/p>\n<pre>docker run --network=host --ulimit memlock=-1 ghcr.io\/microsoft\/garnet<\/pre>\n<p>On Linux configured with basic authentication, replace\u00a0{{replace_password_here}}\u00a0with your password<\/p>\n<pre>docker run --network=host --ulimit memlock=-1 ghcr.io\/microsoft\/garnet --auth Password --password {{replace_password_here}}<\/pre>\n<h3>Examples<\/h3>\n<h4>Garnet with Console Application<\/h4>\n<p>Garnet implementation is as easy as RedisStack.<\/p>\n<pre>using System;\u00a0\u00a0\r\nusing System.Threading.Tasks;\u00a0 \r\nusing Garnet.Client;\u00a0 \r\nnamespace GarnetClientSample\u00a0 \r\n{\u00a0 \r\n  \u00a0 class Program\u00a0\u00a0\r\n  \u00a0 {\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 static async Task Main(string[] args)\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 {\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ Replace with your Garnet server details (hostname and port)\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 var garnetServer = new GarnetServer(\"localhost\", 6379);\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 {\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ Connect to the Garnet server\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 await garnetServer.ConnectAsync();\u00a0\u00a0\r\n\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ Set a key-value pair\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 await garnetServer.SetAsync(\"myKey\", \"Hello, Garnet!\");\u00a0\u00a0\r\n\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ Retrieve the value for a key\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 var retrievedValue = await garnetServer.GetAsync(\"myKey\");\u00a0\u00a0\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Console.WriteLine($\"Retrieved value: {retrievedValue}\");\u00a0\u00a0\r\n\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ Delete the key\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 await garnetServer.DeleteAsync(\"myKey\");\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 catch (Exception ex)\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 {\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Console.WriteLine($\"Error: {ex.Message}\");\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 finally\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 {\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ Clean up and disconnect\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 await garnetServer.DisconnectAsync();\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\u00a0\u00a0\r\n  \u00a0 \u00a0 \u00a0 }\u00a0\u00a0\r\n  \u00a0 }\u00a0\u00a0\r\n}<\/pre>\n<h4>Garnet with ASP.NET WebAPI C#<\/h4>\n<p>In Program.cs or startup.cs<\/p>\n<pre>using Garnet.Server; \r\n\/\/ ... \r\n\r\npublic void ConfigureServices(IServiceCollection services)\u00a0\r\n{ \r\n  \u00a0 \/\/ Other services...\u00a0\r\n  \u00a0 services.AddGarnet(options =&gt;\u00a0\r\n  \u00a0 {\u00a0\r\n  \u00a0 \u00a0 \u00a0 options.Hostname = \"localhost\"; \/\/ Garnet server hostname\u00a0\r\n  \u00a0 \u00a0 \u00a0 options.Port = 6379; \/\/ Garnet server port\u00a0\r\n  \u00a0 });\u00a0\r\n}<\/pre>\n<p>In Controller class<\/p>\n<pre>using System;\u00a0\r\nusing System.Threading.Tasks; \r\nusing Garnet.Client; \r\nusing Microsoft.AspNetCore.Mvc; \r\n\r\nnamespace GarnetWebApi.Controllers \r\n{ \r\n\r\n\u00a0 \u00a0 [ApiController]\u00a0\r\n  \u00a0 [Route(\"api\/[controller]\")]\u00a0\r\n  \u00a0 public class CacheController : ControllerBase \r\n  \u00a0 {\u00a0\r\n  \u00a0 \u00a0 \u00a0 private readonly GarnetServer _garnetServer;\u00a0\r\n  \u00a0 \u00a0 \u00a0 public CacheController(GarnetServer garnetServer)\u00a0\r\n  \u00a0 \u00a0 \u00a0 {\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 _garnetServer = garnetServer; \r\n  \u00a0 \u00a0 \u00a0 }\u00a0\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 [HttpGet(\"{key}\")]\u00a0\r\n  \u00a0 \u00a0 \u00a0 public async Task&lt;IActionResult&gt; Get(string key)\u00a0\r\n  \u00a0 \u00a0 \u00a0 { \r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 {\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 var value = await _garnetServer.GetAsync(key);\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return Ok(value);\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 catch (Exception ex)\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 {\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return BadRequest($\"Error: {ex.Message}\"); \r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\u00a0\r\n  \u00a0 \u00a0 \u00a0 }\u00a0\r\n\r\n\u00a0 \u00a0 \u00a0 \u00a0 [HttpPost(\"{key}\")]\u00a0\r\n  \u00a0 \u00a0 \u00a0 public async Task&lt;IActionResult&gt; Set(string key, [FromBody] string value)\u00a0\r\n  \u00a0 \u00a0 \u00a0 {\u00a0 \r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try \r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 {\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 await _garnetServer.SetAsync(key, value);\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return Ok(\"Value set successfully!\");\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 catch (Exception ex)\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 {\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return BadRequest($\"Error: {ex.Message}\");\u00a0\r\n  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\u00a0\r\n  \u00a0 \u00a0 \u00a0 }\u00a0\r\n  \u00a0 } \r\n}<\/pre>\n<p>Garnet is way more than this, so please feel free to try it in your project&#8217;s cache requirement or try it just for fun.<\/p>\n<p>Happy Coding \ud83d\ude80<\/p>\n<p>&nbsp;<\/p>\n<h3>Sources:<\/h3>\n<ul>\n<li><a href=\"https:\/\/www.microsoft.com\/en-us\/research\/blog\/introducing-garnet-an-open-source-next-generation-faster-cache-store-for-accelerating-applications-and-services\/\">Introducing Garnet \u2013 an open-source, next-generation, faster cache-store for accelerating applications and services<\/a><\/li>\n<li><a href=\"https:\/\/www.microsoft.com\/en-us\/research\/project\/garnet\/overview\/\">Garnet &#8211; Microsoft Research: Overview\u00a0<\/a><\/li>\n<li><a href=\"https:\/\/www.microsoft.com\/en-us\/research\/project\/garnet\/microsoft-research-blog\/\">Garnet: Microsoft Research blog &#8211; Microsoft Research<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/garnet\">Garnet: Github Repository<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Garnet is an exciting project from Microsoft Research that addresses the ever-growing demand for efficient data storage mechanisms to support interactive web applications and services. Let\u2019s dive into the details: Introducing Garnet: A Next-Generation Cache-Store What Is Garnet? Garnet is an open-source, next-generation cache-store system designed to offer high performance, extensibility, and low latency. Researchers [&hellip;]<\/p>\n","protected":false},"author":2005,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":205},"categories":[5867],"tags":[1072,6734,6699,6733,6701,6698],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/67440"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/2005"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=67440"}],"version-history":[{"count":7,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/67440\/revisions"}],"predecessor-version":[{"id":68096,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/67440\/revisions\/68096"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=67440"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=67440"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=67440"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}