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版权协议,转载请附上原文出处链接和本声明。