静态网页模板生成工具,汨罗网站seo,icp,wordpress登录修改前言稍微复杂一点的互联网项目#xff0c;技术选型都会涉及Redis#xff0c;.NetCore的生态越发完善#xff0c;支持.NetCore的Redis客户端越来越多#xff0c;下面三款常见的Redis客户端#xff0c;相信大家平时或多或少用到一些#xff0c;结合三款客户端的使用经历技术选型都会涉及Redis.NetCore的生态越发完善支持.NetCore的Redis客户端越来越多下面三款常见的Redis客户端相信大家平时或多或少用到一些结合三款客户端的使用经历有些心得体会。先比较宏观的背景使用心得三款客户端Redis支持的连接字符串配置基本相同 connectionstrings: {redis: localhost:6379,passwordabcdef,connectTimeout5000,writeBuffer40960}
1. StackExchange.Redis定位是高性能、通用的Redis .Net客户端方便地应用Redis全功能支持Redis Cluster高性能的核心在于多路复用连接允许有效使用来自多个调用线程的共享连接) 服务器端操作使用ConnectionMultiplexer类ConnectionMultiplexer redis ConnectionMultiplexer.Connect(server1:6379,server2:6379);
// 日常应用的核心类库是IDatabase
IDatabase db redis.GetDatabase();// 支持Pub/Sub
ISubscriber sub redis.GetSubscriber();
sub.Subscribe(messages, (channel, message) {Console.WriteLine((string)message);
});
---
sub.Publish(messages, hello);
也正是因为多路复用StackExchange.Redis唯一不支持的Redis特性是 blocking pops这个特性是RedisMQ的关键理论。如果你需要blocking pops StackExchange.Redis官方推荐使用pub/sub模型模拟实现。日常操作API请关注IDatabase接口支持异步方法这里我对【客户端操作Redis尽量不要使用异步方法】的说法不敢苟同对于异步方法我认为还是遵守微软最佳实践对于IO密集的操作能使用异步尽量使用异步// 对应redis自增apiDECR mykey
_redisDB0.StringDecrementAsync(ProfileUsageCap, (double)1)
// 对应redis apiHGET KEY field1
_redisDB0.HashGetAsync(profileUsage, eqidPair.ProfileId))
// 对应redis哈希自增apiHINCRBY myhash field -1
_redisDB0.HashDecrementAsync(profileUsage, eqidPair.ProfileId, 1)
ConnectionMultiplexer 方式支持随时切换Redis DB对于多个Redis DB的操作我封装了一个常用的Redis DB 操作客户端。public class RedisStore{private static LazyConnectionMultiplexer LazyConnection;private static string connectionRedis localhost:6379;public RedisStore(string connectiontring){connectionRedis connectiontring ?? localhost:6379;LazyConnection new LazyConnectionMultiplexer(() ConnectionMultiplexer.Connect(connectionRedis));}public static ConnectionMultiplexer Connection LazyConnection.Value;public RedisDatabase RedisCache new RedisDatabase(Connection);}public class RedisDatabase{private Dictionaryint, IDatabase DataBases new Dictionaryint, IDatabase();public ConnectionMultiplexer RedisConnection { get; }public RedisDatabase(ConnectionMultiplexer Connection){DataBases new Dictionaryint, IDatabase{ };for(var i0;i16;i){DataBases.Add(i, Connection.GetDatabase(i));}RedisConnection Connection;}public IDatabase this[int index]{get{if (DataBases.ContainsKey(index))return DataBases[index];elsereturn DataBases[0];}}}
2. Microsoft.Extensions.Caching.StackExchangeRedis从nuget doc可知该组件库依赖于 StackExchange.Redis 客户端是.NetCore针对分布式缓存提供的客户端侧重点在Redis的缓存特性。该库是基于 IDistributedCache 接口实现的该接口为实现分布式缓存的通用性缓存内容将以byte[] 形式读写 另外能使用的函数签名也更倾向于【通用的 增、查操作】// add Redis cache service
services.AddStackExchangeRedisCache(options
{options.Configuration Configuration.GetConnectionString(redis);options.InstanceName SampleInstance;
});// Set Cache Item (by byte[])lifetime.ApplicationStarted.Register(()
{var currentTimeUTC DateTime.UtcNow.ToString();byte[] encodedCurrentTimeUTC Encoding.UTF8.GetBytes(currentTimeUTC);var options new DistributedCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(20));cache.Set(cachedTimeUTC, encodedCurrentTimeUTC, options);
});// Retrieve Cache Item
[HttpGet]
[Route(CacheRedis)]
public async Taskstring GetAsync()
{var ret ;var bytes await _cache.GetAsync(cachedTimeUTC);if (bytes ! null){ret Encoding.UTF8.GetString(bytes);_logger.LogInformation(ret);}return await Task.FromResult(ret);
}
① 很明显该Cache组件并不能做到自由切换 Redis DB 目前可在redis连接字符串一次性配置项目要使用哪个Redis DB② 会在指定DB默认为0生成key SampleInstancecachedTimeUTC 的redis缓存项③ 通用接口只支持bytes[] 形式传值以上byte[] 实际是以Hash的形式存储3. CSRedisCore该组件是基于连接池模型默认配置会预热50个redis连接。功能更灵活针对实际Redis应用场景有更多玩法。普通模式官方集群模式 redis cluster分区模式作者实现普通模式使用方法极其简单这里要提示的是该客户端也不支持随意切换Redis DB, 但是原作者给出一种缓解的方式构造多客户端。var redisDB new CSRedisClient[16]; // 多客户端
for (var a 0; a redisDB.Length; a)redisDB[a] new CSRedisClient(Configuration.GetConnectionString(redis) ,defaultDatabase a);
services.AddSingleton(redisDB);
// ----------------------------
_redisDB[0].IncrByAsync(ProfileUsageCap, -1)
_redisDB[0].HGetAsync(profileUsage, eqidPair.ProfileId.ToString())
_redisDB[0].HIncrByAsync(profileUsage, eqidPair.ProfileId.ToString(), -1);
内置的静态操作类RedisHelper 与Redis-Cli 命令完全一致 故能原生支持”blocking pops”。// 实现后台服务持续消费MQ消息
public class BackgroundJob : BackgroundService{private readonly CSRedisClient[] _redisDB;private readonly IConfiguration _conf;private readonly ILogger _logger;public BackgroundJob(CSRedisClient[] csRedisClients,IConfiguration conf,ILoggerFactory loggerFactory){_redisDB csRedisClients;_conf conf;_logger loggerFactory.CreateLogger(nameof(BackgroundJob));}// Background 需要实现的后台任务protected override async Task ExecuteAsync(CancellationToken stoppingToken){_redisDB[0] new CSRedisClient(_conf.GetConnectionString(redis) ,defualtDatabase 0);RedisHelper.Initialization(_redisDB[0]);while (!stoppingToken.IsCancellationRequested){var key $eqidpair:{DateTime.Now.ToString(yyyyMMdd)};// 阻塞式从右侧读取List首消息var eqidpair RedisHelper.BRPop(5, key);// TODO Handler Messageelseawait Task.Delay(1000, stoppingToken);}}}-----RedisMQ 生产者---
// 将一个或多个msg插入List头部
RedisHelper.LPush(redisKey, eqidPairs.ToArray());
以上三大客户端Microsoft.Extensions.Caching.StackExchangeRedis 与其他两者的定位还是有很大差距的单纯使用Redis缓存特性 有微软出品必属精品情结的可使用此客户端StackExchange.Redis、CSRedisCore 对于Redis全功能特性支持的比较全Redis的一点小经验对要使用的Redis API 的时间复杂度心里要有数尽量不要使用长时间运行的命令如keys *可通过redis.io SlowLog命令观测哪些命令耗时较长Redis Key可按照“”分隔定义成有业务意义的字符串如NewUsers:202004:666某些Redis UI可直观友好查看该键值合适确定Key-Value的大小Redis对于small value更友好 如果值很大考虑划分到多个key关于缓存穿透面试的时候会问自行搜索布隆过滤器。redis虽然有持久化机制但在实际中会将key-value持久化到关系型数据库因为对于某些结构化查询SQL更为有效。推荐阅读● 这么香的Chrome插件你都安装了吗● 一文掌握Cookies前世今生● ASP.NET Core跨平台技术内幕● TPL Dataflow组件应对高并发,低延迟要求● 实例解读Docker Swarm● 基于docker-compose的Gitlab CI/CD实践排坑指南