共享你们的二级缓存实现类 返回

共享你们的二级缓存实现类,不允许水贴
热忱回答(21)
-
Mr、谢 VIP0
2020/11/15.net framework 版本使用 ,系统自带的缓存 Nuget 安装 System.Runtime.Caching
public class HttpRuntimeCache : ICacheService { public void Add<V>(string key, V value) { ObjectCache cache = MemoryCache.Default; cache[key] = value; } public void Add<V>(string key, V value, int cacheDurationInSeconds) { MemoryCache.Default.Add(key, value, new CacheItemPolicy() { AbsoluteExpiration = DateTime.Now.AddSeconds(cacheDurationInSeconds) }); } public bool ContainsKey<V>(string key) { return MemoryCache.Default.Contains(key); } public V Get<V>(string key) { return (V)MemoryCache.Default.Get(key); } public IEnumerable<string> GetAllKey<V>() { var keys = new List<string>(); foreach (var cacheItem in MemoryCache.Default) { keys.Add(cacheItem.Key); } return keys; } public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue) { var cacheManager = MemoryCache.Default; if (cacheManager.Contains(cacheKey)) { return (V)cacheManager[cacheKey]; } else { var result = create(); cacheManager.Add(cacheKey, result, new CacheItemPolicy() { AbsoluteExpiration = DateTime.Now.AddSeconds(cacheDurationInSeconds) }); return result; } } public void Remove<V>(string key) { MemoryCache.Default.Remove(key); } }
0 回复 -
fate stay night VIP0
2020/11/28ServiceStack.Redis 的二缓存实现,目前这个dll是收费的,免费版本有很多限制 (CSDN可以拿到破解版本的)
using ServiceStack.Redis; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SqlSugar; namespace SqlSugar.Extensions { public class RedisCache : ICacheService { ServiceStackRedis service = null; public RedisCache(string host, int port, string password, int expirySeconds, long db) { service = new ServiceStackRedis(host, port, password, expirySeconds, db); } public RedisCache(string host) { service = new ServiceStackRedis(host); } public RedisCache() { service = new ServiceStackRedis(); } public void Add<V>(string key, V value) { service.Set(key, value); } public void Add<V>(string key, V value, int cacheDurationInSeconds) { service.Set(key, value,cacheDurationInSeconds); } public bool ContainsKey<V>(string key) { return service.ContainsKey(key); } public V Get<V>(string key) { return service.Get<V>(key); } public IEnumerable<string> GetAllKey<V>() { return service.GetAllKeys(); } public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue) { if (this.ContainsKey<V>(cacheKey)) { return this.Get<V>(cacheKey); } else { var result = create(); this.Add(cacheKey, result, cacheDurationInSeconds); return result; } } public void Remove<V>(string key) { service.Remove(key); } } public class ServiceStackRedis { private readonly int _expirySeconds = -1; private readonly PooledRedisClientManager _redisClientManager; private readonly SerializeService _serializeService = new SerializeService(); public ServiceStackRedis(string host, int port, string password, int expirySeconds, long db) { _expirySeconds = expirySeconds; var hosts = new[] { string.Format("{0}@{1}:{2}", password, host, port) }; _redisClientManager = new PooledRedisClientManager(hosts, hosts, null, db, 500, _expirySeconds); } public ServiceStackRedis(string host) : this(host, 6379, null, -1, 0) { } public ServiceStackRedis() : this("localhost", 6379, null, -1, 0) { } public bool Set(string key, object value) { if (key == null) throw new ArgumentNullException("key"); if (_expirySeconds != -1) return Set(key, value, _expirySeconds); var json = _serializeService.SerializeObject(value); using (var client = _redisClientManager.GetClient()) { return client.Set(key, json); } } public bool Set(string key, object value, int duration) { if (key == null) throw new ArgumentNullException("key"); var json = _serializeService.SerializeObject(value); using (var client = _redisClientManager.GetClient()) { return client.Set(key, json, DateTime.Now.AddSeconds(duration)); } } public T Get<T>(string key) { if (key == null) throw new ArgumentNullException("key"); string data; using (var client = _redisClientManager.GetClient()) { data = client.Get<string>(key); } return data == null ? default(T) : _serializeService.DeserializeObject<T>(data); } public bool Remove(string key) { using (var client = _redisClientManager.GetClient()) { return client.Remove(key); } } public bool RemoveAll() { using (var client = _redisClientManager.GetClient()) { try { client.FlushDb(); return true; } catch (Exception) { return false; } } } public bool ContainsKey(string key) { using (var client = _redisClientManager.GetClient()) { return client.ContainsKey(key); } } public List<string> GetAllKeys() { using (var client = _redisClientManager.GetClient()) { return client.SearchKeys("SqlSugarDataCache.*"); } } } }
0 回复 -
fate stay night VIP0
2020/12/5.NET Core 版本的 自带缓存
public class SugarCache : ICacheService { MemoryCacheHelper cache = new MemoryCacheHelper(); public void Add<V>(string key, V value) { cache.Set(key, value); } public void Add<V>(string key, V value, int cacheDurationInSeconds) { cache.Set(key, value,cacheDurationInSeconds); } public bool ContainsKey<V>(string key) { return cache.Exists(key); } public V Get<V>(string key) { return cache.Get<V>(key); } public IEnumerable<string> GetAllKey<V>() { return cache.GetCacheKeys(); } public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue) { if (cache.Exists(cacheKey)) { return cache.Get<V>(cacheKey); } else { var result = create(); cache.Set(cacheKey, result, cacheDurationInSeconds); return result; } } public void Remove<V>(string key) { cache.Remove(key); } } public class MemoryCacheHelper { private static readonly MemoryCache Cache = new MemoryCache(new MemoryCacheOptions()); /// <summary> /// 验证缓存项是否存在 /// </summary> /// <param name="key">缓存Key</param> /// <returns></returns> public bool Exists(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); return Cache.TryGetValue(key, out _); } /// <summary> /// 添加缓存 /// </summary> /// <param name="key">缓存Key</param> /// <param name="value">缓存Value</param> /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param> /// <param name="expiressAbsoulte">绝对过期时长</param> /// <returns></returns> public bool Set(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte) { if (key == null) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); Cache.Set(key, value, new MemoryCacheEntryOptions().SetSlidingExpiration(expiresSliding) .SetAbsoluteExpiration(expiressAbsoulte)); return Exists(key); } /// <summary> /// 添加缓存 /// </summary> /// <param name="key">缓存Key</param> /// <param name="value">缓存Value</param> /// <param name="expiresIn">缓存时长</param> /// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param> /// <returns></returns> public bool Set(string key, object value, TimeSpan expiresIn, bool isSliding = false) { if (key == null) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); Cache.Set(key, value, isSliding ? new MemoryCacheEntryOptions().SetSlidingExpiration(expiresIn) : new MemoryCacheEntryOptions().SetAbsoluteExpiration(expiresIn)); return Exists(key); } /// <summary> /// 添加缓存 /// </summary> /// <param name="key">缓存Key</param> /// <param name="value">缓存Value</param> /// <returns></returns> public void Set(string key, object value) { Set(key, value, TimeSpan.FromDays(1)); } /// <summary> /// 添加缓存 /// </summary> /// <param name="key">缓存Key</param> /// <param name="value">缓存Value</param> /// <param name="ts"></param> /// <returns></returns> public void Set(string key, object value, TimeSpan ts) { Set(key, value, ts, false); } /// <summary> /// 添加缓存 /// </summary> /// <param name="key">缓存Key</param> /// <param name="value">缓存Value</param> /// <param name="ts"></param> /// <returns></returns> public void Set(string key, object value, int seconds) { var ts = TimeSpan.FromSeconds(seconds); Set(key, value, ts, false); } #region 删除缓存 /// <summary> /// 删除缓存 /// </summary> /// <param name="key">缓存Key</param> /// <returns></returns> public void Remove(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); Cache.Remove(key); } /// <summary> /// 批量删除缓存 /// </summary> /// <returns></returns> public void RemoveAll(IEnumerable<string> keys) { if (keys == null) throw new ArgumentNullException(nameof(keys)); keys.ToList().ForEach(item => Cache.Remove(item)); } #endregion #region 获取缓存 /// <summary> /// 获取缓存 /// </summary> /// <param name="key">缓存Key</param> /// <returns></returns> public T Get<T>(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); return Cache.Get<T>(key); } /// <summary> /// 获取缓存 /// </summary> /// <param name="key">缓存Key</param> /// <returns></returns> public object Get(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); return Cache.Get(key); } /// <summary> /// 获取缓存集合 /// </summary> /// <param name="keys">缓存Key集合</param> /// <returns></returns> public IDictionary<string, object> GetAll(IEnumerable<string> keys) { if (keys == null) throw new ArgumentNullException(nameof(keys)); var dict = new Dictionary<string, object>(); keys.ToList().ForEach(item => dict.Add(item, Cache.Get(item))); return dict; } #endregion /// <summary> /// 删除所有缓存 /// </summary> public void RemoveCacheAll() { var l = GetCacheKeys(); foreach (var s in l) { Remove(s); } } /// <summary> /// 删除匹配到的缓存 /// </summary> /// <param name="pattern"></param> /// <returns></returns> public void RemoveCacheRegex(string pattern) { IList<string> l = SearchCacheRegex(pattern); foreach (var s in l) { Remove(s); } } /// <summary> /// 搜索 匹配到的缓存 /// </summary> /// <param name="pattern"></param> /// <returns></returns> public IList<string> SearchCacheRegex(string pattern) { var cacheKeys = GetCacheKeys(); var l = cacheKeys.Where(k => Regex.IsMatch(k, pattern)).ToList(); return l.AsReadOnly(); } /// <summary> /// 获取所有缓存键 /// </summary> /// <returns></returns> public List<string> GetCacheKeys() { const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; var entries = Cache.GetType().GetField("_entries", flags).GetValue(Cache); //.net7需要这样写 //var coherentState = _memoryCache.GetType().GetField("_coherentState", flags).GetValue(_memoryCache); //var entries = coherentState.GetType().GetField("_entries", flags).GetValue(coherentState); var cacheItems = entries as IDictionary; var keys = new List<string>(); if (cacheItems == null) return keys; foreach (DictionaryEntry cacheItem in cacheItems) { keys.Add(cacheItem.Key.ToString()); } return keys; } }
0 回复 -
东汉 VIP0
2021/3/9首先,SqlSugar很棒!我之前是用“Dapper+Dapper扩展包”,现在果断转用SqlSugar。
其次,我想说我不会用这个二级缓存,作用不大、更新缓存时性能有问题。我上午刚看了会二级缓存的内容,对这块并不算深入了解,如果有说错的地方还请指正。
问题和建议:
比如数据库用户表有用户A(Id=1)、用户B(Id=2)两笔数据,已经在SqlSugar的二级缓存中,如果用户A改变,那么调用RemoveDataCache,它会把用户B的缓存也删除了?
作者回答:如果每个用户的不同操作都是独立的,那么这个情况就不适合用缓存,因为内存有限
RemoveDataCache是取缓存AllKey,取AllKey的过程性能是不好的,不管是redis还是net core 自带的IMemoryCache。redis在key多的时候,取所有key直接卡住,会导致其它操作等待。二级缓存可以设计成自己存储所有key,因为所有key都是二级缓存产生的。
作者回答:GetAllKey是你自个实现的,你完全可以让这个GetAllkey 只取出你想要的
key产生的规则太麻烦,key太长了,key长也是开销。其实key名称可以直接约定为比如:"sugar.表名.主键值"(开放获取key的函数),这样的话,如果只是修改用户A的数据,那么我只要删除"sugar.用户.1"这个key的缓存即可。
然后再建议:SqlSugar只要发现是根据主键对某一笔数据进行更改、删除,都可以自动删除这笔缓存。
作者回答:KEY长度是没办法改变的,要保证唯一, 对于每一笔数据的 删除改 这种用缓存去存储是不合适的你把缓存当成一个数据库在用
如果能按第3点的设计,几乎是不会用到取所有key的操作,如果没必要,都不用特意去存储所有key。
我这边建议的是对单个实体(根据主键)的CRUD操作时的缓存。另,SqlSugar目前二级缓存应该也有支持对相同条件查询的缓存,这时开放取key的函数,让调用方可以单单删除当前项即可。
0 回复 -
东汉 VIP0
2021/3/9Net Core自带内存缓存,在Startup.cs里增加services.AddMemoryCache();
/// <summary> /// 实现SqlSugar的ICacheService接口,为了让SqlSugar直接支持简单缓存操作。 /// </summary> public class SqlSugarMemoryCacheService : BaseService, ICacheService //继承空类BaseService,会统一Ioc注册 { protected IMemoryCache _memoryCache; public SqlSugarMemoryCacheService(IMemoryCache memoryCache) { _memoryCache = memoryCache; } public void Add<V>(string key, V value) { _memoryCache.Set(key, value); } public void Add<V>(string key, V value, int cacheDurationInSeconds) { _memoryCache.Set(key, value, DateTimeOffset.Now.AddSeconds(cacheDurationInSeconds)); } public bool ContainsKey<V>(string key) { return _memoryCache.TryGetValue(key, out _); } public V Get<V>(string key) { return _memoryCache.Get<V>(key); } public IEnumerable<string> GetAllKey<V>() { const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; var entries = _memoryCache.GetType().GetField("_entries", flags).GetValue(_memoryCache); //.NET 7 //var coherentState = _memoryCache.GetType().GetField("_coherentState", flags).GetValue(_memoryCache); //var entries = coherentState.GetType().GetField("_entries", flags).GetValue(coherentState); var cacheItems = entries as IDictionary; var keys = new List<string>(); if (cacheItems == null) return keys; foreach (DictionaryEntry cacheItem in cacheItems) { keys.Add(cacheItem.Key.ToString()); } return keys; } public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue) { if (!_memoryCache.TryGetValue<V>(cacheKey, out V value)) { value = create(); _memoryCache.Set(cacheKey, value); } return value; } public void Remove<V>(string key) { _memoryCache.Remove(key); } } }
0 回复 -
会弹吉他的猴子 VIP0
2021/5/15@Mr、谢:您好,非常感谢您共享出来的这个缓存类,我想请教一下,我要怎么把数据放到这个缓存里,我第一次接触缓存,不知道语法是怎样的,您如果有时间的话,可以跟我说一下怎么使用吗?谢谢啦
0 回复 -
Mr、谢 VIP0
2021/5/17@会弹吉他的猴子:https://www.donet5.com/Home/Doc?typeId=1214 参考这个
0 回复 -
胖虎啊 VIP0
2021/6/18@东汉:呀,你这里写的少了一点东西哦 忘记加时间了把,哈哈哈哈 能坑死一堆不看代码直接复制的
public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue) { if (!_memoryCache.TryGetValue<V>(cacheKey, out V value)) { value = create(); _memoryCache.Set(cacheKey, value); } return value; }
public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue) { if (!_memoryCache.TryGetValue<V>(cacheKey, out V value)) { value = create(); _memoryCache.Set(cacheKey, value, DateTime.Now.AddSeconds(cacheDurationInSeconds)); } return value; }
0 回复 -
江林 VIP0
2022/4/17@东汉:
0 回复 -
Falcon VIP0
2022/10/11Microsoft.Extensions.Caching.Distributed.IDistributedCache实现:
/// <summary> /// 使用分布式缓存存储器 /// </summary> public class DistributedCache : ICacheService { /// <summary> /// 分布式缓存存储器 /// </summary> public IDistributedCache Cache { get; set; } /// <summary> /// 序列化方法 /// </summary> public IJsonSerialize Serialize { get; set; } /// <summary> /// 提供分布式缓存存储器 /// </summary> /// <param name="cache">分布式缓存存储器</param> /// <param name="serialize">实现序列化的接口s</param> public DistributedCache(IDistributedCache cache, IJsonSerialize serialize) { this.Cache = cache; this.Serialize = serialize; } /// <inheritdoc/> public void Add<V>(string key, V value) { var valStr = this.Serialize.Serialize(value); this.Cache.SetString(key, valStr); } /// <inheritdoc/> public void Add<V>(string key, V value, int cacheDurationInSeconds) { var valStr = this.Serialize.Serialize(value); DistributedCacheEntryOptions op = new() { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(cacheDurationInSeconds), }; this.Cache.SetString(key, valStr, op); } /// <inheritdoc/> public bool ContainsKey<V>(string key) { return this.Cache.Get(key) != null; } /// <inheritdoc/> public V Get<V>(string key) { var val = this.Cache.GetString(key); if (val == null) return default(V); return (V)this.Serialize.Deserialize(val, typeof(V)); } /// <inheritdoc/> public IEnumerable<string> GetAllKey<V>() { throw new NotImplementedException(); } /// <inheritdoc/> public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue) { if (ContainsKey<V>(cacheKey)) { return Get<V>(cacheKey); } V val = create(); Add(cacheKey, val, cacheDurationInSeconds); return val; } /// <inheritdoc/> public void Remove<V>(string key) { this.Cache.Remove(key); } }
GetAllKey方法好像无法支持。另外需要自己实现以下接口。
/// <summary> /// 序列化对象到字符串 /// </summary> public interface IJsonSerialize { /// <summary> /// 序列化对象 /// </summary> /// <typeparam name="T">对象类型</typeparam> /// <param name="obj">对象</param> /// <returns>序列化字符串</returns> public string Serialize<T>(T obj); /// <summary> /// 反序列化对象 /// </summary> /// <typeparam name="T">对象类型</typeparam> /// <param name="str">序列化字符串</param> /// <returns>对象实例</returns> public T? Deserialize<T>(string str) where T : class; /// <summary> /// 反序列化json字符串 /// </summary> /// <param name="str">json字符串</param> /// <param name="returnType">返回类型</param> /// <returns>json对象</returns> public object? Deserialize(string str, Type returnType); /// <summary> /// 序列化json对象 /// </summary> /// <param name="obj">json对象</param> /// <param name="inputType">输入类型</param> /// <returns>json字符串</returns> public string Serialize(object obj, Type inputType); }
0 回复 -
lwq VIP0
2023/4/4请问这个缓存默认时间是一天是在哪设置的,默认值是int.MaxValue,而不是一天,
源码:
protected int SetCacheTime(int cacheDurationInSeconds) { if (cacheDurationInSeconds == int.MaxValue && this.Context.CurrentConnectionConfig.MoreSettings != null && this.Context.CurrentConnectionConfig.MoreSettings.DefaultCacheDurationInSeconds > 0) { cacheDurationInSeconds = this.Context.CurrentConnectionConfig.MoreSettings.DefaultCacheDurationInSeconds; } return cacheDurationInSeconds; }
如果是int.MaxValue的话 则使用this.Context.CurrentConnectionConfig.MoreSettings.DefaultCacheDurationInSeconds,而我没找到这个属性默认值是多少。
0 回复 -
fate sta VIP0
2023/4/4@lwq:-
0 回复 -
fate sta VIP0
2023/4/4DbType=DbType.MySql同一个级的地方设置 MoreSettings
0 回复 -
斌斌 VIP0
2023/8/31有没有netstandar2.1 用的。我数据库放在这里了。
0 回复 -
... VIP0
2023/10/29framework版本必须是5以上的吗?
0 回复 -
xxoogod VIP0
2023/11/13我这边是做自动化业务的,基础数据前期配置好后,后期基本不会去修改数据库了,大部分的表数据量不大,一般万级内,但读取率高。我这边目前使用的是增加缓存整表到Redis的方法,读数据前先拉Redis。希望作者能够考虑指定缓存整表的方法。
0 回复 -
Sheldon VIP0
2024/1/29CSReidsCore版本来了:
/// <summary> /// 用官网二级缓存的案列ServiceStack自己改写的 /// Redis缓存 /// </summary> public class SqlSugarCsRedisCache : ICacheService { //注意:SugarRedis 不要扔到构造函数里面, 一定要单例模式 public void Add<V>(string key, V value) { RedisHelper.Set(key, value); } public void Add<V>(string key, V value, int cacheDurationInSeconds) { RedisHelper.Set(key, value, cacheDurationInSeconds); } public bool ContainsKey<V>(string key) { return RedisHelper.Exists(key); } public V Get<V>(string key) { return RedisHelper.Get<V>(key); } public IEnumerable<string> GetAllKey<V>() { //性能注意: 只查sqlsugar用到的key return RedisHelper.Keys("cache:SqlSugarDataCache.*");//个人封装问题,key前面会带上cache:缓存前缀,请根据实际情况自行修改 ,如果没有去掉前缀或者使用最下面.如果不确定,可以用最下面前面都加通配符的做法 // return RedisHelper.Keys("SqlSugarDataCache.*"); // return RedisHelper.Keys("*SqlSugarDataCache.*"); } public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue) { if (this.ContainsKey<V>(cacheKey)) { var result = this.Get<V>(cacheKey); if (result == null) { return create(); } else { return result; } } else { var result = create(); this.Add(cacheKey, result, cacheDurationInSeconds); return result; } } public void Remove<V>(string key) { RedisHelper.Del(key); } }
0 回复 -
QI VIP0
1个月前请问key值如何自定义设置呢?
0 回复 -
fate sta VIP0
1个月前@QI:发新贴这里不要有任何提问
0 回复