C# Redis使用教程:从入门到高级应用


Redis是一个开源的高性能键值存储系统,常被用作数据库、缓存和消息代理。本教程将全面介绍如何在C#中使用Redis,涵盖基础操作、高级功能以及最佳实践。

1. Redis基础与环境准备

1.1 Redis安装与运行

  • Windows:使用Microsoft提供的Redis Windows版本或通过WSL安装
  • Linux:通过包管理器安装(如sudo apt-get install redis-server
  • Dockerdocker run --name redis -p 6379:6379 -d redis

1.2 C#客户端选择

  • StackExchange.Redis(推荐):高性能、功能全面
  • ServiceStack.Redis:商业产品有免费限制
  • NRedisStack:支持Redis最新数据结构

安装StackExchange.Redis:

Install-Package StackExchange.Redis

2. 基本连接与操作

2.1 建立连接

using StackExchange.Redis;

// 创建连接
var connection = ConnectionMultiplexer.Connect("localhost:6379");
IDatabase db = connection.GetDatabase();

// 异步连接方式
var asyncConnection = await ConnectionMultiplexer.ConnectAsync("localhost:6379");

2.2 基本键值操作

// 设置键值
db.StringSet("mykey", "Hello Redis!");

// 获取值
string value = db.StringGet("mykey");
Console.WriteLine(value); // 输出: Hello Redis!

// 设置带过期时间(秒)
db.StringSet("tempKey", "expiring soon", TimeSpan.FromSeconds(30));

// 删除键
db.KeyDelete("mykey");

// 检查键是否存在
bool exists = db.KeyExists("mykey");

3. 数据结构操作

3.1 列表(List)

// 从左侧推入
db.ListLeftPush("messages", "msg1");
db.ListLeftPush("messages", "msg2");

// 从右侧推入
db.ListRightPush("messages", "msg3");

// 获取列表范围
RedisValue[] messages = db.ListRange("messages");
foreach (var msg in messages)
{
    Console.WriteLine(msg);
}

// 获取列表长度
long length = db.ListLength("messages");

3.2 哈希(Hash)

// 设置哈希字段
db.HashSet("user:1000", new HashEntry[] {
    new HashEntry("name", "John Doe"),
    new HashEntry("email", "john@example.com"),
    new HashEntry("age", "30")
});

// 获取单个字段
string name = db.HashGet("user:1000", "name");

// 获取所有字段
HashEntry[] allFields = db.HashGetAll("user:1000");

// 删除字段
db.HashDelete("user:1000", "age");

3.3 集合(Set)

// 添加元素
db.SetAdd("tags", "redis");
db.SetAdd("tags", "csharp");
db.SetAdd("tags", "database");

// 获取所有元素
RedisValue[] tags = db.SetMembers("tags");

// 检查元素是否存在
bool contains = db.SetContains("tags", "redis");

// 集合运算
db.SetAdd("tags2", "csharp");
db.SetAdd("tags2", "dotnet");

// 交集
RedisValue[] intersect = db.SetCombine(SetOperation.Intersect, "tags", "tags2");

// 并集
RedisValue[] union = db.SetCombine(SetOperation.Union, "tags", "tags2");

4. 高级特性

4.1 发布/订阅模式

// 发布者
ISubscriber sub = connection.GetSubscriber();
sub.Publish("news", "New update available!");

// 订阅者
sub.Subscribe("news", (channel, message) => {
    Console.WriteLine($"收到消息: {message}");
});

4.2 事务支持

var transaction = db.CreateTransaction();

// 添加多个操作
transaction.StringSetAsync("tx-key1", "value1");
transaction.StringSetAsync("tx-key2", "value2");

// 执行事务
bool committed = transaction.Execute();

4.3 批量操作

var batch = db.CreateBatch();

// 添加多个操作
var task1 = batch.StringSetAsync("batch-key1", "value1");
var task2 = batch.StringSetAsync("batch-key2", "value2");
var task3 = batch.StringGetAsync("batch-key1");

// 执行批量操作
batch.Execute();

// 获取结果
Console.WriteLine(task3.Result);

5. 性能优化与最佳实践

5.1 连接管理

// 推荐的单例模式
public static class RedisConnector
{
    private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => 
    {
        return ConnectionMultiplexer.Connect("localhost:6379");
    });

    public static ConnectionMultiplexer Connection => lazyConnection.Value;
}

