Giter Club home page Giter Club logo

Comments (22)

2881099 avatar 2881099 commented on July 29, 2024

每秒并发数100,链接池500
如果一秒内完成不了操作,确实会超时
redis服务时本地还是远程,本地不太会这样

from csredis.

lawrence-peng avatar lawrence-peng commented on July 29, 2024

是本地的。其实50个并发也很快就满了。我的 redis 操作 主要是用的是 pub/sub .存储的数据是 base64 字符串,大小大概 5、6 K 左右。50并发不大,有什么解决方案吗

from csredis.

2881099 avatar 2881099 commented on July 29, 2024

原来如此啊,Subscribe 不能回收链接的,多少都会满,尽可能重用 Subscribe
如:
Subscribe(
("chan1", msg => Console.WriteLine(msg.Body)),
("chan2", msg => Console.WriteLine(msg.Body))
)

如果是一次性订阅,RedisHelper.Subscribe 暂时还不支持

from csredis.

2881099 avatar 2881099 commented on July 29, 2024
Task.Run(() => {
	try {
		subscr.Client.PSubscribe(chans);
	} catch (Exception ex) {
		var bgcolor = Console.BackgroundColor;
		Console.BackgroundColor = ConsoleColor.Yellow;
		Console.WriteLine($"模糊订阅出错(channel:{string.Join(",", chans)}{ex.Message},5秒后重连。。。");
		Console.BackgroundColor = bgcolor;
		Thread.CurrentThread.Join(1000 * 5);
		PSubscribe(channelPatterns, pmessage);
	}
});

RedisHelper.Subscribe 与 RedisHelper.PSubscribe 都是一根筋的设计,错误或断线重新订阅,不适合做一次性订阅,除非用完销毁这个redisClient实例,因为它已经有了对应的订阅事件,属性。。。这不符合连接池管理原则

redis-server本来是没有这种问题的

仍然推荐尽可能重用 Subscribe,不然只能自行现实了,参考文档:https://github.com/ctstone/csredis/blob/master/README.md

from csredis.

lawrence-peng avatar lawrence-peng commented on July 29, 2024

我的场景不是一次性订阅的。程序有一个单例的类,在程序启动的时候就执行一次订阅(RedisHelper.Subcribe)。 每次用户提交请求时就 Push。下面是订阅的部分代码:
image

from csredis.

2881099 avatar 2881099 commented on July 29, 2024
public partial class BaseController : Controller {
	public override void OnActionExecuting(ActionExecutingContext context) {
		RedisHelper.Publish("test", DateTime.Now.ToString("g"));
	}
}

//在 Startup.cs

RedisHelper.Subscribe(("test", msg => {
		Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(msg));
	}
));

image

运行结果,手工访问每个 BaseController 接口都有收到订阅消息

image

redisHelper 连接池数据,正常

正在下载 apache ab,等会发压力测试结果

from csredis.

2881099 avatar 2881099 commented on July 29, 2024

image

Server Software: Kestrel
Server Hostname: localhost
Server Port: 5000

Document Path: /Tag/
Document Length: 4061 bytes

