Redis是一个开源的高性能键值存储系统,常被用作数据库、缓存和消息代理。本教程将全面介绍如何在C#中使用Redis,涵盖基础操作、高级功能以及最佳实践。
1. Redis基础与环境准备
1.1 Redis安装与运行
- Windows:使用Microsoft提供的Redis Windows版本或通过WSL安装
- Linux:通过包管理器安装(如
sudo apt-get install redis-server
) - Docker:
docker 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 安全建议
- 始终使用密码保护Redis实例
- 禁用危险命令(如FLUSHALL)
- 限制网络访问(防火墙规则)
- 定期轮换密码
- 考虑使用SSL/TLS加密传输
9. 总结
本教程全面介绍了在C#中使用Redis的各个方面,从基础操作到高级特性,再到实际应用场景。Redis作为一个高性能的内存数据结构存储,可以为你的应用带来显著的性能提升和功能扩展。
关键要点:
- 使用StackExchange.Redis作为C#客户端
- 合理管理连接(推荐单例模式)
- 根据场景选择合适的数据结构
- 利用管道和批量操作提高性能
- 实现缓存、分布式锁等常见模式
- 重视安全配置和监控
随着Redis的不断发展,建议定期查看官方文档以了解新功能和最佳实践的更新。对于企业级应用,可以考虑使用Redis集群或云服务提供的Redis服务(如Azure Cache for Redis、AWS ElastiCache等)以获得更好的可用性和扩展性。