Athena.Cache.Redis
1.0.0
See the version list below for details.
dotnet add package Athena.Cache.Redis --version 1.0.0
NuGet\Install-Package Athena.Cache.Redis -Version 1.0.0
<PackageReference Include="Athena.Cache.Redis" Version="1.0.0" />
<PackageVersion Include="Athena.Cache.Redis" Version="1.0.0" />
<PackageReference Include="Athena.Cache.Redis" />
paket add Athena.Cache.Redis --version 1.0.0
#r "nuget: Athena.Cache.Redis, 1.0.0"
#:package Athena.Cache.Redis@1.0.0
#addin nuget:?package=Athena.Cache.Redis&version=1.0.0
#tool nuget:?package=Athena.Cache.Redis&version=1.0.0
๐๏ธ Athena.Cache
Smart caching library for ASP.NET Core with automatic query parameter key generation and table-based cache invalidation.
Athena.Cache๋ ASP.NET Core ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ ์ง๋ฅํ ์บ์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ฅผ ์๋์ผ๋ก ์บ์ ํค๋ก ๋ณํํ๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ ๋ณ๊ฒฝ ์ ๊ด๋ จ ์บ์๋ฅผ ์๋์ผ๋ก ๋ฌดํจํํฉ๋๋ค.
โจ ์ฃผ์ ๊ธฐ๋ฅ
- ๐ **์๋ ์บ์ ํค ์์ฑ**: ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ โ SHA256 ํด์ ํค ์๋ ๋ณํ
- ๐๏ธ **ํ
์ด๋ธ ๊ธฐ๋ฐ ๋ฌดํจํ**: ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ
์ด๋ธ ๋ณ๊ฒฝ ์ ๊ด๋ จ ์บ์ ์๋ ์ญ์
- ๐ **๋ค์ค ๋ฐฑ์๋ ์ง์**: MemoryCache, Redis, Valkey ์ง์
- ๐ฏ **์ ์ธ์ ์บ์ฑ**: `[AthenaCache]`, `[CacheInvalidateOn]` ์ดํธ๋ฆฌ๋ทฐํธ
- โก **๊ณ ์ฑ๋ฅ**: ๋์ฉ๋ ํธ๋ํฝ ํ๊ฒฝ์ ์ต์ ํ
- ๐ง **์ฌ์ด ํตํฉ**: ๋ฏธ๋ค์จ์ด์ ์ก์
ํํฐ๋ก ๊ฐ๋จํ ์ค์
- ๐งช **์์ ํ ํ
์คํธ**: ํฌ๊ด์ ์ธ ๋จ์ ๋ฐ ํตํฉ ํ
์คํธ
๐ ๋น ๋ฅธ ์์
์ค์น
# ๊ธฐ๋ณธ ํจํค์ง (MemoryCache ํฌํจ)
dotnet add package Athena.Cache.Core
# Redis ์ง์
dotnet add package Athena.Cache.Redis
๊ธฐ๋ณธ ์ค์
// Program.cs
using Athena.Cache.Core.Extensions;
// ๊ฐ๋ฐ ํ๊ฒฝ (MemoryCache)
services.AddAthenaCacheComplete(options => {
options.Namespace = "MyApp_DEV";
options.DefaultExpirationMinutes = 30;
});
// ์ด์ ํ๊ฒฝ (Redis)
services.AddAthenaCacheRedisComplete(
athena => {
athena.Namespace = "MyApp_PROD";
athena.DefaultExpirationMinutes = 60;
},
redis => {
redis.ConnectionString = "localhost:6379";
redis.DatabaseId = 1;
});
// ๋ฏธ๋ค์จ์ด ์ถ๊ฐ
app.UseAthenaCache();
์ปจํธ๋กค๋ฌ์์ ์ฌ์ฉ
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
[HttpGet]
[AthenaCache(ExpirationMinutes = 30)]
[CacheInvalidateOn("Users")]
public async Task<IActionResult> GetUsers(
[FromQuery] string? search = null,
[FromQuery] int page = 1)
{
// ๋น์ฆ๋์ค ๋ก์ง
// ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก๋ถํฐ ์บ์ ํค ์๋ ์์ฑ๋จ
var users = await _userService.GetUsersAsync(search, page);
return Ok(users);
}
[HttpPost]
public async Task<IActionResult> CreateUser([FromBody] User user)
{
var createdUser = await _userService.CreateUserAsync(user);
// Users ํ
์ด๋ธ ๊ด๋ จ ์บ์ ์๋ ๋ฌดํจํ๋จ
return CreatedAtAction(nameof(GetUser), new { id = createdUser.Id }, createdUser);
}
[HttpGet("{id}")]
[AthenaCache(ExpirationMinutes = 60)]
[CacheInvalidateOn("Users")]
[CacheInvalidateOn("Orders", InvalidationType.Pattern, "User_*")]
public async Task<IActionResult> GetUser(int id)
{
var user = await _userService.GetUserByIdAsync(id);
if (user == null) return NotFound();
return Ok(user);
}
}
๐ ๏ธ ๊ณ ๊ธ ๊ธฐ๋ฅ
์ปค์คํ ์บ์ ํค
[AthenaCache(
ExpirationMinutes = 45,
CustomKeyPrefix = "UserStats",
ExcludeParameters = new[] { "debug", "trace" }
)]
public async Task<IActionResult> GetUserStatistics(int userId, bool debug = false)
{
// debug ํ๋ผ๋ฏธํฐ๋ ์บ์ ํค ์์ฑ์์ ์ ์ธ๋จ
return Ok(stats);
}
ํจํด ๊ธฐ๋ฐ ๋ฌดํจํ
[CacheInvalidateOn("Users", InvalidationType.All)] // ๋ชจ๋ Users ๊ด๋ จ ์บ์
[CacheInvalidateOn("Orders", InvalidationType.Pattern, "User_*")] // User_* ํจํด ์บ์
[CacheInvalidateOn("Products", InvalidationType.Related, "Categories")] // ์ฐ๊ด ํ
์ด๋ธ๊น์ง
public async Task<IActionResult> GetUserOrders(int userId) { ... }
์๋ ์บ์ ๊ด๋ฆฌ
public class UserService
{
private readonly IAthenaCache _cache;
private readonly ICacheInvalidator _invalidator;
public UserService(IAthenaCache cache, ICacheInvalidator invalidator)
{
_cache = cache;
_invalidator = invalidator;
}
public async Task InvalidateUserCaches(int userId)
{
// ํน์ ์ฌ์ฉ์ ๊ด๋ จ ์บ์๋ง ์ญ์
await _invalidator.InvalidateByPatternAsync($"User_{userId}_*");
}
public async Task<CacheStatistics> GetCacheStats()
{
return await _cache.GetStatisticsAsync();
}
}
๐ ์ฑ๋ฅ
- ๋์ ์ฒ๋ฆฌ๋: Redis ๊ธฐ์ค 10,000+ requests/second
- ๋ฎ์ ์ง์ฐ์๊ฐ: ์บ์ ํค ์์ฑ 1ms ๋ฏธ๋ง
- ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ: ์ต์ ํ๋ ์ง๋ ฌํ ๋ฐ ์์ถ
- ํ์ฅ ๊ฐ๋ฅ: ๋ค์ค ์ธ์คํด์ค ๋ถ์ฐ ๋ฌดํจํ ์ง์
๐ง ์ค์ ์ต์
์ ์ญ ์ค์
services.AddAthenaCacheComplete(options => {
options.Namespace = "MyApp"; // ๋ค์์คํ์ด์ค (ํ๊ฒฝ ๋ถ๋ฆฌ)
options.VersionKey = "v1.0"; // ๋ฒ์ ํค (๋ฐฐํฌ ์ ์บ์ ๋ถ๋ฆฌ)
options.DefaultExpirationMinutes = 30; // ๊ธฐ๋ณธ ๋ง๋ฃ ์๊ฐ
options.MaxRelatedDepth = 3; // ์ฐ์ ๋ฌดํจํ ์ต๋ ๊น์ด
options.StartupCacheCleanup = CleanupMode.ExpireShorten; // ์์ ์ ์ ๋ฆฌ ๋ฐฉ์
// ๋ก๊น
์ค์
options.Logging.LogCacheHitMiss = true; // ํํธ/๋ฏธ์ค ๋ก๊น
options.Logging.LogInvalidation = true; // ๋ฌดํจํ ๋ก๊น
// ์๋ฌ ์ฒ๋ฆฌ
options.ErrorHandling.SilentFallback = true; // ์กฐ์ฉํ ํด๋ฐฑ
});
Redis ์ค์
services.AddAthenaCacheRedisComplete(
athena => { /* Athena ์ค์ */ },
redis => {
redis.ConnectionString = "localhost:6379";
redis.DatabaseId = 1;
redis.KeyPrefix = "MyApp";
redis.BatchSize = 1000;
redis.ConnectTimeoutSeconds = 5;
redis.RetryCount = 3;
});
๐งช ํ ์คํธ
# ๋ชจ๋ ํ
์คํธ ์คํ
dotnet test
# ์ปค๋ฒ๋ฆฌ์ง ํฌํจ
dotnet test --collect:"XPlat Code Coverage"
# ํตํฉ ํ
์คํธ (Redis ํ์)
docker run -d -p 6379:6379 redis:7-alpine
dotnet test --filter Category=Integration
๐ ์ถ๊ฐ ๋ฌธ์
๐๏ธ ์ํคํ ์ฒ
ํต์ฌ ์ปดํฌ๋ํธ
- ICacheKeyGenerator: ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ โ ์บ์ ํค ๋ณํ
- ICacheInvalidator: ํ ์ด๋ธ ๊ธฐ๋ฐ ์บ์ ๋ฌดํจํ ๊ด๋ฆฌ
- IAthenaCache: ์บ์ ์ ๊ณต์ ์ถ์ํ (Memory/Redis/Valkey)
- AthenaCacheMiddleware: HTTP ์์ฒญ ๊ฐ๋ก์ฑ๊ธฐ ๋ฐ ์บ์ฑ
- AthenaCacheActionFilter: ์ดํธ๋ฆฌ๋ทฐํธ ๋ฉํ๋ฐ์ดํฐ ์์ง
๋์ ์๋ฆฌ
- ์์ฒญ ๊ฐ๋ก์ฑ๊ธฐ: ๋ฏธ๋ค์จ์ด๊ฐ GET ์์ฒญ์ ๊ฐ๋ก์ฑ
- ํค ์์ฑ: ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ ฌํ์ฌ SHA256 ํด์ ์์ฑ
- ์บ์ ํ์ธ: ์์ฑ๋ ํค๋ก ์บ์์์ ์๋ต ์กฐํ
- ์๋ต ์บ์ฑ: ์บ์ ๋ฏธ์ค ์ ์๋ต์ ์บ์์ ์ ์ฅ
- ๋ฌดํจํ: ํ ์ด๋ธ ๋ณ๊ฒฝ ์ ๊ด๋ จ ์บ์ ์๋ ์ญ์
๐ ์บ์ ๋ฌดํจํ ์ ๋ต
1. ์ฆ์ ๋ฌดํจํ (Immediate)
[CacheInvalidateOn("Users", InvalidationType.All)]
2. ํจํด ๋ฌดํจํ (Pattern-based)
[CacheInvalidateOn("Users", InvalidationType.Pattern, "User_*")]
3. ์ฐ๊ด ๋ฌดํจํ (Related)
[CacheInvalidateOn("Users", InvalidationType.Related, "Orders", "Profiles")]
๐ค ๊ธฐ์ฌํ๊ธฐ
- ์ ์ฅ์ ํฌํฌ
- ๊ธฐ๋ฅ ๋ธ๋์น ์์ฑ (
git checkout -b feature/amazing-feature
) - ๋ณ๊ฒฝ์ฌํญ ์ปค๋ฐ (
git commit -m 'Add amazing feature'
) - ๋ธ๋์น์ ํธ์ (
git push origin feature/amazing-feature
) - Pull Request ์คํ
๊ฐ๋ฐ ํ๊ฒฝ ์ค์
git clone https://github.com/jhbrunoK/Athena.Cache.git
cd Athena.Cache
dotnet restore
dotnet build
dotnet test
๐ ๋ผ์ด์ผ์ค
์ด ํ๋ก์ ํธ๋ MIT ๋ผ์ด์ผ์ค ํ์ ๋ฐฐํฌ๋ฉ๋๋ค. ์์ธํ ๋ด์ฉ์ LICENSE ํ์ผ์ ์ฐธ์กฐํ์ธ์.
๐ ๊ฐ์ฌ์ ๋ง
- ์ ๋ต๊ณผ ์งํ์ ์ฌ์ ์ํ ๋์์ ์๊ฐ์ ๋ฐ์์ต๋๋ค
- ASP.NET Core ์ปค๋ฎค๋ํฐ๋ฅผ ์ํด ์ ์๋์์ต๋๋ค
- ๋ชจ๋ ๊ธฐ์ฌ์๋ถ๋ค๊ป ๊ฐ์ฌ๋๋ฆฝ๋๋ค
๐ ์ง์ ๋ฐ ๋ฌธ์
- ๐ ๋ฒ๊ทธ ๋ฆฌํฌํธ: GitHub Issues
- ๐ก ๊ธฐ๋ฅ ์์ฒญ: GitHub Discussions
- ๐ง ์ด๋ฉ์ผ: bobhappy2000@gmail.com
โค๏ธ ๊ณ ์ฑ๋ฅ ASP.NET Core ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํด ์ ์๋์์ต๋๋ค
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Athena.Cache.Core (>= 1.0.0)
- Microsoft.Extensions.DependencyInjection (>= 9.0.7)
- StackExchange.Redis (>= 2.8.58)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.