diff --git a/TYLDDB.Utils.FastCache.Test/Program.cs b/TYLDDB.Utils.FastCache.Test/Program.cs index da4dde3..1b06543 100644 --- a/TYLDDB.Utils.FastCache.Test/Program.cs +++ b/TYLDDB.Utils.FastCache.Test/Program.cs @@ -1,11 +1,15 @@ -using TYLDDB.Utils.FastCache; +using TYLDDB.Utils.FastCache; using TYLDDB.Utils.FastCache.Test; +Console.WriteLine("基于信号量的缓存读写运行"); SemaphoreSlimDefault(); +Console.WriteLine(); +Console.WriteLine("基于信号量的缓存读写运行"); +ConcurrentDictionary(); Console.ReadLine(); -// 普通线程锁的数据库读写运行 +// 基于信号量的缓存读写运行 static async void SemaphoreSlimDefault() { var setTime = new HighPrecisionTimer(); @@ -17,7 +21,7 @@ static async void SemaphoreSlimDefault() var getAllCacheTime = new HighPrecisionTimer(); var getAllCacheAsyncTime = new HighPrecisionTimer(); - var cache = new Cache(); + ICache cache = new SemaphoreThreadLock(); setTime.Start(); cache.Set("TESTKEY1", "TESTVALUE1"); @@ -68,6 +72,75 @@ static async void SemaphoreSlimDefault() getAllCacheAsyncTime.Stop(); + Console.WriteLine("时间消耗:"); + Console.WriteLine($"设置键值(同步):{setTime.ElapsedMilliseconds()}ms 设置键值(异步):{setAsyncTime.ElapsedMilliseconds()}ms"); + Console.WriteLine($"根据键获取值(同步):{getByKeyTime.ElapsedMilliseconds()}ms 根据键获取值(异步):{getByKeyAsyncTime.ElapsedMilliseconds()}ms"); + Console.WriteLine($"根据值获取键(同步):{getKeysByValueTime.ElapsedMilliseconds()}ms 根据值获取键(异步):{getKeysByValueAsyncTime.ElapsedMilliseconds()}ms"); + Console.WriteLine($"获取所有缓存项(同步):{getAllCacheTime.ElapsedMilliseconds()}ms 获取所有缓存项(异步):{getAllCacheAsyncTime.ElapsedMilliseconds()}ms"); +} + +// 基于并发词典的缓存读写运行 +static async void ConcurrentDictionary() +{ + var setTime = new HighPrecisionTimer(); + var setAsyncTime = new HighPrecisionTimer(); + var getByKeyTime = new HighPrecisionTimer(); + var getByKeyAsyncTime = new HighPrecisionTimer(); + var getKeysByValueTime = new HighPrecisionTimer(); + var getKeysByValueAsyncTime = new HighPrecisionTimer(); + var getAllCacheTime = new HighPrecisionTimer(); + var getAllCacheAsyncTime = new HighPrecisionTimer(); + + ICache cache = new ConcurrentDictionary(); + + setTime.Start(); + cache.Set("TESTKEY1", "TESTVALUE1"); + setTime.Stop(); + + setAsyncTime.Start(); + await cache.SetAsync("TESTKEY2", "TESTVALUE2"); + setAsyncTime.Stop(); + + getByKeyTime.Start(); + Console.WriteLine("TESTKEY1对应的值:" + cache.GetByKey("TESTKEY1")); + getByKeyTime.Stop(); + + getByKeyAsyncTime.Start(); + Console.WriteLine("TESTKEY2对应的值:" + await cache.GetByKeyAsync("TESTKEY2")); + getByKeyAsyncTime.Stop(); + + cache.Set("TESTKEY3", "TESTVALUE2"); + + Console.WriteLine("TESTVALUE2对应的所有键:"); + getKeysByValueTime.Start(); + Console.WriteLine(string.Join(", ", cache.GetKeysByValue("TESTVALUE2"))); + getKeysByValueTime.Stop(); + + Console.WriteLine("TESTVALUE2对应的所有键:"); + getKeysByValueAsyncTime.Start(); + Console.WriteLine(string.Join(", ", await cache.GetKeysByValueAsync("TESTVALUE2"))); + getKeysByValueAsyncTime.Stop(); + + // 获取并输出所有缓存项(同步方法) + getAllCacheTime.Start(); + var allCacheSync = cache.GetAllCache(); + Console.WriteLine("同步获取所有缓存项:"); + foreach (var kvp in allCacheSync) + { + Console.WriteLine($"{kvp.Key}: {kvp.Value}"); + } + getAllCacheTime.Stop(); + + // 获取并输出所有缓存项(异步方法) + getAllCacheAsyncTime.Start(); + var allCacheAsync = await cache.GetAllCacheAsync(); + Console.WriteLine("异步获取所有缓存项:"); + foreach (var kvp in allCacheAsync) + { + Console.WriteLine($"{kvp.Key}: {kvp.Value}"); + } + getAllCacheAsyncTime.Stop(); + Console.WriteLine("时间消耗:"); Console.WriteLine($"设置键值(同步):{setTime.ElapsedMilliseconds()}ms 设置键值(异步):{setAsyncTime.ElapsedMilliseconds()}ms"); Console.WriteLine($"根据键获取值(同步):{getByKeyTime.ElapsedMilliseconds()}ms 根据键获取值(异步):{getByKeyAsyncTime.ElapsedMilliseconds()}ms"); diff --git a/TYLDDB/TYLDDB.cs b/TYLDDB/TYLDDB.cs index 0fe14ba..359ce37 100644 --- a/TYLDDB/TYLDDB.cs +++ b/TYLDDB/TYLDDB.cs @@ -78,25 +78,23 @@ public void ReadingFile() /// name of the database
数据库名称 public void LoadDatabase(string db) { - if (_isRead == true) + switch (_isRead) { - _databaseContent = database.GetDatabaseContent(_fileContent, db); - } - else - { - ReadingFile(); - _databaseContent = database.GetDatabaseContent(_fileContent, db); - } + case true: + _databaseContent = database.GetDatabaseContent(_fileContent, db); + break; + default: + ReadingFile(); + _databaseContent = database.GetDatabaseContent(_fileContent, db); + break; } + } /// /// Gets the contents of the database being loaded
/// 获取正在加载的数据库内容 ///
- public string GetLoadingDatabaseContent() - { - return _databaseContent; - } + public string GetLoadingDatabaseContent() => _databaseContent; /// /// Read the names of all databases
diff --git a/TYLDDB/TYLDDB.csproj b/TYLDDB/TYLDDB.csproj index 4a1776d..7a9222e 100644 --- a/TYLDDB/TYLDDB.csproj +++ b/TYLDDB/TYLDDB.csproj @@ -1,11 +1,11 @@ - + netstandard2.0;netstandard2.1;net6.0;net8.0;net9.0 True TTYPDB.NET - 1.0.0-alpha.1 - QingYi-Studio + 1.0.0-alpha.2 + TYLDDB-Project LICENSE True icon.png @@ -17,6 +17,8 @@ True True DataBase + QingYi-Studio + README.md @@ -37,6 +39,10 @@ True \ + + True + \ + diff --git a/TYLDDB/Utils/FastCache/ConcurrentDictionary.cs b/TYLDDB/Utils/FastCache/ConcurrentDictionary.cs new file mode 100644 index 0000000..55a4d5f --- /dev/null +++ b/TYLDDB/Utils/FastCache/ConcurrentDictionary.cs @@ -0,0 +1,159 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace TYLDDB.Utils.FastCache +{ + /// + /// Use thread locks based on concurrent dictionaries to achieve high concurrency stability.
+ /// 使用基于信号量的线程锁来实现高并发的稳定性。 + ///
+ public class ConcurrentDictionary : ICache + { + /// + /// Thread-safe dictionary to store cache data.
+ /// 线程安全的字典,用于存储缓存数据。 + ///
+ private readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); + + /// + /// Synchronization method: Obtain the corresponding value by key.
+ /// 同步方法:根据键获取对应的值。 + ///
+ /// Key
键 + /// Value
+ public string GetByKey(string key) + { + _cache.TryGetValue(key, out var value); + return value; + } + + /// + /// Asynchronous method to get the corresponding value by key.
+ /// 异步方法:根据键获取对应的值。 + ///
+ /// Key
键 + /// Value
+ public async Task GetByKeyAsync(string key) + { + return await Task.FromResult(GetByKey(key)); + } + + /// + /// Get a list of keys that correspond to a specific value.
+ /// 获取与指定值对应的所有键的列表。 + ///
+ /// Value to match
要匹配的值 + /// List of keys
键的列表
+ public List GetKeysByValue(string value) + { + var keys = new List(); + foreach (var kvp in _cache) + { + if (kvp.Value == value) + { + keys.Add(kvp.Key); + } + } + return keys; + } + + /// + /// Asynchronous method to get a list of keys that correspond to a specific value.
+ /// 异步方法:获取与指定值对应的所有键的列表。 + ///
+ /// Value to match
要匹配的值 + /// List of keys
键的列表
+ public async Task> GetKeysByValueAsync(string value) + { + return await Task.FromResult(GetKeysByValue(value)); + } + + /// + /// Set a cache entry for a specified key.
+ /// 为指定键设置缓存项。 + ///
+ /// Key
键 + /// Value
值 + /// Whether the operation is successful.
操作是否成功。
+ public bool Set(string key, string value) + { + // Using AddOrUpdate to ensure atomic insert or update operation + _cache.AddOrUpdate(key, value, (existingKey, existingValue) => value); + return true; + } + + /// + /// Asynchronous method to set a cache entry for a specified key.
+ /// 异步方法:为指定键设置缓存项。 + ///
+ /// Key
键 + /// Value
值 + /// Whether the operation is successful.
操作是否成功。
+ public async Task SetAsync(string key, string value) + { + return await Task.FromResult(Set(key, value)); + } + + /// + /// Remove a cache entry by its key.
+ /// 根据键移除缓存项。 + ///
+ /// Key
键 + /// Whether the removal is successful.
移除操作是否成功。
+ public bool RemoveByKey(string key) + { + return _cache.TryRemove(key, out _); + } + + /// + /// Asynchronous method to remove a cache entry by its key.
+ /// 异步方法:根据键移除缓存项。 + ///
+ /// Key
键 + /// Whether the removal is successful.
移除操作是否成功。
+ public async Task RemoveByKeyAsync(string key) + { + return await Task.FromResult(RemoveByKey(key)); + } + + /// + /// Clear all cache entries.
+ /// 清空所有缓存项。 + ///
+ public void Clear() + { + _cache.Clear(); + } + + /// + /// Asynchronous method to clear all cache entries.
+ /// 异步方法:清空所有缓存项。 + ///
+ /// Asynchronous task for clearing.
清空操作的异步任务。
+ public async Task ClearAsync() + { + await Task.Run(() => Clear()); + } + + /// + /// Get all cache entries as a dictionary.
+ /// 获取所有缓存项,返回字典。 + ///
+ /// All cache entries as a dictionary.
所有缓存项的字典。
+ public Dictionary GetAllCache() + { + return new Dictionary(_cache); + } + + /// + /// Asynchronous method to get all cache entries as a dictionary.
+ /// 异步方法:获取所有缓存项,返回字典。 + ///
+ /// All cache entries as a dictionary.
所有缓存项的字典。
+ public async Task> GetAllCacheAsync() + { + return await Task.FromResult(GetAllCache()); + } + } +} diff --git a/TYLDDB/Utils/FastCache/ICache.cs b/TYLDDB/Utils/FastCache/ICache.cs new file mode 100644 index 0000000..76561be --- /dev/null +++ b/TYLDDB/Utils/FastCache/ICache.cs @@ -0,0 +1,99 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace TYLDDB.Utils.FastCache +{ + /// + /// Use cached key-value pairs for fast reads and writes.
+ /// 使用缓存的键值对来快速读写。 + ///
+ public interface ICache + { + /// + /// Synchronization method: Obtain the corresponding value by key.
+ /// 同步方法:根据键获取对应的值。 + ///
+ /// Key
键 + /// Value
+ string GetByKey(string key); + + /// + /// Asynchronous method: Obtains the corresponding value based on the key.
+ /// 异步方法:根据键获取对应的值。 + ///
+ /// Key
键 + /// Value
+ Task GetByKeyAsync(string key); + + /// + /// Synchronization method: Obtains one or more keys according to the value.
+ /// 同步方法:根据值获取对应的一个或多个键。 + ///
+ /// Value
值 + /// Key (List)
键 (List)
+ List GetKeysByValue(string value); + + /// + /// Asynchronous method: Get one or more keys based on the value.
+ /// 异步方法:根据值获取对应的一个或多个键。 + ///
+ /// Value
值 + /// Key (List)
键 (List)
+ Task> GetKeysByValueAsync(string value); + + /// + /// 同步方法:设置一个键值对。 + /// + /// + /// + /// + bool Set(string key, string value); + + /// + /// 异步方法:设置一个键值对。 + /// + /// + /// + /// + Task SetAsync(string key, string value); + + /// + /// 同步方法:移除一个键值对。 + /// + /// + /// + bool RemoveByKey(string key); + + /// + /// 异步方法:移除一个键值对。 + /// + /// + /// + Task RemoveByKeyAsync(string key); + + /// + /// 同步方法:清空缓存。 + /// + void Clear(); + + /// + /// 异步方法:清空缓存。 + /// + /// + Task ClearAsync(); + + /// + /// Gets all key-value pairs.
+ /// 获取所有的键值对。 + ///
+ /// Key-value pair
键值对
+ Dictionary GetAllCache(); + + /// + /// Gets all key-value pairs.
+ /// 获取所有的键值对。 + ///
+ /// Key-value pair
键值对
+ Task> GetAllCacheAsync(); + } +} diff --git a/TYLDDB/Utils/FastCache/SemaphoreThreadLock.cs b/TYLDDB/Utils/FastCache/SemaphoreThreadLock.cs new file mode 100644 index 0000000..ff661cd --- /dev/null +++ b/TYLDDB/Utils/FastCache/SemaphoreThreadLock.cs @@ -0,0 +1,286 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace TYLDDB.Utils.FastCache +{ + /// + /// Use semaphore based thread locks to achieve high concurrency stability.
+ /// 使用基于信号量的线程锁来实现高并发的稳定性。 + ///
+ public class SemaphoreThreadLock : ICache + { + private readonly Dictionary keyValueDict; // 存储键->值映射 + private readonly Dictionary> valueKeyDict; // 存储值->键的映射 + private readonly SemaphoreSlim semaphore; // 控制并发访问 + + /// + /// Use cached key-value pairs for fast reads and writes.
+ /// 使用缓存的键值对来快速读写。 + ///
+ public SemaphoreThreadLock() + { + keyValueDict = new Dictionary(); + valueKeyDict = new Dictionary>(); + semaphore = new SemaphoreSlim(1, 1); // 使用信号量来同步 + } + + /// + /// Synchronization method: Obtain the corresponding value by key.
+ /// 同步方法:根据键获取对应的值。 + ///
+ /// Key
键 + /// Value
+ public string GetByKey(string key) + { + lock (semaphore) + { + keyValueDict.TryGetValue(key, out var value); + return value; + } + } + + /// + /// Asynchronous method: Obtains the corresponding value based on the key.
+ /// 异步方法:根据键获取对应的值。 + ///
+ /// Key
键 + /// Value
+ public async Task GetByKeyAsync(string key) + { + await semaphore.WaitAsync(); + try + { + keyValueDict.TryGetValue(key, out var value); + return value; + } + finally + { + semaphore.Release(); + } + } + + /// + /// Synchronization method: Obtains one or more keys according to the value.
+ /// 同步方法:根据值获取对应的一个或多个键。 + ///
+ /// Value
值 + /// Key (List)
键 (List)
+ public List GetKeysByValue(string value) + { + lock (semaphore) + { + if (valueKeyDict.ContainsKey(value)) + { + return valueKeyDict[value].ToList(); + } + return new List(); + } + } + + /// + /// Asynchronous method: Get one or more keys based on the value.
+ /// 异步方法:根据值获取对应的一个或多个键。 + ///
+ /// Value
值 + /// Key (List)
键 (List)
+ public async Task> GetKeysByValueAsync(string value) + { + await semaphore.WaitAsync(); + try + { + if (valueKeyDict.ContainsKey(value)) + { + return valueKeyDict[value].ToList(); + } + return new List(); + } + finally + { + semaphore.Release(); + } + } + + /// + /// 同步方法:设置一个键值对。 + /// + /// + /// + /// + public bool Set(string key, string value) + { + lock (semaphore) + { + if (keyValueDict.ContainsKey(key)) + { + return false; // 键已存在,不允许重复的键 + } + + keyValueDict[key] = value; + + if (!valueKeyDict.ContainsKey(value)) + { + valueKeyDict[value] = new HashSet(); + } + valueKeyDict[value].Add(key); + return true; + } + } + + /// + /// 异步方法:设置一个键值对。 + /// + /// + /// + /// + public async Task SetAsync(string key, string value) + { + await semaphore.WaitAsync(); + try + { + if (keyValueDict.ContainsKey(key)) + { + return false; // 键已存在,不允许重复的键 + } + + keyValueDict[key] = value; + + if (!valueKeyDict.ContainsKey(value)) + { + valueKeyDict[value] = new HashSet(); + } + valueKeyDict[value].Add(key); + return true; + } + finally + { + semaphore.Release(); + } + } + + /// + /// 同步方法:移除一个键值对。 + /// + /// + /// + public bool RemoveByKey(string key) + { + lock (semaphore) + { + if (!keyValueDict.ContainsKey(key)) + { + return false; + } + var value = keyValueDict[key]; + keyValueDict.Remove(key); + + if (valueKeyDict.ContainsKey(value)) + { + valueKeyDict[value].Remove(key); + if (valueKeyDict[value].Count == 0) + { + valueKeyDict.Remove(value); + } + } + return true; + } + } + + /// + /// 异步方法:移除一个键值对。 + /// + /// + /// + public async Task RemoveByKeyAsync(string key) + { + await semaphore.WaitAsync(); + try + { + if (!keyValueDict.ContainsKey(key)) + { + return false; + } + var value = keyValueDict[key]; + keyValueDict.Remove(key); + + if (valueKeyDict.ContainsKey(value)) + { + valueKeyDict[value].Remove(key); + if (valueKeyDict[value].Count == 0) + { + valueKeyDict.Remove(value); + } + } + return true; + } + finally + { + semaphore.Release(); + } + } + + /// + /// 同步方法:清空缓存。 + /// + public void Clear() + { + lock (semaphore) + { + keyValueDict.Clear(); + valueKeyDict.Clear(); + } + } + + /// + /// 异步方法:清空缓存。 + /// + /// + public async Task ClearAsync() + { + await semaphore.WaitAsync(); + try + { + keyValueDict.Clear(); + valueKeyDict.Clear(); + } + finally + { + semaphore.Release(); + } + } + + /// + /// Gets all key-value pairs.
+ /// 获取所有的键值对。 + ///
+ /// Key-value pair
键值对
+ public Dictionary GetAllCache() + { + lock (semaphore) + { + // 返回完整的键值对字典 + return new Dictionary(keyValueDict); + } + } + + /// + /// Gets all key-value pairs.
+ /// 获取所有的键值对。 + ///
+ /// Key-value pair
键值对
+ public async Task> GetAllCacheAsync() + { + await semaphore.WaitAsync(); + try + { + // 返回完整的键值对字典 + return new Dictionary(keyValueDict); + } + finally + { + semaphore.Release(); + } + } + } +}