// 使用
IDatabase db = RedisConnector.Connection.GetDatabase();

5.2 管道(Pipelining)

var tasks = new List<Task>();
for (int i = 0; i < 1000; i++)
{
    tasks.Add(db.StringSetAsync($"key-{i}", $"value-{i}"));
}
await Task.WhenAll(tasks);

5.3 Lua脚本

var script = @"local current = redis.call('GET', KEYS[1])
               if current == ARGV[1] then
                   redis.call('SET', KEYS[1], ARGV[2])
                   return 1
               else
                   return 0
               end";

var prepared = LuaScript.Prepare(script);
var result = db.ScriptEvaluate(prepared, new { keys = new RedisKey[] { "mykey" }, 
    values = new RedisValue[] { "oldValue", "newValue" });

6. 实际应用场景

6.1 缓存实现

public class RedisCacheService
{
    private readonly IDatabase _db;

    public RedisCacheService(ConnectionMultiplexer redis)
    {
        _db = redis.GetDatabase();
    }

    public async Task<T> GetOrSetAsync<T>(string key, Func<Task<T>> getData, TimeSpan? expiry = null)
    {
        var value = await _db.StringGetAsync(key);
        if (!value.IsNull)
        {
            return JsonSerializer.Deserialize<T>(value);
        }

        var data = await getData();
        await _db.StringSetAsync(key, JsonSerializer.Serialize(data), expiry);
        return data;
    }
}

6.2 分布式锁

public class RedisLock : IDisposable
{
    private readonly IDatabase _db;
    private readonly string _lockKey;
    private readonly string _lockValue;

    public RedisLock(IDatabase db, string lockKey, TimeSpan expiry)
    {
        _db = db;
        _lockKey = lockKey;
        _lockValue = Guid.NewGuid().ToString();

        while (!_db.LockTake(_lockKey, _lockValue, expiry))
        {
            Thread.Sleep(100);
        }
    }

    public void Dispose()
    {
        _db.LockRelease(_lockKey, _lockValue);
    }
}

// 使用
using (new RedisLock(db, "resource-lock", TimeSpan.FromSeconds(30)))
{
    // 受保护的代码块
}

7. 监控与维护

7.1 健康检查

public class RedisHealthCheck : IHealthCheck
{
    private readonly ConnectionMultiplexer _redis;

    public RedisHealthCheck(ConnectionMultiplexer redis)
    {
        _redis = redis;
    }

    public async Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, 
        CancellationToken cancellationToken = default)
    {
        try
        {
            var db = _redis.GetDatabase();
            await db.PingAsync();
            return HealthCheckResult.Healthy();
        }
        catch (Exception ex)
        {
            return HealthCheckResult.Unhealthy(ex.Message);
        }
    }
}

7.2 性能监控

// 获取服务器信息
IServer server = connection.GetServer("localhost:6379");
var info = server.Info();

// 获取客户端列表
var clients = server.ClientList();

// 监控关键指标
Console.WriteLine($"Used memory: {info["memory"]["used_memory_human"]}");
Console.WriteLine($"Connected clients: {info["clients"]["connected_clients"]}");

8. 安全配置

8.1 认证配置

var config = new ConfigurationOptions
{
    EndPoints = { "localhost:6379" },
    Password = "your-strong-password",
    Ssl = true
};

var secureConnection = ConnectionMultiplexer.Connect(config);

8.2 安全建议

  1. 始终使用密码保护Redis实例
  2. 禁用危险命令(如FLUSHALL)
  3. 限制网络访问(防火墙规则)
  4. 定期轮换密码
  5. 考虑使用SSL/TLS加密传输

9. 总结

本教程全面介绍了在C#中使用Redis的各个方面,从基础操作到高级特性,再到实际应用场景。Redis作为一个高性能的内存数据结构存储,可以为你的应用带来显著的性能提升和功能扩展。

关键要点:

  • 使用StackExchange.Redis作为C#客户端
  • 合理管理连接(推荐单例模式)
  • 根据场景选择合适的数据结构
  • 利用管道和批量操作提高性能
  • 实现缓存、分布式锁等常见模式
  • 重视安全配置和监控

随着Redis的不断发展,建议定期查看官方文档以了解新功能和最佳实践的更新。对于企业级应用,可以考虑使用Redis集群或云服务提供的Redis服务(如Azure Cache for Redis、AWS ElastiCache等)以获得更好的可用性和扩展性。


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注