.NET redis 客户端开源组件 FreeRedis (继 CSRedisCore 之后重写)
什么是 FreeRedis
FreeRedis 是一款 .NET redis 客户端开源组件,以 MIT 协议开源托管于 github,目前支持 .NET 5、.NETCore 2.1+、.NETFramework 4.0+、Xamarin,有可能已经支持 AOT 编译(目前未测试,但会往这个方向走)。
FreeRedis 会严格按照 FreeSql 的开源方式,做好单元测试,兼容平台,简单易用,有问必答,有求必应的态度,为中国 .NET 开源事业做一点点贡献。
感谢大家的支持,项目还未公开就已经获得 66 星。目前项目仍在起步阶段,欢迎小伙伴参与进来,贡献测试、或代码、或建议都可以。
项目当前的状态:
- 版本 0.0.8(目前不建议使用在生产环境)
- 单元测试 268 个
- 支持 集群、哨兵、主从(已通过测试)
- 支持 连接池
- 支持 .NET5/.NETCore 2.1+/.NET4.0+
- 支持 Redis6.0 所有类型
- 支持 Redis6.0 RESP3 协议
- API 仍然与 redis-cli 命令保持一致
- 采用最宽松的开源协议 MIT https://github.com/2881099/FreeRedis
项目由来
说来话长,2016 年之前本人写了一年多 nodejs 服务端应用,使用过 node-redis 组件,真心好用。在此期间有同事不停安利 .NET 可以跨平台了,劝我快回来搞 .NET,开始我是抗拒做螃蟹第一人的,不知道是哪天下午闲着蛋疼去体验了一把 .NETCore 1.0-previewXX(不记得哪个版本了)。试了一把被吸引住了,体验感受和 expressjs 像极了,再也看不见以往 webform/mvc 的缺点。
于是我准备入坑了,入坑第一件事除了 hello world,还需要做相关调研:
- 性能OK
- 设计OK
- 发展OK(暂时的定级)
- 相关组件OK(HttpClient、Redis、Ado.NET、等等基础组件)
初始调研完成之后,接下下就要抽时间选型框架了,最终从众多框架中选择了合适团队的一款:https://github.com/simplcommerce/SimplCommerce ,在这个项目原有基础之上,结合企业规范要求定制改造,大约两个月时间完成了可生产的状态。(框架不求开始尽善尽美,只求使用中不断打磨,最终走向完美)
理想丰满现实骨干,接下来的故事就是遇到生产故障了,StackExchange.Redis、HttpClient 关于这两个组件的问题,以前讲过现在就不说了(万万没想到这么大的组件使用都能出现问题)。吃螃蟹就会掉坑,掉了坑就要想办法解决,最终与 csredis 组件结缘。
以当时的情形纵观 .NET 所有 redis 客户端组件,只有 csredis 源码最易改造支持 .NETCore(水平有限见谅),csredis 2014 年停止更新,本人于 2016 年将其改造支持 .NETCore 为主,以及增加连接池管理、集群、哨兵、redis2.8 以上的命令,在公司项目生产环境使用一年半载之后开源。
- csredis 原源码地址:https://github.com/ctstone/csredis
- CSRedisCore 源码地址:https://github.com/2881099/csredis
CSRedisCore 开源这到久,nuget 下载量达到 60W,收集需求若干,bug 若干(有解决了的、也有未能重现的),基于我已经对 redis 这块很熟悉,然后 redis 5.0/6.0 又新增了蛮多特性,重新写一款 bug 更少、可维护性更好的想法产生了。
经过几个月的墨迹终于走通可用了,项目最终命名:FreeRedis
如何使用
Single machine redis (单机)
public static RedisClient cli = new RedisClient("127.0.0.1:6379,password=123,defaultDatabase=13");
//cli.Serialize = obj => JsonConvert.SerializeObject(obj);
//cli.Deserialize = (json, type) => JsonConvert.DeserializeObject(json, type);
cli.Notice += (s, e) => Console.WriteLine(e.Log); //print command log
cli.Set("key1", "value1");
cli.MSet("key1", "value1", "key2", "value2");
string value1 = cli.Get("key1");
string[] vals = cli.MGet("key1", "key2");
API 仍然与 redis-cli 命令保持一致,所以如果想了解 FreeRedis 每个方法怎么使用,去百度搜索 “redis 命令”,有很多很多很多资料。don't say so much!!!
支持 Redis6.0 支持的所有数据类型:strings, hashes, lists, sets, sorted sets, bitmaps, hyperloglogs, geo, streams And BloomFilter.
Parameter | Default | Explain |
---|---|---|
protocol | RESP2 | If you use RESP3, you need redis 6.0 environment |
user | <empty> | Redis server username, requires redis-server 6.0 |
password | <empty> | Redis server password |
defaultDatabase | 0 | Redis server database |
max poolsize | 100 | Connection max pool size |
min poolsize | 5 | Connection min pool size |
idleTimeout | 20000 | Idle time of elements in the connection pool (MS) |
connectTimeout | 10000 | Connection timeout (MS) |
receiveTimeout | 10000 | Receive timeout (MS) |
sendTimeout | 10000 | Send timeout (MS) |
encoding | utf-8 | string charset |
ssl | false | Enable encrypted transmission |
name | <empty> | Connection name, use client list command to view |
如果需要连接 IPv6,连接串请使用: [fe80::b164:55b3:4b4f:7ce6%15]:6379
Master-Slave (读写分离)
public static RedisClient cli = new RedisClient(
"127.0.0.1:6379,password=123,defaultDatabase=13",
"127.0.0.1:6380,password=123,defaultDatabase=13",
"127.0.0.1:6381,password=123,defaultDatabase=13"
);
var value = cli.Get("key1");
这样创建的 cli,所有写入命令都会连接 127.0.0.1:6379 执行,所有读取命令只会随机连接 127.0.0.1:6380 或 127.0.0.1:6381 执行。(内部已经为每个命令做好了读写标记)
Redis Sentinel (哨兵高可用)
public static RedisClient cli = new RedisClient(
"mymaster,password=123",
new [] { "192.169.1.10:26379", "192.169.1.11:26379", "192.169.1.12:26379" },
true //是否读写分离
);
哨兵是一个分布式系统,为 Redis 提供高可用性解决方案,当主机 master 宕机之后,会马上出现一个新的 master 可使用,确保服务的正常运作。
哨兵模式还可以设置读写分离,缓解 master 频繁读取数据的压力,缺点:有可能读到的数据不是最新,因为 redis 从 master 同步到 slave 有延时。
Redis Cluster (集群)
假如你有一个 Redis Cluster 集群,其中有三个主节点(7001-7003)、三个从节点(7004-7006),则连接此集群的代码:
public static RedisClient cli = new RedisClient(
new ConnectionStringBuilder[] { "192.168.0.2:7001", "192.168.0.2:7001", "192.168.0.2:7003" }
);
Subscribe (订阅)
using (cli.Subscribe("abc", ondata)) //wait .Dispose()
{
Console.ReadKey();
}
void ondata(string channel, string data) =>
Console.WriteLine($"{channel} -> {data}");
Scripting (脚本)
var r1 = cli.Eval("return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}",
new[] { "key1", "key2" }, "first", "second") as object[];
var r2 = cli.Eval("return {1,2,{3,'Hello World!'}}") as object[];
cli.Eval("return redis.call('set',KEYS[1],'bar')",
new[] { Guid.NewGuid().ToString() })
Pipeline (管道)
using (var pipe = cli.StartPipe())
{
pipe.IncrBy("key1", 10);
pipe.Set("key2", Null);
pipe.Get("key1");
object[] ret = pipe.EndPipe();
Console.WriteLine(ret[0] + ", " + ret[2]);
}
// or Async Callback
using (var pipe = cli.StartPipe())
{
var tasks = new List<Task>();
long t0 = 0;
task.Add(pipe.IncrByAsync("key1", 10).ContinueWith(t => t0 = t.Result)); //callback
pipe.SetAsync("key2", Null);
string t2 = null;
task.Add(pipe.GetAsync("key1").ContinueWith(t => t2 = t.Result)); //callback
pipe.EndPipe();
Task.WaitAll(tasks.ToArray()); //wait all callback
Console.WriteLine(t0 + ", " + t2);
}
Transaction (事务)
using (var tran = cli.Multi())
{
tran.IncrBy("key1", 10);
tran.Set("key2", Null);
tran.Get("key1");
object[] ret = tran.Exec();
Console.WriteLine(ret[0] + ", " + ret[2]);
}
// or Async Callback
using (var tran = cli.Multi())
{
var tasks = new List<Task>();
long t0 = 0;
task.Add(tran.IncrByAsync("key1", 10).ContinueWith(t => t0 = t.Result)); //callback
tran.SetAsync("key2", Null);
string t2 = null;
task.Add(tran.GetAsync("key1").ContinueWith(t => t2 = t.Result)); //callback
tran.Exec();
Task.WaitAll(tasks.ToArray()); //wait all callback
Console.WriteLine(t0 + ", " + t2);
}
.NET redis 客户端开源组件 FreeRedis (继 CSRedisCore 之后重写)的更多相关文章
- Redis .NET开源组件Beetle.Redis
Redis .NET开源组件Beetle.Redis Beetle.Redis是一款开源的Redis Client for .net组件,它提供非常简便的操作方式可以让开发人员轻松地访问Redis,同 ...
- .Net 开源项目 FreeRedis 实现思路之 - Redis 6.0 客户端缓存技术
写在开头 FreeRedis 是一款继 CSRedisCore 之后重写的 .NET redis 客户端开源组件,以 MIT 协议开源托管于 github,目前支持 .NET 5..NETCore 2 ...
- Redis 客户端重试指南
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可. 在互联网服务中,特别是在云环境下,网络及硬件环境复杂,所有应用程序都可能遇到暂时性故障.暂时性故障包括瞬时的网络抖动,服务暂时不可 ...
- [开源福利] FreeRedis 历时两年正式发布 v1.0 [C#.NET Redis Client]
最近很多 .net QQ 群无故被封停,特别是 wpf 群几乎全军覆没.依乐祝的 .net6交流群,晓晨的 .net跨平台交流群,导致很多码友流离失所无家可归,借此机会使用一次召唤术,有需要的请加群: ...
- redis在游戏服务器中的使用初探(二) 客户端开源库选择
上文提到 搭建完成后 我们选择客户端的开源库进行连接 有以下三种选择 1 acl-redis 原因是支持VC 国产 作者博客 acl 框架库简介 用 acl 库编写高效的 C++ redis ...
- 国人开源了一款超好用的 Redis 客户端,真香!!
大家都知道,Redis Desktop Manager 是一款非常好用的 Redis 可视化客户端工具,但可惜的是 v0.9.4 版本之后需要收费了: 这个工具不再免费提供安装包了,要对所有安装包收费 ...
- .net 开源组件推荐 之 StackExchange
已经两年没更新过博客了!!! StackExchange,地址:https://github.com/StackExchange,开源的这些项目都是在StackOverflow线上使用的. 说起Sta ...
- .Net Core 三大Redis客户端对比和使用心得
前言 稍微复杂一点的互联网项目,技术选型都可能会涉及Redis,.NetCore的生态越发完善,支持.NetCore的Redis客户端越来越多, 下面三款常见的Redis客户端,相信大家平时或多或少用 ...
- 分享几个.NET WinForm开源组件,纪念逐渐远去的WinForm。。。
前面3个月的时间内,这些.NET开源项目你知道吗?系列文章已经发表了3篇,共计45个平时接触比较少,曾经默默无闻的.NET开源项目,展示给大家,当然不是每个人都能用得上,但也的确是有些人用了,反响还不 ...
随机推荐
- 玩转 SpringBoot2.x 之整合 thumbnailator 图片处理
1.序 在实际项目中,有时为了响应速度,难免会对一些高清图片进行一些处理,比如图片压缩之类的,而其中压缩可能就是最为常见的.最近,阿淼就被要求实现这个功能,原因是客户那边嫌速度过慢.借此机会,阿淼今儿 ...
- CentOS7 没有安装 ifconfig 命令
ifconfig 命令是设置或显示网络接口的程序,可以显示出我们机器的网卡信息. 除此之外, ip a 命令,也可以设置或显示网卡的信息 在 CentOS 7 下,默认 ifconfig 命令是没有安 ...
- docker-compose应用
docker-compose应用 需求编写compose模板文件,实现同时启动tomcat.mysql.redis容器. 1.编写模板文件 #新建文件夹mkdir -p /tzh/compose_te ...
- GCC编译选项笔记
警告选项 -Wall:开启大多数的警告信息 -Wextra:开启额外的警告信息,比如参数未使用警告(-Wunused-parameter) -Werror:将警告当作错误,中断编译 优化选项 -O,- ...
- 【最短路】HDU 1688 Sightseeing
题目大意 给出一个有向图(可能存在重边),求从\(S\)到\(F\)最短路的条数,如果次短路的长度仅比最短路的长度多1,那么再加上次短路的条数. 输入格式 第一行是数据组数\(T\). 对于魅族数据, ...
- Docker下部署springboot项目
1.背景 如何在docker容器环境下部署一个springboot项目? 2.具体步骤 第一步:准备一个springboot项目的xxxx.jar包 jar包中用于测试的一个接口如下 第二步:编写Do ...
- nginx配置laravel lumen重写
location / { try_files $uri $uri/ /index.php?$query_string;}
- 第五章 NFS、rsync等统一用户相关操作
一.统一用户 1.httpd2.NFS挂载目录3.rsync 1.所有服务器统一创建用户 [root@web01 ~]# groupadd www -g 666[root@web01 ~]# user ...
- JAVA 线上故障排查套路,从 CPU、磁盘、内存、网络到GC 一条龙!
线上故障主要会包括cpu.磁盘.内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次排查一遍. 同时例如jstack.jmap等工具也是不囿于一个方面的问题的, ...
- LeetCode 45跳跃游戏&46全排列
原创公众号:bigsai,回复进群加入力扣打卡群. 昨日打卡:LeetCode 42字符串相乘&43通配符匹配 跳跃游戏 题目描述: 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中 ...