我需要的是管理共享资源(更像是日志,同时具有读写操作)
在应用程序中的不同进程(因此也是多个线程)之间。数据也应该是
持续系统重启,因此它应该是一个物理文件/数据库。
共享资源是一些具有键值信息的数据。 (因此可以使用此共享资源执行的可能操作是添加新的键值信息,
更新/删除现有的键值信息。)
因此我正在考虑使用xml文件来物理存储信息,样本内容将
看起来像,
<Root>
<Key1>Value</Key1>
<Key2>Value</Key2>
<Key3>Value</Key3>
</Root>
执行读取和操作的界面将如下所示:
public interface IDataHandler
{
IDictionary<string,string> GetData();
void SetData(string key,string value);
}
我可以假设数据不会超过500 MB因此xml决定以及数据是否增长 我会把它移到DB。 此外,与读取操作相比,写入数据会更多。
与上述场景相关的查询/设计考虑很少,
可以在xml文件中处理500 MB的数据吗?
假设文件为xml,现在如何处理性能问题?
在读取操作期间实现性能,是否可以在内存中缓存500 MB数据,或者我们
还有其他选择吗?
现在,如果我使用上述缓存机制,在写操作期间应该发生什么:
我应该通过转换
整个字典到xml?要么 - 有没有办法只更新其数据被修改/添加的xml文件的一部分?或任何
处理这种情况的其他方法? - 我应该通过将写入操作放入队列和后台来再次提高性能
线程读取队列并启用实际的写操作,以便实际写入数据的人
因为写入文件而不会受到影响? - 要处理多线程场景,计划使用具有全局名称的Mutex,还有其他
更好的方法吗?
我确信,我操作的假设很少,并试图从那里建造,如果我错了
某些假设然后会改变大部分设计概念。因此,全新的解决方案也是欢迎(保持表现为主要标准)。 提前谢谢。
答案 0 :(得分:3)
正如您所说的“写操作不仅仅是读取”我假设数据增长得更快,因此我的建议是开始设计数据库。它不需要像MSSQL或MYSQL这样的完整功能数据库,您可以从SQL-Lite或MSSQL-Compact开始。这使您的应用程序成为大数据处理能力的未来证明。
存储大量读取数据,例如RAM中变化不大的配置是有效的方法。我的建议是使用一些缓存管理器,如MemoryCache或Enterprise Library Caching Block,这样可以节省大量时间实现线程安全数据访问和恶梦:),而不是自己编写。
public interface IDataHandler
{
IDictionary<string,string> GetData();
void SetData(string key,string value);
}
public class MyDataHandler : IDataHandler
{
public IDictionary<string,string> GetData()
{
return CacheManager.GetData("ConfigcacheKey") as IDictionary<string,string>;
}
public void SetData(string key,string value)
{
var data = GetData() ?? new Dictionary<string,string();
if(data.ContainsKey(key)) data[key] = value;
else data.Add(key,value);
CacheManager.Add("ConfigcacheKey", data);
// HERE write an async method to save the key,value in database or XML file
}
}
如果你使用XML,那么每次都不需要将字典转换为xml。在XmlDocument / XDocument对象中加载XML文档,并使用XPath查找要更新值的元素或添加新元素并保存文档。
从性能点来看,除非你做一些疯狂的逻辑或处理GB中的巨大(我的意思是非常巨大的)数据,我建议你使用已经可用的经过测试的组件(如数据库,CacheManagers)快速完成你的应用程序,它们将你从线程安全操作中抽象出来
答案 1 :(得分:2)
我看到了解决这个问题的两种方法:
要记住的关键点:
答案 2 :(得分:1)
将您的解决方案基于Stackoverflow答案的设计原则:
How to effectively log asynchronously?
正如您在其中一个考虑因素中提到的,上述解决方案涉及线程和排队。
此外,使用BinaryFormatter
可以获得更好的性能,而不是将数据序列化为XML。答案 3 :(得分:1)
关于表现 - 当大小超过100MB时,XML非常慢。我的要求是在磁盘上读/写数据(~1GB),读n操作可能是并行的。例如数据来自1个线程,它正在文件中写入,而另一个/同一个应用程序可以在图表/其他UI上请求数据用于显示目的。我们转向二进制阅读器编写器,我们进行了性能分析,二进制阅读器/写入器与XML相比非常快(对于更大的文件大小)。
现在我们已经转移到HDF5,我们正在播放20GB数据文件,同时进行读写操作。
具有全球名称shud工作的互斥体,我们使用相同的。
答案 4 :(得分:1)
我从单一,轻量级的调控器流程开始,完全负责访问数据文件。其他进程与调控器通信(即通过此方案中的.NET Remoting通过IDataHandler
接口),并且永远不会直接操作文件。这样,您不仅可以抽象出与多路访问相关的问题,还可以获得一些功能:
答案 5 :(得分:1)
数据库,毫无疑问。
如果您不想创建另一台服务器,只需在网络驱动器上的共享文件上使用SQLCE(只要您不需要超过256个并发连接)。
没有大型数据库可供支持,但您可以获得强类型数据以及使用数据库所产生的所有其他好处,例如索引,哈希,反转等等。
如果没有别的,每次你想要找到(或更新,删除,甚至添加,如果你想要唯一的密钥)记录时,它都不必对整个文件进行线性扫描。
您正在编写一个哈希表,将键映射到值。不要使用等效于元组数组的数据存储。使用真正的永久商店。
你对XML文件的唯一优势(如果甚至可以使用得好)是人类的可读性和可编辑性(如果这甚至是奖励......难以使用的SSMS)?
缺点:
1)所有查询的线性扫描 2)在应用程序级别没有安全性或密码访问权限......任何人都可以编辑此XML文件。 SQLCE可以加密并密码锁定。 3)无类型数据。 4)详细格式(严肃地说,JSON会更好,更快,更小,类型和人类可读)。 5)SQL&gt;的XPath / XSLT 6)如果您的数据需求增长,则您具有内置约束和密钥。
我无法想象一个性能更高的解决方案,其开销比SQLCE实例更少。
答案 6 :(得分:1)
首先要做的事情。您必须忘记将XML用于高性能系统。我建议去JSON。它的重量轻,许多高性能要求的应用程序,如Foursquare使用JSON来存储他们的数据(虽然不是他们的所有数据)。
最好尝试一个基于NOSQL文档的数据库,而不是去关系数据库,因为它们专门用于高性能系统,而且很少有人可以保存原始JSON格式数据。我建议去MongoDB(有C#驱动程序并支持LINQ)。还有许多其他基于文档的NOSQL DB。但是我还没有用过它们。
对于并发性,您可以使用其中一个并发集合,尤其是ConcurrentDictionary<TKey, TValue>
,这样您就不必担心同步问题了。