在开发过程中,我们经常需要使用缓存来提高应用程序的性能。本文将介绍如何使用C#实现一个简单的内存缓存系统,它模仿了Redis的部分基本功能
功能:
- 基本的键值存储
- 支持过期时间
- 支持泛型类型
- Hash 类型操作
- 线程安全
- 清理过期项
优点:
- 不依赖第三方库
- 实现简单
- 内存操作,速度快
- 支持基本的 Redis 功能
限制:
- 数据存储在内存中,程序重启后数据会丢失
- 不支持分布式
- 功能相对简单
代码实现:
using System.Collections.Concurrent;namespace SimpleRedisApp
{public interface ISimpleRedis{bool Set<T>(string key, T value, TimeSpan? expiry = null);T Get<T>(string key);bool Delete(string key);bool Exists(string key);List<string> GetAllKeys();bool HashSet(string key, string field, object value);T HashGet<T>(string key, string field);void RemoveExpiredItems();}/// <summary>/// 简单的内存缓存实现/// </summary>public class SimpleRedis : ISimpleRedis{// 使用ConcurrentDictionary保证线程安全private static readonly ConcurrentDictionary<string, CacheItem> Cache = new ConcurrentDictionary<string, CacheItem>();// 缓存项类,包含值和过期时间private class CacheItem{public object Value { get; set; }public DateTime? ExpireTime { get; set; }}/// <summary>/// 设置缓存/// </summary>public bool Set<T>(string key, T value, TimeSpan? expiry = null){var item = new CacheItem{Value = value,ExpireTime = expiry.HasValue ? DateTime.Now.Add(expiry.Value) : null};Cache.AddOrUpdate(key, item, (k, old) => item);return true;}/// <summary>/// 获取缓存/// </summary>public T Get<T>(string key){if (Cache.TryGetValue(key, out CacheItem item)){if (item.ExpireTime.HasValue && item.ExpireTime.Value < DateTime.Now){// 已过期,删除并返回默认值Cache.TryRemove(key, out _);return default(T);}return (T)item.Value;}return default(T);}/// <summary>/// 删除缓存/// </summary>public bool Delete(string key){return Cache.TryRemove(key, out _);}/// <summary>/// 判断键是否存在/// </summary>public bool Exists(string key){return Cache.ContainsKey(key) &&(!Cache[key].ExpireTime.HasValue || Cache[key].ExpireTime.Value > DateTime.Now);}/// <summary>/// 清空所有缓存/// </summary>public void Clear(){Cache.Clear();}/// <summary>/// 获取所有键/// </summary>public List<string> GetAllKeys(){return Cache.Keys.ToList();}/// <summary>/// 设置Hash/// </summary>public bool HashSet(string key, string field, object value){var hash = Get<Dictionary<string, object>>(key) ?? new Dictionary<string, object>();hash[field] = value;return Set(key, hash);}/// <summary>/// 获取Hash/// </summary>public T HashGet<T>(string key, string field){var hash = Get<Dictionary<string, object>>(key);if (hash != null && hash.ContainsKey(field)){return (T)hash[field];}return default(T);}/// <summary>/// 删除过期的缓存项/// </summary>public void RemoveExpiredItems(){var now = DateTime.Now;var expiredKeys = Cache.Where(kvp =>kvp.Value.ExpireTime.HasValue &&kvp.Value.ExpireTime.Value < now).Select(kvp => kvp.Key).ToList();foreach (var key in expiredKeys){Cache.TryRemove(key, out _);}}}public class User{public string Name { get; set; }public int Age { get; set; }}internal class Program{static void Main(string[] args){var redis = new SimpleRedis();// 字符串操作redis.Set("name", "张三", TimeSpan.FromMinutes(1));var name = redis.Get<string>("name");Console.WriteLine($"Name: {name}");// 对象操作var user = new User { Name = "李四", Age = 25 };redis.Set("user:1", user);var savedUser = redis.Get<User>("user:1");Console.WriteLine($"User: {savedUser.Name}, {savedUser.Age}");// Hash操作redis.HashSet("user:2", "name", "王五");redis.HashSet("user:2", "age", 30);var userName = redis.HashGet<string>("user:2", "name");var userAge = redis.HashGet<int>("user:2", "age");Console.WriteLine($"Hash User: {userName}, {userAge}");// 删除操作redis.Delete("name");// 检查键是否存在var exists = redis.Exists("user:1");Console.WriteLine($"user:1 exists: {exists}");// 获取所有键var allKeys = redis.GetAllKeys();Console.WriteLine($"All keys: {string.Join(", ", allKeys)}");// 存入缓存,设置过期时间为30分钟redis.Set($"user:3", user, TimeSpan.FromMinutes(30));// 清理过期项redis.RemoveExpiredItems();Console.ReadKey();}}
}
可以写个定时器定期清理过期项