Redis 作为内存数据库,拥有非常高的性能,单个实例的 QPS 能够达到 10W 左右。
Redis 在写入数据时,需要为新的数据分配内存,当从 Redis 中删除数据时,它会释放对应的内存空间。
如果一个 Key 写入的数据非常大,Redis 在分配内存时也会比较耗时。同样的,当删除这个 Key 的数据时,释放内存也会耗时比较久。
你需要检查你的业务代码,是否存在写入大 Key 的情况,需要评估写入数据量的大小,业务层应该避免一个 Key 存入过大的数据量。
那么有没有什么办法可以扫描现在 Redis 中是否存在大 Key 的数据吗?
Redis 也提供了扫描大 Key 的方法:
redis-cli -h $host -p $port --bigkeys -i 0.01
项目上遇到过 存了几千条数据(5M以上)到redis 导致 从redis获取就花费了 近两秒
这里主要是针对微服务,因为微服务同一个程序可能有多个实例,此时 通过 redis 同步缓存memoryCache的key,删除了redis里面的key就可以使所有实现的缓存失效,无需同步删除所有实例的缓存(如果担心缓存时间过长,造成内存泄漏可以加一个定时任务 隔一段时间清理下redis上不存在的key)
具体实现如下(java原理一样):
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Service.Common.Autofac.Attributes;
using Service.Common.helpers;
using Utils.Common.utils;
namespace Service.Common.Services
{
/// <summary>
/// 内存缓存 主要是缓存部分大对象 不要所有的缓存都是用这个缓存
/// 不能依赖这个缓存 如果缓存查询不到还是要从数据库查询
/// 每个服务都会缓存一份
/// </summary>
[Service(lifetime = ServiceLifetime.Singleton)]
public class CacheService
{
//前缀
private static String redisKeyPrefix = "CacheServiceKey_";
//内存缓存
private IMemoryCache memoryCache;
//redis服务
private RedisService redisService;
/// <summary>
/// 构造方法
/// </summary>
/// <param name="memoryCache"></param>
/// <param name="redisService"></param>
public CacheService(IMemoryCache memoryCache, RedisService redisService)
{
this.memoryCache = memoryCache;
this.redisService = redisService;
}
/// <summary>
/// 获取对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public T Get<T>(string key)
{
if (String.IsNullOrWhiteSpace(key))
{
return default(T);
}
key = $"{redisKeyPrefix}{key}";
Object result;
if (redisService.Exists(key) && memoryCache.TryGetValue(key, out result))
{
return (T)result;
}
return default(T);
}
/// <summary>
/// 设置缓存
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="expireMinutes"></param>
public bool Set(string key, Object value, int expireMinutes = 1440)
{
TimeSpan timeSpan = TimeSpan.FromMinutes(expireMinutes);
return Set(key, value, timeSpan);
}
/// <summary>
/// 设置缓存
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="timeSpan"></param>
public bool Set(string key, object value, TimeSpan timeSpan)
{
if (String.IsNullOrWhiteSpace(key) || value == null)
{
return false;
}
key = $"{redisKeyPrefix}{key}";
memoryCache.Set(key, value, timeSpan);
redisService.Set(key, "1", timeSpan);
return true;
}
/// <summary>
/// 判断在缓存中是否存在该key的缓存数据
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool Exists(string key)
{
key = $"{redisKeyPrefix}{key}";
return redisService.Exists(key) && memoryCache.TryGetValue(key, out _);
}
/// <summary>
/// 移除指定key的缓存
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool Remove(string key)
{
if (String.IsNullOrWhiteSpace(key))
{
return true;
}
key = $"{redisKeyPrefix}{key}";
redisService.Remove(key);
memoryCache.Remove(key);
return true;
}
}
}
版权声明:本文为qq_17056391原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。