Concurrency Level: 50
Time taken for tests: 3.516 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 22575000 bytes
HTML transferred: 20305000 bytes
Requests per second: 1422.24 [#/sec] (mean)
Time per request: 35.156 [ms] (mean)
Time per request: 0.703 [ms] (mean, across all concurrent requests)
Transfer rate: 6270.93 [Kbytes/sec] received

from csredis.

2881099 avatar 2881099 commented on July 29, 2024

CSRedis.ConnectionPool.GetConnection 连接池获取超时(10秒)的可能原因:

1、多次订阅,订阅长期占用连接,不会归还连接池,如上图 freeConnections: 49,allConnections: 50
2、借走连接池 redis 操作较耗时,未能及时完成(默认完成会自动归还)

连接池空的期间,若有借的需求,则 await 10秒,等待归还则马上激活(不用干等10秒),若10秒都无资源归还则抛出上述异常。

from csredis.

lawrence-peng avatar lawrence-peng commented on July 29, 2024

我的程序也是这样的实现的,有差别的地方是,我存到 redis 的内容是 png 图片的 base64 字符 ,字符的 size 大概 6K 左右。我想应该是操作比较耗时导致。可以试着把你的测试例子 Push 一个 base64 图片字符串看看

from csredis.

2881099 avatar 2881099 commented on July 29, 2024

image

正常的,复制这段代码,可以查看连接池状态

[HttpGet(@"connection/redis")]
public object GetRedisConnectionPool() {
	var ret = new Hashtable();
	foreach(var pool in RedisHelper.ClusterNodes) {
		List<Hashtable> list = new List<Hashtable>();
		foreach (var conn in pool.Value.AllConnections) {
			list.Add(new Hashtable() {
				{ "最后活动", conn.LastActive },
				{ "获取次数", conn.UseSum }
			});
		}
		ret.Add(pool.Key, new {
			FreeConnections = pool.Value.FreeConnections.Count,
			AllConnections = pool.Value.AllConnections.Count,
			GetConnectionQueue = pool.Value.GetConnectionQueue.Count,
			GetConnectionAsyncQueue = pool.Value.GetConnectionAsyncQueue.Count,
			List = list
		});
	}
	return ret;
}

from csredis.

lawrence-peng avatar lawrence-peng commented on July 29, 2024

我在 redis-cli 用命令 info 查看过,确实是满的。 我想跟我的代码有关系,在 push 函数,我有用 async task 而 redis push 用的 RedisHelper.Push

from csredis.

2881099 avatar 2881099 commented on July 29, 2024

push ? 还是 publish?我上面一直讲的是 Publish + Subscribe

push 是操作列表的

都是一个道理,使用方从连接池借走,操作耗时会归还不及时,导致阻塞后面的使用者,这个取决于连接池大小。

注: redis-server 是单线程的,多个连接不会提高效率,连接池的设计是借用其他库的**,避免重复 open close 连接的开销。

from csredis.

lawrence-peng avatar lawrence-peng commented on July 29, 2024

Publish ,表达有误。这个是我在 Startup.cs 的代码
image

image

image

我的代码跟你的测试用例基本一致了。连接数还是会一直飙上去。

netcore 单例注入 Processor,在 startup.cs 的 processor.run() 就是 执行 Subscribe,所以在controller 里,我拿到实例应该是同一个,用这个实例 processor.push

from csredis.

2881099 avatar 2881099 commented on July 29, 2024

_processor.Push 代码发出来看看

[HttpGet(@"connection/redis")]
public object GetRedisConnectionPool() {
	var ret = new Hashtable();
	foreach(var pool in RedisHelper.ClusterNodes) {
		List<Hashtable> list = new List<Hashtable>();
		foreach (var conn in pool.Value.AllConnections) {
			list.Add(new Hashtable() {
				{ "最后活动", conn.LastActive },
				{ "获取次数", conn.UseSum }
			});
		}
		ret.Add(pool.Key, new {
			FreeConnections = pool.Value.FreeConnections.Count,
			AllConnections = pool.Value.AllConnections.Count,
			GetConnectionQueue = pool.Value.GetConnectionQueue.Count,
			GetConnectionAsyncQueue = pool.Value.GetConnectionAsyncQueue.Count,
			List = list
		});
	}
	return ret;
}

把这段代码放进你的项目,请求截图发出来

from csredis.

lawrence-peng avatar lawrence-peng commented on July 29, 2024

_processor.Push 的代码在上面回复中已贴了。下面是 Run 的代码
image

这是服务器的服务运行后 redis info 出来的信息。

qq 20180823154525

这是服务器的服务停止后 redis info 出来的信息

image

代码统计的图

image

from csredis.

2881099 avatar 2881099 commented on July 29, 2024

_processor.Push 的代码在上面回复中已贴了


Run 的发了, _processor.Push 的没有发

from csredis.

lawrence-peng avatar lawrence-peng commented on July 29, 2024

image

from csredis.

2881099 avatar 2881099 commented on July 29, 2024

压力测试报错的时候,看 [HttpGet(@"connection/redis")] 接口的返回结果

from csredis.

lawrence-peng avatar lawrence-peng commented on July 29, 2024

我测试时,都把 async Task 去掉后没发现 10秒超时的报错了,但在redis-cli 看连接数还是满的。

from csredis.

2881099 avatar 2881099 commented on July 29, 2024

异步可以增加吞吐量,async 可以,因为.net线程池大小没超过500,所以连接池500个用不完

from csredis.

zsy619 avatar zsy619 commented on July 29, 2024

如何在高并发的情况下,防止:
CSRedis.ConnectionPool.GetConnection 连接池获取超时(10秒)
设置poolSize大小多少为合适?

from csredis.

2881099 avatar 2881099 commented on July 29, 2024

如何在高并发的情况下,防止:
CSRedis.ConnectionPool.GetConnection 连接池获取超时(10秒)
设置poolSize大小多少为合适?

异步方法,没有这个限制。

真实场景极少会这么大访问量,poolsize可以设置成同时刻访问次数/10,比如同时同时同时1000个操作,poolsize=100,具体还要看网络传输速度,如果redis-server是远程的,处理会稍慢。

poolsize好比道路的宽度,设大了浪费,设小了又堵车。所以先确定有多少台车,车速多少来决定。

from csredis.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.