├── .gitignore
├── README.md
├── lesson_1
└── interacting_with_redis.linq
├── lesson_2
├── AspNetCoreRedis
│ ├── AspNetCoreRedis.sln
│ └── AspNetCoreRedis
│ │ ├── AspNetCoreRedis.csproj
│ │ ├── Controllers
│ │ └── HomeController.cs
│ │ ├── Program.cs
│ │ ├── Properties
│ │ └── launchSettings.json
│ │ ├── Startup.cs
│ │ ├── appsettings.Development.json
│ │ └── appsettings.json
└── interacting_with_redis_clients.linq
├── lesson_3
├── CachingStrategies
│ ├── CachingStrategies.sln
│ └── CachingStrategies
│ │ ├── 0_MemoryCache.cs
│ │ ├── 0_RedisCache.cs
│ │ ├── 1_NamespacedCache.cs
│ │ ├── 2_FallBackCache.cs
│ │ ├── 3_WriteThroughCache.cs
│ │ ├── 4_WriteBackCache.cs
│ │ ├── CachingStrategies.csproj
│ │ └── Extensions.cs
├── aside_read.png
├── lazy_read.png
├── write_aside.png
├── write_back.png
└── write_through.png
├── lesson_4
└── WebApp
│ ├── Dockerfile
│ ├── WebApp.sln
│ └── WebApp
│ ├── DefaultController.cs
│ ├── IDistributedCacheExtensions.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── ServiceOne.cs
│ ├── ServiceThree.cs
│ ├── ServiceTwo.cs
│ ├── Startup.cs
│ ├── WebApp.csproj
│ ├── appsettings.Development.json
│ └── appsettings.json
└── lesson_6
├── distributed_cache_ttl.linq
└── redis_lru_policy_check.linq
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | bin
3 | obj
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Redis Distributed Caching with ASPNET Core & Redis
2 |
3 | [Full Youtube playlist](https://youtube.com/playlist?list=PLOeFnOV9YBa77eJeW39a5Q2lsyfdxpE_d)
4 |
5 | ## Episodes
6 | 1. [Introduction & Setup](https://youtu.be/fb0XZTAURCo)
7 | 2. [StackExchange.Redis & IDistributedCaching](https://youtu.be/rsXvpCHdldg)
8 | 3. [Caching Strategies & Theory](https://youtu.be/EJ73Bl3AtFY)
9 | 4. [Project Setup & Practice](https://youtu.be/eNEAdd8J-WY)
10 | 5. [Running in the Cloud](https://youtu.be/-heHQR1Jmuk)
11 | 6. [Configuration and Final Thoughts](https://youtu.be/u05Y_H1rE-c)
12 |
--------------------------------------------------------------------------------
/lesson_1/interacting_with_redis.linq:
--------------------------------------------------------------------------------
1 |
2 | System.Net.Sockets
3 |
4 |
5 | void Main()
6 | {
7 | var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
8 |
9 | socket.Connect("127.0.0.1", 6379);
10 |
11 | var responseStream = new BufferedStream(new NetworkStream(socket), 1024);
12 |
13 | var requestString = "*2\r\n$3\r\nGET\r\n$3\r\ncat\r\n";
14 | byte[] request = Encoding.UTF8.GetBytes(requestString);
15 | socket.Send(request);
16 |
17 |
18 | var result = new StringBuilder();
19 | int b;
20 |
21 | while((b = responseStream.ReadByte()) != -1){
22 | if(b == '\r'){
23 | responseStream.ReadByte();
24 | break;
25 | }
26 | result.Append((char) b);
27 | }
28 |
29 | var responseLength = int.Parse(result.ToString().Substring(1));
30 | var responseValue = new byte[responseLength];
31 | responseStream.Read(responseValue, 0, responseLength);
32 | Encoding.UTF8.GetString(responseValue).Dump("result");
33 | }
--------------------------------------------------------------------------------
/lesson_2/AspNetCoreRedis/AspNetCoreRedis.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCoreRedis", "AspNetCoreRedis\AspNetCoreRedis.csproj", "{CFA58D2B-163F-4BC2-9382-625254C8982A}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Any CPU = Debug|Any CPU
8 | Release|Any CPU = Release|Any CPU
9 | EndGlobalSection
10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
11 | {CFA58D2B-163F-4BC2-9382-625254C8982A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12 | {CFA58D2B-163F-4BC2-9382-625254C8982A}.Debug|Any CPU.Build.0 = Debug|Any CPU
13 | {CFA58D2B-163F-4BC2-9382-625254C8982A}.Release|Any CPU.ActiveCfg = Release|Any CPU
14 | {CFA58D2B-163F-4BC2-9382-625254C8982A}.Release|Any CPU.Build.0 = Release|Any CPU
15 | EndGlobalSection
16 | EndGlobal
17 |
--------------------------------------------------------------------------------
/lesson_2/AspNetCoreRedis/AspNetCoreRedis/AspNetCoreRedis.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson_2/AspNetCoreRedis/AspNetCoreRedis/Controllers/HomeController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.Extensions.Caching.Distributed;
4 |
5 | namespace AspNetCoreRedis.Controllers
6 | {
7 | public class HomeController : ControllerBase
8 | {
9 | public IActionResult Index([FromServices] IDistributedCache cache)
10 | {
11 | return Ok(cache.GetString("rat"));
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/lesson_2/AspNetCoreRedis/AspNetCoreRedis/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Hosting;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.Hosting;
8 | using Microsoft.Extensions.Logging;
9 |
10 | namespace AspNetCoreRedis
11 | {
12 | public class Program
13 | {
14 | public static void Main(string[] args)
15 | {
16 | CreateHostBuilder(args).Build().Run();
17 | }
18 |
19 | public static IHostBuilder CreateHostBuilder(string[] args) =>
20 | Host.CreateDefaultBuilder(args)
21 | .ConfigureWebHostDefaults(webBuilder =>
22 | {
23 | webBuilder.UseStartup();
24 | });
25 | }
26 | }
--------------------------------------------------------------------------------
/lesson_2/AspNetCoreRedis/AspNetCoreRedis/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:6734",
7 | "sslPort": 44308
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "AspNetCoreRedis": {
19 | "commandName": "Project",
20 | "dotnetRunMessages": "true",
21 | "launchBrowser": true,
22 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
23 | "environmentVariables": {
24 | "ASPNETCORE_ENVIRONMENT": "Development"
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lesson_2/AspNetCoreRedis/AspNetCoreRedis/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Builder;
6 | using Microsoft.AspNetCore.Hosting;
7 | using Microsoft.AspNetCore.Http;
8 | using Microsoft.Extensions.DependencyInjection;
9 | using Microsoft.Extensions.Hosting;
10 |
11 | namespace AspNetCoreRedis
12 | {
13 | public class Startup
14 | {
15 | // This method gets called by the runtime. Use this method to add services to the container.
16 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
17 | public void ConfigureServices(IServiceCollection services)
18 | {
19 | services.AddControllers();
20 |
21 | services.AddStackExchangeRedisCache(config =>
22 | {
23 | config.Configuration = "127.0.0.1:6379";
24 | });
25 | }
26 |
27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
28 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
29 | {
30 | if (env.IsDevelopment())
31 | {
32 | app.UseDeveloperExceptionPage();
33 | }
34 |
35 | app.UseRouting();
36 |
37 | app.UseEndpoints(endpoints =>
38 | {
39 | endpoints.MapDefaultControllerRoute();
40 | });
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/lesson_2/AspNetCoreRedis/AspNetCoreRedis/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lesson_2/AspNetCoreRedis/AspNetCoreRedis/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*"
10 | }
11 |
--------------------------------------------------------------------------------
/lesson_2/interacting_with_redis_clients.linq:
--------------------------------------------------------------------------------
1 |
2 | Microsoft.Extensions.Caching.StackExchangeRedis
3 | StackExchange.Redis
4 | StackExchange.Redis
5 | Microsoft.Extensions.Caching.StackExchangeRedis
6 | Microsoft.Extensions.Options
7 | Microsoft.Extensions.Caching.Distributed
8 |
9 |
10 | void Main()
11 | {
12 | //ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("127.0.0.1");
13 | //
14 | //IDatabase db = redis.GetDatabase();
15 | //
16 | //db.StringGet("dog").Dump();
17 | //db.StringGet("cat").Dump();
18 |
19 |
20 | var options = Options.Create(new RedisCacheOptions()
21 | {
22 | Configuration = "127.0.0.1:6379"
23 | });
24 | IDistributedCache cache = new RedisCache(options);
25 |
26 | //cache.SetString("rat", "bob");
27 | cache.GetString("rat").Dump();
28 |
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/lesson_3/CachingStrategies/CachingStrategies.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CachingStrategies", "CachingStrategies\CachingStrategies.csproj", "{36A4E26C-46B7-49DE-B6E9-120616F9CB7E}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Any CPU = Debug|Any CPU
8 | Release|Any CPU = Release|Any CPU
9 | EndGlobalSection
10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
11 | {36A4E26C-46B7-49DE-B6E9-120616F9CB7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12 | {36A4E26C-46B7-49DE-B6E9-120616F9CB7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
13 | {36A4E26C-46B7-49DE-B6E9-120616F9CB7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
14 | {36A4E26C-46B7-49DE-B6E9-120616F9CB7E}.Release|Any CPU.Build.0 = Release|Any CPU
15 | EndGlobalSection
16 | EndGlobal
17 |
--------------------------------------------------------------------------------
/lesson_3/CachingStrategies/CachingStrategies/0_MemoryCache.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Microsoft.Extensions.Caching.Distributed;
5 |
6 | namespace CachingStrategies
7 | {
8 | public class MemoryCache : IDistributedCache
9 | {
10 | public byte[] Get(string key)
11 | {
12 | throw new System.NotImplementedException();
13 | }
14 |
15 | public Task GetAsync(string key, CancellationToken token = new CancellationToken())
16 | {
17 | throw new System.NotImplementedException();
18 | }
19 |
20 | public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
21 | {
22 | throw new System.NotImplementedException();
23 | }
24 |
25 | public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = new CancellationToken())
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public void Refresh(string key)
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public Task RefreshAsync(string key, CancellationToken token = new CancellationToken())
36 | {
37 | throw new System.NotImplementedException();
38 | }
39 |
40 | public void Remove(string key)
41 | {
42 | throw new System.NotImplementedException();
43 | }
44 |
45 | public Task RemoveAsync(string key, CancellationToken token = new CancellationToken())
46 | {
47 | throw new System.NotImplementedException();
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/lesson_3/CachingStrategies/CachingStrategies/0_RedisCache.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using System.Threading.Tasks;
3 | using Microsoft.Extensions.Caching.Distributed;
4 |
5 | namespace CachingStrategies
6 | {
7 | public class RedisCache : IDistributedCache
8 | {
9 | public byte[] Get(string key)
10 | {
11 | throw new System.NotImplementedException();
12 | }
13 |
14 | public Task GetAsync(string key, CancellationToken token = new CancellationToken())
15 | {
16 | throw new System.NotImplementedException();
17 | }
18 |
19 | public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
20 | {
21 | throw new System.NotImplementedException();
22 | }
23 |
24 | public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = new CancellationToken())
25 | {
26 | throw new System.NotImplementedException();
27 | }
28 |
29 | public void Refresh(string key)
30 | {
31 | throw new System.NotImplementedException();
32 | }
33 |
34 | public Task RefreshAsync(string key, CancellationToken token = new CancellationToken())
35 | {
36 | throw new System.NotImplementedException();
37 | }
38 |
39 | public void Remove(string key)
40 | {
41 | throw new System.NotImplementedException();
42 | }
43 |
44 | public Task RemoveAsync(string key, CancellationToken token = new CancellationToken())
45 | {
46 | throw new System.NotImplementedException();
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/lesson_3/CachingStrategies/CachingStrategies/1_NamespacedCache.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using System.Threading.Tasks;
3 | using Microsoft.Extensions.Caching.Distributed;
4 |
5 | namespace CachingStrategies
6 | {
7 | public class NamespacedCache : IDistributedCache
8 | {
9 | private readonly IDistributedCache _cache;
10 | private readonly string _name;
11 |
12 | public NamespacedCache(IDistributedCache cache, string name)
13 | {
14 | _cache = cache.ToNamespaced("products");
15 | _name = name;
16 | }
17 |
18 | public byte[] Get(string key) => _cache.Get(_name + key);
19 |
20 | public Task GetAsync(string key, CancellationToken token = new CancellationToken())
21 | {
22 | throw new System.NotImplementedException();
23 | }
24 |
25 | public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
26 | {
27 | throw new System.NotImplementedException();
28 | }
29 |
30 | public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = new CancellationToken())
31 | {
32 | throw new System.NotImplementedException();
33 | }
34 |
35 | public void Refresh(string key)
36 | {
37 | throw new System.NotImplementedException();
38 | }
39 |
40 | public Task RefreshAsync(string key, CancellationToken token = new CancellationToken())
41 | {
42 | throw new System.NotImplementedException();
43 | }
44 |
45 | public void Remove(string key)
46 | {
47 | throw new System.NotImplementedException();
48 | }
49 |
50 | public Task RemoveAsync(string key, CancellationToken token = new CancellationToken())
51 | {
52 | throw new System.NotImplementedException();
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/lesson_3/CachingStrategies/CachingStrategies/2_FallBackCache.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Microsoft.Extensions.Caching.Distributed;
5 |
6 | namespace CachingStrategies
7 | {
8 | public class FallBackCache : IDistributedCache
9 | {
10 | private readonly IDistributedCache _main;
11 | private readonly IDistributedCache _secondary;
12 |
13 | private int failCount;
14 |
15 | public FallBackCache(IDistributedCache main, IDistributedCache secondary)
16 | {
17 | _main = main;
18 | _secondary = secondary;
19 | }
20 |
21 | public byte[] Get(string key)
22 | {
23 | try
24 | {
25 | if (failCount < 3)
26 | _main.Get(key);
27 | }
28 | catch (Exception e)
29 | {
30 | failCount++;
31 | }
32 |
33 | return _secondary.Get(key);
34 | }
35 |
36 | public Task GetAsync(string key, CancellationToken token = new CancellationToken())
37 | {
38 | throw new System.NotImplementedException();
39 | }
40 |
41 | public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
42 | {
43 | throw new System.NotImplementedException();
44 | }
45 |
46 | public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = new CancellationToken())
47 | {
48 | throw new System.NotImplementedException();
49 | }
50 |
51 | public void Refresh(string key)
52 | {
53 | throw new System.NotImplementedException();
54 | }
55 |
56 | public Task RefreshAsync(string key, CancellationToken token = new CancellationToken())
57 | {
58 | throw new System.NotImplementedException();
59 | }
60 |
61 | public void Remove(string key)
62 | {
63 | throw new System.NotImplementedException();
64 | }
65 |
66 | public Task RemoveAsync(string key, CancellationToken token = new CancellationToken())
67 | {
68 | throw new System.NotImplementedException();
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/lesson_3/CachingStrategies/CachingStrategies/3_WriteThroughCache.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using System.Threading.Tasks;
3 | using Microsoft.Extensions.Caching.Distributed;
4 |
5 | namespace CachingStrategies
6 | {
7 | public class WriteThroughCache : IDistributedCache
8 | {
9 | private readonly IDistributedCache _main;
10 | private readonly IDistributedCache _secondary;
11 |
12 | public WriteThroughCache(IDistributedCache main, IDistributedCache secondary)
13 | {
14 | _main = main;
15 | _secondary = secondary;
16 | }
17 |
18 | // read aside
19 | public byte[] Get(string key)
20 | {
21 | var value = _secondary.Get(key);
22 | if (value == null)
23 | {
24 | value = _main.Get(key);
25 | _secondary.Set(key, value);
26 | }
27 |
28 | return value;
29 | }
30 |
31 | public Task GetAsync(string key, CancellationToken token = new CancellationToken())
32 | {
33 | throw new System.NotImplementedException();
34 | }
35 |
36 | public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
37 | {
38 | _secondary.Set(key, value);
39 | _main.Set(key, value);
40 | }
41 |
42 | public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = new CancellationToken())
43 | {
44 | throw new System.NotImplementedException();
45 | }
46 |
47 | public void Refresh(string key)
48 | {
49 | throw new System.NotImplementedException();
50 | }
51 |
52 | public Task RefreshAsync(string key, CancellationToken token = new CancellationToken())
53 | {
54 | throw new System.NotImplementedException();
55 | }
56 |
57 | public void Remove(string key)
58 | {
59 | throw new System.NotImplementedException();
60 | }
61 |
62 | public Task RemoveAsync(string key, CancellationToken token = new CancellationToken())
63 | {
64 | throw new System.NotImplementedException();
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/lesson_3/CachingStrategies/CachingStrategies/4_WriteBackCache.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using Microsoft.Extensions.Caching.Distributed;
6 |
7 | namespace CachingStrategies
8 | {
9 | public class WriteBackCache : IDistributedCache
10 | {
11 | private readonly IDistributedCache _main;
12 | private readonly IDistributedCache _secondary;
13 |
14 | public WriteBackCache(IDistributedCache main, IDistributedCache secondary)
15 | {
16 | _main = main;
17 | _secondary = secondary;
18 | _backgroundTask = Task.Run(WriteBack);
19 | }
20 |
21 | public byte[] Get(string key)
22 | {
23 | throw new System.NotImplementedException();
24 | }
25 |
26 | public Task GetAsync(string key, CancellationToken token = new CancellationToken())
27 | {
28 | throw new System.NotImplementedException();
29 | }
30 |
31 | private List> writeBackBuffer = new();
32 | private readonly Task _backgroundTask;
33 |
34 | private async Task WriteBack()
35 | {
36 | while (true)
37 | {
38 | try
39 | {
40 | if (writeBackBuffer.Count > 100)
41 | {
42 | // build batch update
43 | }
44 |
45 | await Task.Delay(1000 * 60);
46 | }
47 | catch (Exception e)
48 | {
49 |
50 | }
51 | }
52 | }
53 |
54 | public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
55 | {
56 | _secondary.Set(key, value);
57 | writeBackBuffer.Add(KeyValuePair.Create(key, value));
58 | }
59 |
60 | public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = new CancellationToken())
61 | {
62 | throw new System.NotImplementedException();
63 | }
64 |
65 | public void Refresh(string key)
66 | {
67 | throw new System.NotImplementedException();
68 | }
69 |
70 | public Task RefreshAsync(string key, CancellationToken token = new CancellationToken())
71 | {
72 | throw new System.NotImplementedException();
73 | }
74 |
75 | public void Remove(string key)
76 | {
77 | throw new System.NotImplementedException();
78 | }
79 |
80 | public Task RemoveAsync(string key, CancellationToken token = new CancellationToken())
81 | {
82 | throw new System.NotImplementedException();
83 | }
84 | }
85 | }
--------------------------------------------------------------------------------
/lesson_3/CachingStrategies/CachingStrategies/CachingStrategies.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson_3/CachingStrategies/CachingStrategies/Extensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Caching.Distributed;
2 |
3 | namespace CachingStrategies
4 | {
5 | public static class Extensions
6 | {
7 | public static IDistributedCache ToNamespaced(this IDistributedCache @this, string name) =>
8 | new NamespacedCache(@this, name);
9 | }
10 | }
--------------------------------------------------------------------------------
/lesson_3/aside_read.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raw-coding-youtube/aspnetcore-redis-distributed-caching/7a8f5e6dc527e172c9eba2c51fcb501a0dc04dba/lesson_3/aside_read.png
--------------------------------------------------------------------------------
/lesson_3/lazy_read.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raw-coding-youtube/aspnetcore-redis-distributed-caching/7a8f5e6dc527e172c9eba2c51fcb501a0dc04dba/lesson_3/lazy_read.png
--------------------------------------------------------------------------------
/lesson_3/write_aside.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raw-coding-youtube/aspnetcore-redis-distributed-caching/7a8f5e6dc527e172c9eba2c51fcb501a0dc04dba/lesson_3/write_aside.png
--------------------------------------------------------------------------------
/lesson_3/write_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raw-coding-youtube/aspnetcore-redis-distributed-caching/7a8f5e6dc527e172c9eba2c51fcb501a0dc04dba/lesson_3/write_back.png
--------------------------------------------------------------------------------
/lesson_3/write_through.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raw-coding-youtube/aspnetcore-redis-distributed-caching/7a8f5e6dc527e172c9eba2c51fcb501a0dc04dba/lesson_3/write_through.png
--------------------------------------------------------------------------------
/lesson_4/WebApp/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/aspnet:5.0
2 |
3 | WORKDIR /app
4 |
5 | COPY WebApp/bin/Release/net5.0/publish .
6 |
7 | EXPOSE 5000
8 |
9 | CMD ["dotnet", "WebApp.dll"]
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApp", "WebApp\WebApp.csproj", "{9472701A-3B77-461D-B005-B1C1A9008BE4}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Any CPU = Debug|Any CPU
8 | Release|Any CPU = Release|Any CPU
9 | EndGlobalSection
10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
11 | {9472701A-3B77-461D-B005-B1C1A9008BE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12 | {9472701A-3B77-461D-B005-B1C1A9008BE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
13 | {9472701A-3B77-461D-B005-B1C1A9008BE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
14 | {9472701A-3B77-461D-B005-B1C1A9008BE4}.Release|Any CPU.Build.0 = Release|Any CPU
15 | EndGlobalSection
16 | EndGlobal
17 |
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp/DefaultController.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 | using System.Threading.Tasks;
3 | using Microsoft.AspNetCore.Http;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.Extensions.Caching.Distributed;
6 |
7 | namespace WebApp
8 | {
9 | public class DefaultController : ControllerBase
10 | {
11 | private readonly IDistributedCache _cache;
12 |
13 | public DefaultController(IDistributedCache cache)
14 | {
15 | _cache = cache;
16 | }
17 |
18 | [HttpGet("/one")]
19 | public async Task One([FromServices] ServiceOne one, [FromQuery] int n = 1)
20 | {
21 | var res = await _cache.GetOrAddAsync(n, one.GetCarAsync);
22 |
23 | return Ok(res);
24 | }
25 |
26 | [HttpGet("/two")]
27 | public async Task Two([FromServices] ServiceTwo two, [FromQuery] string key = "foo")
28 | {
29 | var res = await _cache.GetOrAddAsync(key, two.GetNameAsync);
30 |
31 | return Ok(res);
32 | }
33 |
34 | [HttpGet("/three")]
35 | public async Task Three([FromServices] ServiceThree three)
36 | {
37 | Dude dude = new(1, "Bob");
38 | await _cache.SetAsync(dude);
39 | await three.SaveDudeAsync(dude);
40 | return Ok();
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp/IDistributedCacheExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.Json;
3 | using System.Threading.Tasks;
4 | using Microsoft.Extensions.Caching.Distributed;
5 |
6 | namespace WebApp
7 | {
8 | public static class IDistributedCacheExtensions
9 | {
10 | public static async Task> GetOrAddAsync(
11 | this IDistributedCache cache,
12 | TKey anyKey,
13 | Func> factory
14 | )
15 | where T : class
16 | {
17 | var key = anyKey switch
18 | {
19 | string k => k,
20 | _ => anyKey.ToString(),
21 | };
22 |
23 | var value = await cache.GetAsync(key);
24 | if (value == null)
25 | {
26 | value = await factory(anyKey);
27 | await cache.SetStringAsync(key, JsonSerializer.Serialize(value));
28 | return new(false, value);
29 | }
30 |
31 | return new(true, value);
32 | }
33 |
34 | public static async Task GetAsync(this IDistributedCache cache, string key)
35 | where T : class
36 | {
37 | var jsonValue = await cache.GetStringAsync(key);
38 | if (string.IsNullOrEmpty(jsonValue))
39 | {
40 | return null;
41 | }
42 |
43 | return JsonSerializer.Deserialize(jsonValue);
44 | }
45 |
46 | public static async Task GetLongAsync(this IDistributedCache cache, string key)
47 | {
48 | var value = await cache.GetAsync(key);
49 | return BitConverter.ToInt64(value);
50 | }
51 |
52 | public static Task SetLongAsync(this IDistributedCache cache, string key, long value)
53 | {
54 | return cache.SetAsync(key, BitConverter.GetBytes(value));
55 | }
56 |
57 | public static async Task GetDateTimeAsync(this IDistributedCache cache, string key)
58 | {
59 | var value = await cache.GetAsync(key);
60 | var ticks = BitConverter.ToInt64(value);
61 | return new(ticks);
62 | }
63 |
64 | public static Task SetDateTimeAsync(this IDistributedCache cache, string key, DateTime value)
65 | {
66 | var ticks = value.Ticks;
67 | return cache.SetAsync(key, BitConverter.GetBytes(ticks));
68 | }
69 |
70 | public static Task SetAsync(this IDistributedCache cache, T value)
71 | where T : ICacheKey
72 | {
73 | return cache.SetStringAsync(value.CacheKey, JsonSerializer.Serialize(value));
74 | }
75 |
76 | public record GetCachedValue(bool Cached, T value);
77 | }
78 | }
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Hosting;
2 | using Microsoft.Extensions.Hosting;
3 |
4 | namespace WebApp
5 | {
6 | public class Program
7 | {
8 | public static void Main(string[] args)
9 | {
10 | CreateHostBuilder(args).Build().Run();
11 | }
12 |
13 | public static IHostBuilder CreateHostBuilder(string[] args) =>
14 | Host.CreateDefaultBuilder(args)
15 | .ConfigureWebHostDefaults(webBuilder =>
16 | {
17 | webBuilder.UseStartup()
18 | .UseUrls("http://0.0.0.0:5000");
19 | });
20 | }
21 | }
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:19848",
7 | "sslPort": 44328
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "WebApp": {
19 | "commandName": "Project",
20 | "dotnetRunMessages": "true",
21 | "launchBrowser": true,
22 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
23 | "environmentVariables": {
24 | "ASPNETCORE_ENVIRONMENT": "Development"
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp/ServiceOne.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace WebApp
4 | {
5 | public class ServiceOne
6 | {
7 | public async Task GetCarAsync(int id)
8 | {
9 | await Task.Delay(5000);
10 | return new(id, $"Volvo {id}", "Me");
11 | }
12 | }
13 |
14 | public record Car(int Id, string Mark, string Owner);
15 | }
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp/ServiceThree.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace WebApp
4 | {
5 | public class ServiceThree
6 | {
7 | public Task SaveDudeAsync(Dude dude) => Task.CompletedTask;
8 | }
9 |
10 | public record Dude(int Id, string Name, bool Cool = true) : ICacheKey
11 | {
12 | public string CacheKey => $"dude_{Id}";
13 | }
14 |
15 | public interface ICacheKey
16 | {
17 | string CacheKey { get; }
18 | }
19 | }
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp/ServiceTwo.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace WebApp
4 | {
5 | public class ServiceTwo
6 | {
7 | public Task GetNameAsync(string id) => Task.FromResult("Bob");
8 | }
9 | }
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.AspNetCore.Builder;
3 | using Microsoft.AspNetCore.Hosting;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.Hosting;
6 |
7 | namespace WebApp
8 | {
9 | public class Startup
10 | {
11 | private readonly IWebHostEnvironment _env;
12 |
13 | public Startup(IWebHostEnvironment env) => _env = env;
14 |
15 | public void ConfigureServices(IServiceCollection services)
16 | {
17 | services.AddControllers();
18 |
19 | services.AddStackExchangeRedisCache(config =>
20 | {
21 | config.Configuration = _env.IsDevelopment()
22 | ? "127.0.0.1:6379"
23 | : Environment.GetEnvironmentVariable("REDIS_URL");
24 | }
25 | );
26 |
27 | services.AddTransient()
28 | .AddTransient()
29 | .AddTransient();
30 | }
31 |
32 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
33 | {
34 | if (env.IsDevelopment())
35 | {
36 | app.UseDeveloperExceptionPage();
37 | }
38 |
39 | app.UseRouting();
40 |
41 | app.UseEndpoints(endpoints =>
42 | {
43 | endpoints.MapDefaultControllerRoute();
44 | });
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp/WebApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net5.0
5 | 9.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lesson_4/WebApp/WebApp/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*"
10 | }
11 |
--------------------------------------------------------------------------------
/lesson_6/distributed_cache_ttl.linq:
--------------------------------------------------------------------------------
1 |
2 | Microsoft.Extensions.Caching.StackExchangeRedis
3 | StackExchange.Redis
4 | StackExchange.Redis
5 | Microsoft.Extensions.Caching.StackExchangeRedis
6 | Microsoft.Extensions.Options
7 | Microsoft.Extensions.Caching.Distributed
8 | System.Threading.Tasks
9 |
10 |
11 | IDistributedCache _cache = new RedisCache(
12 | Options.Create(new RedisCacheOptions()
13 | {
14 | Configuration = "127.0.0.1:6379"
15 | })
16 | );
17 |
18 | void Main()
19 | {
20 | //AbsoluteExpiration();
21 |
22 | // SlidingExpiration();
23 |
24 | _cache.GetString("key");
25 | }
26 |
27 | public void AbsoluteExpiration()
28 | {
29 | var options = new DistributedCacheEntryOptions()
30 | {
31 | AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(20)
32 | };
33 |
34 | _cache.SetString("key", "string", options);
35 | }
36 |
37 | public void SlidingExpiration()
38 | {
39 | var options = new DistributedCacheEntryOptions()
40 | {
41 | SlidingExpiration = TimeSpan.FromSeconds(30)
42 | };
43 |
44 | _cache.SetString("key", "string", options);
45 | }
--------------------------------------------------------------------------------
/lesson_6/redis_lru_policy_check.linq:
--------------------------------------------------------------------------------
1 |
2 | Microsoft.Extensions.Caching.StackExchangeRedis
3 | StackExchange.Redis
4 | StackExchange.Redis
5 | Microsoft.Extensions.Caching.StackExchangeRedis
6 | Microsoft.Extensions.Options
7 | Microsoft.Extensions.Caching.Distributed
8 | System.Threading.Tasks
9 |
10 |
11 | void Main()
12 | {
13 | IDistributedCache cache = new RedisCache(
14 | Options.Create(new RedisCacheOptions()
15 | {
16 | Configuration = "127.0.0.1:6379"
17 | })
18 | );
19 |
20 | var twoMegabytes = (1024 * 1024 * 2);
21 | var chunks = 10;
22 | var chunkSize = twoMegabytes / chunks;
23 |
24 | var bigWords = Enumerable.Range(0, chunks + 1).Select(_ => BigA(chunkSize));
25 |
26 | int i = 0;
27 | foreach (var word in bigWords)
28 | {
29 | cache.SetString(i.ToString(), word);
30 | cache.Get(0.ToString());
31 | i++;
32 | }
33 | }
34 |
35 | public string BigA(int length)
36 | {
37 | var builder = new StringBuilder();
38 |
39 | for (int i = 0; i < length; i++)
40 | {
41 | builder.Append("a");
42 | }
43 |
44 | return builder.ToString();
45 | }
--------------------------------------------------------------------------------