RRedis Handbook

TEMEL

List & Set & Sorted Set

Redis 8 ve .NET 10 ile caching, veri yapıları, messaging, ölçekleme, dayanıklılık ve production operasyonları.

Kod örneği görünümü Bu sayfadaki eşleşen örnekleri seçilen istemciye göre gösterir.

List — Queue/Stack

# Queue (FIFO)
LPUSH queue:emails "msg1" "msg2" "msg3"
RPOP queue:emails              # "msg1" (FIFO)
BRPOP queue:emails 30          # blocking pop (30s timeout)
LLEN queue:emails
LRANGE queue:emails 0 -1       # tümünü gör
public class QueueService
{
    private readonly IDatabase _redis;

    public QueueService(IConnectionMultiplexer mux)
        => _redis = mux.GetDatabase();

    public async Task EnqueueAsync(string queue, string message)
    {
        await _redis.ListLeftPushAsync($"queue:{queue}", message);
    }

    public async Task<string?> DequeueAsync(string queue)
    {
        var value = await _redis.ListRightPopAsync($"queue:{queue}");
        return value.HasValue ? value.ToString() : null;
    }

    // Reliable queue: pop + push to processing list
    public async Task<string?> ReliableDequeueAsync(string queue)
    {
        var value = await _redis.ListRightPopLeftPushAsync(
            $"queue:{queue}", $"processing:{queue}");
        return value.HasValue ? value.ToString() : null;
    }

    public async Task AcknowledgeAsync(string queue, string message)
    {
        await _redis.ListRemoveAsync($"processing:{queue}", message);
    }

    public async Task<long> GetLengthAsync(string queue)
    {
        return await _redis.ListLengthAsync($"queue:{queue}");
    }
}

Set — Unique Collection

SADD online:users "user:1" "user:2" "user:3"
SISMEMBER online:users "user:1"     # 1
SCARD online:users                  # 3
SINTER user:1:follows user:2:follows  # ortak takip
SDIFF user:1:follows user:2:follows   # fark
public class OnlineUsersService
{
    private readonly IDatabase _redis;

    public OnlineUsersService(IConnectionMultiplexer mux)
        => _redis = mux.GetDatabase();

    public async Task SetOnlineAsync(string userId)
    {
        await _redis.SetAddAsync("online:users", userId);
        await _redis.KeyExpireAsync("online:users", TimeSpan.FromMinutes(5));
    }

    public async Task<bool> IsOnlineAsync(string userId)
    {
        return await _redis.SetContainsAsync("online:users", userId);
    }

    public async Task<long> OnlineCountAsync()
    {
        return await _redis.SetLengthAsync("online:users");
    }

    // Ortak arkadaşlar
    public async Task<string[]> MutualFriendsAsync(string user1, string user2)
    {
        var result = await _redis.SetCombineAsync(
            SetOperation.Intersect, $"friends:{user1}", $"friends:{user2}");
        return result.Select(r => r.ToString()).ToArray();
    }
}

Sorted Set — Leaderboard/Ranking

ZADD leaderboard 1500 "player:1" 2200 "player:2" 1800 "player:3"
ZREVRANGE leaderboard 0 2 WITHSCORES   # top 3
ZINCRBY leaderboard 100 "player:1"     # skor artır
ZRANK leaderboard "player:1"           # sıralama (0-based)
ZRANGEBYSCORE leaderboard 1000 2000    # skor aralığı
ZCARD leaderboard                      # toplam oyuncu
public class LeaderboardService
{
    private readonly IDatabase _redis;
    private const string Key = "leaderboard";

    public LeaderboardService(IConnectionMultiplexer mux)
        => _redis = mux.GetDatabase();

    public async Task AddScoreAsync(string playerId, double score)
    {
        await _redis.SortedSetAddAsync(Key, playerId, score);
    }

    public async Task<double> IncrementScoreAsync(string playerId, double amount)
    {
        return await _redis.SortedSetIncrementAsync(Key, playerId, amount);
    }

    public async Task<List<LeaderboardEntry>> GetTopAsync(int count = 10)
    {
        var entries = await _redis.SortedSetRangeByRankWithScoresAsync(
            Key, 0, count - 1, Order.Descending);

        return entries.Select((e, i) => new LeaderboardEntry
        {
            Rank = i + 1,
            PlayerId = e.Element.ToString(),
            Score = e.Score
        }).ToList();
    }

    public async Task<long?> GetRankAsync(string playerId)
    {
        // ZRevRank: 0-based descending
        return await _redis.SortedSetRankAsync(Key, playerId, Order.Descending);
    }

    public async Task<double?> GetScoreAsync(string playerId)
    {
        return await _redis.SortedSetScoreAsync(Key, playerId);
    }
}