巧用Dictionary實(shí)現(xiàn)日志數(shù)據(jù)批量插入
背景
最近再做一個(gè)需求,就是對(duì)站點(diǎn)的一些事件進(jìn)行埋點(diǎn),說(shuō)白了就是記錄用戶(hù)的訪問(wèn)行為。那么這些數(shù)據(jù)怎么保存呢,人家點(diǎn)一下保存一下?顯然不合適,肯定是需要批量保存,提高效率。
問(wèn)題窺探
首先,我想到的是Dictionary,對(duì)于C#中的Dictionary類(lèi)相信大家都不陌生,這是一個(gè)Collection(集合)類(lèi)型,可以通過(guò)Key/Value(鍵值對(duì)的形式來(lái)存放數(shù)據(jù);該類(lèi)最大的優(yōu)點(diǎn)就是它查找元素的時(shí)間復(fù)雜度接近O(1),實(shí)際項(xiàng)目中常被用來(lái)做一些數(shù)據(jù)的本地緩存,提升整體效率。Dictionary是非線程安全的類(lèi)型,可以實(shí)現(xiàn)先添加到內(nèi)存當(dāng)中,在批量保存進(jìn)去數(shù)據(jù)庫(kù)。
主要代碼實(shí)現(xiàn)
1、定義一個(gè)Dictionary。
private readonly Dictionary<string, Tuple<ObjectInfo, object>> _storage = new Dictionary<string, Tuple<ObjectInfo, object>>(StringComparer.OrdinalIgnoreCase);
2、添加元素,操作的時(shí)候需要對(duì)其進(jìn)行線程安全處理,最簡(jiǎn)單的方式就是加鎖(lock)。
public bool SaveObject<T>(string path, T value) where T : class { if (String.IsNullOrWhiteSpace(path)) throw new ArgumentNullException("path"); lock (_lock) { _storage[path] = Tuple.Create(new ObjectInfo { Created = DateTime.Now, Modified = DateTime.Now, Path = path }, (object)value); if (_storage.Count > MaxObjects) _storage.Remove(_storage.OrderByDescending(kvp => kvp.Value.Item1.Created).First().Key); } return true; }
3、定義一個(gè)隊(duì)列,定時(shí)消費(fèi)日志。
public DefaultEventQueue(ExceptionlessConfiguration config, IExceptionlessLog log, ISubmissionClient client, IObjectStorage objectStorage, IJsonSerializer serializer, TimeSpan? processQueueInterval, TimeSpan? queueStartDelay) { _log = log; _config = config; _client = client; _storage = objectStorage; _serializer = serializer; if (processQueueInterval.HasValue) _processQueueInterval = processQueueInterval.Value; _queueTimer = new Timer(OnProcessQueue, null, queueStartDelay ?? TimeSpan.FromSeconds(2), _processQueueInterval); }
這里刪除的時(shí)候也需要lock 操作。
public bool DeleteObject(string path) { if (String.IsNullOrWhiteSpace(path)) throw new ArgumentNullException("path"); lock (_lock) { if (!_storage.ContainsKey(path)) return false; _storage.Remove(path); } return true; }
public IEnumerable<ObjectInfo> GetObjectList(string searchPattern = null, int? limit = null, DateTime? maxCreatedDate = null) { if (searchPattern == null) searchPattern = "*"; if (!maxCreatedDate.HasValue) maxCreatedDate = DateTime.MaxValue; var regex = new Regex("^" + Regex.Escape(searchPattern).Replace("\\*", ".*?") + "$"); lock (_lock) return _storage.Keys.Where(k => regex.IsMatch(k)).Select(k => _storage[k].Item1).Where(f => f.Created <= maxCreatedDate).Take(limit ?? Int32.MaxValue).ToList(); }
總結(jié)
1、利用Dictionary。多線程添加數(shù)據(jù)到內(nèi)存;
2、達(dá)到一定量的時(shí)候,批量保存數(shù)據(jù)。
3、使用lock ,保證Dictionary操作安全。
到此這篇關(guān)于巧用Dictionary實(shí)現(xiàn)日志數(shù)據(jù)批量插入的文章就介紹到這了,更多相關(guān)Dictionary實(shí)現(xiàn)日志數(shù)據(jù)批量插入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談Visual Studio 2019 Vue項(xiàng)目的目錄結(jié)構(gòu)
這篇文章主要介紹了Visual Studio 2019 Vue項(xiàng)目 目錄結(jié)構(gòu),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03c#中directory 和directoryinfo的使用小結(jié)
當(dāng)使用C#處理目錄時(shí),可以使用?System.IO?命名空間中的?Directory?和?DirectoryInfo?類(lèi)來(lái)執(zhí)行各種目錄操作,本文主要介紹了c#中directory 和directoryinfo的使用小結(jié),感興趣的可以了解一下2024-02-02在WPF中合并兩個(gè)ObservableCollection集合
這篇文章介紹了在WPF中合并兩個(gè)ObservableCollection集合的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06C#3.0使用EventLog類(lèi)寫(xiě)Windows事件日志的方法
這篇文章主要介紹了C#3.0使用EventLog類(lèi)寫(xiě)Windows事件日志的方法,以簡(jiǎn)單實(shí)例形式分析了C#寫(xiě)windows事件日志的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08C#中私有構(gòu)造函數(shù)的特點(diǎn)和用途實(shí)例解析
這篇文章主要介紹了C#中私有構(gòu)造函數(shù)的特點(diǎn)和用途,需要的朋友可以參考下2014-08-08