You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
634 lines
19 KiB
634 lines
19 KiB
using Microsoft.Extensions.Caching.StackExchangeRedis;
|
|
using StackExchange.Redis;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Znyc.Recruitment.Admin.Commons.Cache
|
|
{
|
|
/// <summary>
|
|
/// Redis缓存操作
|
|
/// </summary>
|
|
public class RedisCacheService : ICacheService
|
|
{
|
|
/// <summary>
|
|
/// </summary>
|
|
private readonly ConnectionMultiplexer _connection;
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
private readonly string _instance;
|
|
|
|
private readonly JsonSerializerOptions _jsonOptions;
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
protected IDatabase _cache;
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="options"></param>
|
|
/// <param name="database"></param>
|
|
/// <param name="jsonOptions"></param>
|
|
public RedisCacheService(RedisCacheOptions options, JsonSerializerOptions jsonOptions, int database = 0)
|
|
{
|
|
_connection = ConnectionMultiplexer.Connect(options.Configuration);
|
|
_cache = _connection.GetDatabase(database);
|
|
_instance = options.InstanceName;
|
|
_jsonOptions = jsonOptions;
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <returns></returns>
|
|
public string GetKeyForRedis(string key)
|
|
{
|
|
return _instance + key;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_connection != null)
|
|
{
|
|
_connection.Dispose();
|
|
}
|
|
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
#region 验证缓存项是否存在
|
|
|
|
/// <summary>
|
|
/// 验证缓存项是否存在
|
|
/// </summary>
|
|
/// <param name="key">缓存Key</param>
|
|
/// <returns></returns>
|
|
public bool Exists(string key)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
return _cache.KeyExists(GetKeyForRedis(key));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 验证缓存项是否存在
|
|
/// </summary>
|
|
/// <param name="key">缓存Key</param>
|
|
/// <returns></returns>
|
|
public Task<bool> ExistsAsync(string key)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
return _cache.KeyExistsAsync(GetKeyForRedis(key));
|
|
}
|
|
|
|
#endregion 验证缓存项是否存在
|
|
|
|
#region 添加缓存
|
|
|
|
/// <summary>
|
|
/// 添加缓存
|
|
/// </summary>
|
|
/// <param name="key">缓存Key</param>
|
|
/// <param name="value">缓存Value</param>
|
|
/// <returns></returns>
|
|
public bool Add(string key, object value)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
return _cache.StringSet(GetKeyForRedis(key),
|
|
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加缓存
|
|
/// </summary>
|
|
/// <param name="key">缓存Key</param>
|
|
/// <param name="value">缓存Value</param>
|
|
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)</param>
|
|
/// <param name="expiressAbsoulte">绝对过期时长</param>
|
|
/// <returns></returns>
|
|
public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
return _cache.StringSet(GetKeyForRedis(key),
|
|
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiressAbsoulte);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加缓存
|
|
/// </summary>
|
|
/// <param name="key">缓存Key</param>
|
|
/// <param name="value">缓存Value</param>
|
|
/// <param name="expiresIn">缓存时长</param>
|
|
/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)</param>
|
|
/// <returns></returns>
|
|
public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
return _cache.StringSet(GetKeyForRedis(key),
|
|
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiresIn);
|
|
}
|
|
|
|
public Task<bool> AddAsync(string key, object value)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
return _cache.StringSetAsync(GetKeyForRedis(key),
|
|
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)));
|
|
}
|
|
|
|
public Task<bool> AddAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
return _cache.StringSetAsync(GetKeyForRedis(key),
|
|
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiressAbsoulte);
|
|
}
|
|
|
|
public Task<bool> AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
return _cache.StringSetAsync(GetKeyForRedis(key),
|
|
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)), expiresIn);
|
|
}
|
|
|
|
public Task<bool> HashSetAsync(string key, string filed, object value)
|
|
{
|
|
return _cache.HashSetAsync(GetKeyForRedis(key),
|
|
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(filed, _jsonOptions)),
|
|
Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value, _jsonOptions)));
|
|
}
|
|
|
|
#endregion 添加缓存
|
|
|
|
#region 删除缓存
|
|
|
|
/// <summary>
|
|
/// 删除缓存
|
|
/// </summary>
|
|
/// <param name="key">缓存Key</param>
|
|
/// <returns></returns>
|
|
public bool Remove(string key)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
return _cache.KeyDelete(GetKeyForRedis(key));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 批量删除缓存
|
|
/// </summary>
|
|
/// <param name="key">缓存Key集合</param>
|
|
/// <returns></returns>
|
|
public void RemoveAll(IEnumerable<string> keys)
|
|
{
|
|
if (keys == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(keys));
|
|
}
|
|
|
|
keys.ToList().ForEach(item => Remove(item));
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <returns></returns>
|
|
public Task<bool> RemoveAsync(string key)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
return _cache.KeyDeleteAsync(GetKeyForRedis(key));
|
|
}
|
|
|
|
public Task RemoveAllAsync(IEnumerable<int> keys)
|
|
{
|
|
//if (keys == null)
|
|
//{
|
|
throw new ArgumentNullException(nameof(keys));
|
|
//}
|
|
|
|
//keys.ToList().ForEach(item => RemoveAsync(item));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 使用通配符找出所有的key然后逐个删除
|
|
/// </summary>
|
|
/// <param name="pattern">通配符</param>
|
|
public virtual void RemoveByPattern(string pattern)
|
|
{
|
|
foreach (System.Net.EndPoint ep in _connection.GetEndPoints())
|
|
{
|
|
IServer server = _connection.GetServer(ep);
|
|
IEnumerable<RedisKey> keys = server.Keys(pattern: "*" + pattern + "*", database: _cache.Database);
|
|
foreach (RedisKey key in keys)
|
|
{
|
|
_cache.KeyDelete(key);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除所有缓存
|
|
/// </summary>
|
|
public void RemoveCacheAll()
|
|
{
|
|
RemoveByPattern("");
|
|
}
|
|
|
|
#endregion 删除缓存
|
|
|
|
#region 获取缓存
|
|
|
|
/// <summary>
|
|
/// 获取缓存
|
|
/// </summary>
|
|
/// <param name="key">缓存Key</param>
|
|
/// <returns></returns>
|
|
public T Get<T>(string key) where T : class
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
RedisValue value = _cache.StringGet(GetKeyForRedis(key));
|
|
|
|
if (!value.HasValue)
|
|
{
|
|
return default;
|
|
}
|
|
|
|
return JsonSerializer.Deserialize<T>(value, _jsonOptions);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取缓存
|
|
/// </summary>
|
|
/// <param name="key">缓存Key</param>
|
|
/// <returns></returns>
|
|
public object Get(string key)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
RedisValue value = _cache.StringGet(GetKeyForRedis(key));
|
|
|
|
if (!value.HasValue)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return JsonSerializer.Deserialize<object>(value, _jsonOptions);
|
|
//string json = value.ToString();
|
|
//return Newtonsoft.Json.JsonConvert.DeserializeObject(json);
|
|
}
|
|
|
|
/// <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));
|
|
}
|
|
|
|
Dictionary<string, object> dict = new Dictionary<string, object>();
|
|
|
|
keys.ToList().ForEach(item => dict.Add(item, Get(GetKeyForRedis(item))));
|
|
|
|
return dict;
|
|
}
|
|
|
|
public Task<T> GetAsync<T>(string key) where T : class
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public Task<object> GetAsync(string key)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public Task<IDictionary<string, object>> GetAllAsync(IEnumerable<int> keys)
|
|
{
|
|
throw new ArgumentNullException(nameof(keys));
|
|
}
|
|
|
|
#endregion 获取缓存
|
|
|
|
#region 修改缓存
|
|
|
|
/// <summary>
|
|
/// 修改缓存
|
|
/// </summary>
|
|
/// <param name="key">缓存Key</param>
|
|
/// <param name="value">新的缓存Value</param>
|
|
/// <returns></returns>
|
|
public bool Replace(string key, object value)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
if (Exists(key))
|
|
{
|
|
if (!Remove(key))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return Add(key, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 修改缓存
|
|
/// </summary>
|
|
/// <param name="key">缓存Key</param>
|
|
/// <param name="value">新的缓存Value</param>
|
|
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
|
|
/// <param name="expiressAbsoulte">绝对过期时长</param>
|
|
/// <returns></returns>
|
|
public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
if (Exists(key))
|
|
{
|
|
if (!Remove(key))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return Add(key, value, expiresSliding, expiressAbsoulte);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 修改缓存
|
|
/// </summary>
|
|
/// <param name="key">缓存Key</param>
|
|
/// <param name="value">新的缓存Value</param>
|
|
/// <param name="expiresIn">缓存时长</param>
|
|
/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
|
|
/// <returns></returns>
|
|
public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false)
|
|
{
|
|
if (key == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(key));
|
|
}
|
|
|
|
if (Exists(key))
|
|
{
|
|
if (!Remove(key))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return Add(key, value, expiresIn, isSliding);
|
|
}
|
|
|
|
public Task<bool> ReplaceAsync(string key, object value)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
#endregion 修改缓存
|
|
|
|
#region Hash
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
public bool HSet(string key, string filed, object value)
|
|
{
|
|
return RedisHelper.HSet(key, filed, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
public Task<bool> HSetAsync(string key, string filed, object value)
|
|
{
|
|
return RedisHelper.HSetAsync(key, filed, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
public Task<bool> HMSetAsync(string key, object[] value)
|
|
{
|
|
return RedisHelper.HMSetAsync(key, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
public bool HMSet(string key, object[] value)
|
|
{
|
|
return RedisHelper.HMSet(key, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <returns></returns>
|
|
public string[] HMGet(string key, string[] filed)
|
|
{
|
|
return RedisHelper.HMGet(key, filed);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <returns></returns>
|
|
public Task<string[]> HMGetAsync(string key, string filed)
|
|
{
|
|
return RedisHelper.HMGetAsync(key, filed);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <returns></returns>
|
|
public long HDel(string key, string[] filed)
|
|
{
|
|
return RedisHelper.HDel(key, filed);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <returns></returns>
|
|
public Task<long> HDelAsync(string key, string filed)
|
|
{
|
|
return RedisHelper.HDelAsync(key, filed);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <returns></returns>
|
|
public bool HExists(string key, string filed)
|
|
{
|
|
return RedisHelper.HExists(key, filed);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <returns></returns>
|
|
public Task<bool> HExistsAsync(string key, string filed)
|
|
{
|
|
return RedisHelper.HExistsAsync(key, filed);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <returns></returns>
|
|
public Task<long> HIncrByAsync(string key, string filed)
|
|
{
|
|
return RedisHelper.HIncrByAsync(key, filed);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <returns></returns>
|
|
public long HIncrBy(string key, string filed)
|
|
{
|
|
return RedisHelper.HIncrBy(key, filed);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <returns></returns>
|
|
public Task<Dictionary<string, string>> HGetAllAsync(string key)
|
|
{
|
|
return RedisHelper.HGetAllAsync(key);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <returns></returns>
|
|
public Dictionary<string, string> HGetAll(string key)
|
|
{
|
|
return RedisHelper.HGetAll(key);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <returns></returns>
|
|
public async Task<string> HGetAsync(string key, string filed)
|
|
{
|
|
return await RedisHelper.HGetAsync(key, filed);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
public Task<bool> HSetNxAsync(string key, string filed, object value)
|
|
{
|
|
return RedisHelper.HSetNxAsync(key, filed, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
/// <param name="key"></param>
|
|
/// <param name="filed"></param>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
public bool HSetNx(string key, string filed, object value)
|
|
{
|
|
return RedisHelper.HSetNx(key, filed, value);
|
|
}
|
|
|
|
#endregion Hash
|
|
}
|
|
}
|