ServiceStack.Redis的源码分析

ServiceStack.Redis的源码分析(连接与连接池) 前几天在生产环境上redis创建连接方面的故障,分析过程中对ServiceStack.Redis的连接创建和连接池机制有了进一步了解。问题分析结束后,通过此文系统的将学习到的知识点整理出来。 从连接池获取RedisClient的流程 业务程序中通过PooledRedisClientManager对象的GetClient()方法获取客户端对象,就以此处的源码作为入口: 查看代码 public IRedisClient GetClient() { RedisCl 阅读详情

前几天在生产环境上redis创建连接方面的故障,分析过程中对ServiceStack.Redis的连接创建和连接池机制有了进一步了解。问题分析结束后,通过此问题系统的将学习到的知识点整理出来。

从连接池获取RedisClient的流程

业务程序中通过PooledRedisClientManager对象的GetClient()方法获取客户端对象,就以此处的源码作为入口:

查看代码

public IRedisClient GetClient()        {            RedisClient redisClient = null;            DateTime now = DateTime.Now;            for (; ; )            {                if (!this.deactiveClientQueue.TryPop(out redisClient))                {                    if (this.redisClientSize >= this.maxRedisClient)                    {                        Thread.Sleep(3);                        if (this.PoolTimeout != null && (DateTime.Now - now).TotalMilliseconds >= (double)this.PoolTimeout.Value)                        {                            break;                        }                    }                    else                    {                        redisClient = this.CreateRedisClient();                        if (redisClient != null)                        {                            goto Block_5;                        }                    }                }                else                {                    if (!redisClient.HadExceptions)                    {                        goto Block_6;                    }                    List<RedisClient> obj = this.writeClients;                    lock (obj)                    {                        this.writeClients.Remove(redisClient);                        this.redisClientSize--;                    }                    RedisState.DisposeDeactivatedClient(redisClient);                }            }            bool flag2 = true;            if (flag2)            {                throw new TimeoutException("Redis Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use.");            }            return redisClient;        Block_5:            this.writeClients.Add(redisClient);            return redisClient;        Block_6:            redisClient.Active = true;            this.InitClient(redisClient);            return redisClient;        }

此方法的主体是死循环,主要实现了这几项功能:

  • this.deactiveClientQueue代表空闲的Client集合,是ConcurrentStack<RedisClient>类型的。
  • 当this.deactiveClientQueue能够Pop出redisClient时,则跳转到Block_6分支:标记redisClient.Active属性,并执行this.InitClient(redisClient),然后将redisClient实例返回。
  • 当this.deactiveClientQueue没有可以Pop的元素时,首先执行Client数量上限的判断this.redisClientSize >= this.maxRedisClient;如果未到达上限,则执行redisClient = this.CreateRedisClient();如果达到上限,则先休眠3毫秒,然后判断是否超过连接池超时时间this.PoolTimeout,单位毫秒。超时的话直接break中断循环,不超时的话继续下一次for循环。

上述流程就是从连接池获取Client的主要流程,其中this.deactiveClientQueue相当于“Client池”。需要注意this.PoolTimeout的含义是当连接池耗尽时调用方等待的时间。

上述过程通过流程图表示为:

创建新Client的过程:CreateRedisClient()

源码如下:

查看代码

 private RedisClient CreateRedisClient(){if (this.redisClientSize >= this.maxRedisClient){return null;}object obj = this.lckObj;RedisClient result;lock (obj){if (this.redisClientSize >= this.maxRedisClient){result = null;}else{Random random = new Random((int)DateTime.Now.Ticks);RedisClient newClient = this.InitNewClient(this.RedisResolver.CreateMasterClient(random.Next(100)));newClient.OnDispose += delegate(){if (!newClient.HadExceptions){List<RedisClient> obj2 = this.writeClients;lock (obj2){if (!newClient.HadExceptions){try{this.deactiveClientQueue.Push(newClient);return;}catch{this.writeClients.Remove(newClient);this.redisClientSize--;RedisState.DisposeDeactivatedClient(newClient);}}}}this.writeClients.Remove(newClient);this.redisClientSize--;RedisState.DisposeDeactivatedClient(newClient);};this.redisClientSize++;result = newClient;}}return result;}

基于并发的考虑,创建新Client的流程需要增加并发锁限制,即lock (obj)处。此时如果多个线程都进入CreateRedisClient()方法,则只有一个线程实际执行,其它线程阻塞等待锁释放。这个现象可以通过windbg的syncblk、clrstack命令分析查看。其余的部分就是继续调用this.InitNewClient(
this.RedisResolver.CreateMasterClient(random.Next(100)))创建对象,并对newClient的OnDispose事件增加了处理逻辑。需要说明的是此处OnDispose事件并不是传统意义的析构,而是调用方用完此RedisClient对象后,用于将其回收到连接池的操作,即:newClient对象没有异常的前提下, 将其Push到this.deactiveClientQueue栈里,连接池就是此处回收扩充的。

this.InitNewClient()方法解读

此处是对新创建的RedisClient对象初始化,包括Id、Active等,并继续调用this.InitClient()进一步初始化。

this.RedisResolver.CreateMasterClient()解读

this.redisResolver是IRedisResolver接口类型,源码中有三种实现,如下截图。此处以生产常见的哨兵模式为例进行分析。

RedisSentinelResolver类对应的就是哨兵模式,其相关操作源码如下:

查看代码

public RedisClient CreateMasterClient(int desiredIndex){return this.CreateRedisClient(this.GetReadWriteHost(desiredIndex), true);}public RedisEndpoint GetReadWriteHost(int desiredIndex){return this.sentinel.GetMaster() ?? this.masters[desiredIndex % this.masters.Length];}public virtual RedisClient CreateRedisClient(RedisEndpoint config, bool master){RedisClient result = this.ClientFactory(config);if (master){RedisServerRole redisServerRole = RedisServerRole.Unknown;try{using (RedisClient redisClient = this.ClientFactory(config)){redisClient.ConnectTimeout = 5000;redisClient.ReceiveTimeout = 5000;redisServerRole = redisClient.GetServerRole();if (redisServerRole == RedisServerRole.Master){this.lastValidMasterFromSentinelAt = DateTime.UtcNow;return result;}}}catch (Exception exception){Interlocked.Increment(ref RedisState.TotalInvalidMasters);using (RedisClient redisClient2 = this.ClientFactory(config)){redisClient2.ConnectTimeout = 5000;redisClient2.ReceiveTimeout = 5000;if (redisClient2.GetHostString() == this.lastInvalidMasterHost){object obj = this.oLock;lock (obj){if (DateTime.UtcNow - this.lastValidMasterFromSentinelAt > this.sentinel.WaitBeforeForcingMasterFailover){this.lastInvalidMasterHost = null;this.lastValidMasterFromSentinelAt = DateTime.UtcNow;RedisSentinelResolver.log.Error("Valid master was not found at '{0}' within '{1}'. Sending SENTINEL failover...".Fmt(redisClient2.GetHostString(), this.sentinel.WaitBeforeForcingMasterFailover), exception);Interlocked.Increment(ref RedisState.TotalForcedMasterFailovers);this.sentinel.ForceMasterFailover();Thread.Sleep(this.sentinel.WaitBetweenFailedHosts);redisServerRole = redisClient2.GetServerRole();}goto IL_16E;}}this.lastInvalidMasterHost = redisClient2.GetHostString();IL_16E:;}}if (redisServerRole != RedisServerRole.Master && RedisConfig.VerifyMasterConnections){try{Stopwatch stopwatch = Stopwatch.StartNew();for (;;){try{RedisEndpoint master2 = this.sentinel.GetMaster();using (RedisClient redisClient3 = this.ClientFactory(master2)){redisClient3.ReceiveTimeout = 5000;redisClient3.ConnectTimeout = this.sentinel.SentinelWorkerConnectTimeoutMs;if (redisClient3.GetServerRole() == RedisServerRole.Master){this.lastValidMasterFromSentinelAt = DateTime.UtcNow;return this.ClientFactory(master2);}Interlocked.Increment(ref RedisState.TotalInvalidMasters);}}catch{}if (stopwatch.Elapsed > this.sentinel.MaxWaitBetweenFailedHosts){break;}Thread.Sleep(this.sentinel.WaitBetweenFailedHosts);}throw new TimeoutException("Max Wait Between Sentinel Lookups Elapsed: {0}".Fmt(this.sentinel.MaxWaitBetweenFailedHosts.ToString()));}catch (Exception exception2){RedisSentinelResolver.log.Error("Redis Master Host '{0}' is {1}. Resetting allHosts...".Fmt(config.GetHostString(), redisServerRole), exception2);List<RedisEndpoint> list = new List<RedisEndpoint>();List<RedisEndpoint> list2 = new List<RedisEndpoint>();RedisClient redisClient4 = null;foreach (RedisEndpoint redisEndpoint in this.allHosts){try{using (RedisClient redisClient5 = this.ClientFactory(redisEndpoint)){redisClient5.ReceiveTimeout = 5000;redisClient5.ConnectTimeout = RedisConfig.HostLookupTimeoutMs;RedisServerRole serverRole = redisClient5.GetServerRole();if (serverRole != RedisServerRole.Master){if (serverRole == RedisServerRole.Slave){list2.Add(redisEndpoint);}}else{list.Add(redisEndpoint);if (redisClient4 == null){redisClient4 = this.ClientFactory(redisEndpoint);}}}}catch{}}if (redisClient4 == null){Interlocked.Increment(ref RedisState.TotalNoMastersFound);string message = "No master found in: " + string.Join(", ", this.allHosts.Map((RedisEndpoint x) => x.GetHostString()));RedisSentinelResolver.log.Error(message);throw new Exception(message);}this.ResetMasters(list);this.ResetSlaves(list2);return redisClient4;}return result;}return result;}return result;}

其中GetReadWriteHost()方法的逻辑是:优先使用this.sentinel.GetMaster()得到的主节点信息。如果GetMaster()失败,则从现有的主节点集合masters中随机选择一个进行连接。

然后进入CreateRedisClient()方法内:

  • 首先通过this.ClientFactory()工厂创建对象redisClient,工厂内部实现了计数和new RedisClient()操作。没有太多内容。
  • 然后是执行redisClient.GetServerRole(),代表向服务器核实当前连接的节点确实是Master角色。如果确认,则直接返回给调用方。【如果发送查询请求的过程出现异常,且符合一定条件,则会发起故障转移请求,即this.sentinel.ForceMasterFailover();】
  • 如果当前连接的不是Master角色的节点,则多次调用this.sentinel.GetMaster()查询Master节点信息并重新实例化RedisClient对象;
  • 如果超时仍然未能连接到Master节点,则会进入catch异常处理流程,遍历this.allHosts全部节点并更新对应的节点角色。

至此,通过上述的流程,最终能够得到master节点的RedisClient对象,并返回给调用方。

上述过程中,还有几处方法的实现比较重要和复杂,下面对其一一解释说明:

RedisSentinel类的GetMaster()实现原理解析

调用处很简单,但是此方法的实现操作挺多,RedisSentinel类 源码如下:

查看代码

public RedisEndpoint GetMaster(){RedisSentinelWorker validSentinelWorker = this.GetValidSentinelWorker();RedisSentinelWorker obj = validSentinelWorker;RedisEndpoint result;lock (obj){string masterHost = validSentinelWorker.GetMasterHost(this.masterName);if (this.ScanForOtherSentinels && DateTime.UtcNow - this.lastSentinelsRefresh > this.RefreshSentinelHostsAfter){this.RefreshActiveSentinels();}result = ((masterHost != null) ? ((this.HostFilter != null) ? this.HostFilter(masterHost) : masterHost).ToRedisEndpoint(null) : null);}return result;}private RedisSentinelWorker GetValidSentinelWorker(){if (this.isDisposed){throw new ObjectDisposedException(base.GetType().Name);}if (this.worker != null){return this.worker;}RedisException innerException = null;while (this.worker == null && this.ShouldRetry()){try{this.worker = this.GetNextSentinel();this.GetSentinelInfo();this.worker.BeginListeningForConfigurationChanges();this.failures = 0;return this.worker;}catch (RedisException ex){if (this.OnWorkerError != null){this.OnWorkerError(ex);}innerException = ex;this.worker = null;this.failures++;Interlocked.Increment(ref RedisState.TotalFailedSentinelWorkers);}}this.failures = 0;Thread.Sleep(this.WaitBetweenFailedHosts);throw new RedisException("No Redis Sentinels were available", innerException);}private RedisSentinelWorker GetNextSentinel(){object obj = this.oLock;RedisSentinelWorker result;lock (obj){if (this.worker != null){this.worker.Dispose();this.worker = null;}int num = this.sentinelIndex + 1;this.sentinelIndex = num;if (num >= this.SentinelEndpoints.Length){this.sentinelIndex = 0;}result = new RedisSentinelWorker(this, this.SentinelEndpoints[this.sentinelIndex]){OnSentinelError = new Action<Exception>(this.OnSentinelError)};}return result;}private void OnSentinelError(Exception ex){if (this.worker != null){RedisSentinel.Log.Error("Error on existing SentinelWorker, reconnecting...");if (this.OnWorkerError != null){this.OnWorkerError(ex);}this.worker = this.GetNextSentinel();this.worker.BeginListeningForConfigurationChanges();}}

先通过GetValidSentinelWorker()获得RedisSentinelWorker对象。此方法的实现包含了重试机制的控制,最终是通过this.GetNextSentinel()方法给this.worker字段,即RedisSentinelWorker对象实例。

而GetNextSentinel()方法内部包含了同步锁、调用this.worker.Dispose()、随机选择哨兵节点、实例化RedisSentinelWorker对象等操作。

后面是对validSentinelWorker进行加锁,然后继续执行string masterHost =
validSentinelWorker.GetMasterHost(this.masterName);

对应的RedisSentinelWorker类的代码如下:

查看代码

internal string GetMasterHost(string masterName){string result;try{result = this.GetMasterHostInternal(masterName);}catch (Exception obj){if (this.OnSentinelError != null){this.OnSentinelError(obj);}result = null;}return result;}private string GetMasterHostInternal(string masterName){List<string> list = this.sentinelClient.SentinelGetMasterAddrByName(masterName);if (list.Count <= 0){return null;}return this.SanitizeMasterConfig(list);}public void Dispose(){new IDisposable[]{this.sentinelClient,this.sentinePubSub}.Dispose(RedisSentinelWorker.Log);}

注意GetMasterHost()方法内:当发生异常时,会触发this对象的OnSentinelError事件,顾名思义这个事件用于哨兵异常的后续处理。通过源码搜索,只有GetNextSentinel()方法内对OnSentinelError事件增加了处理程序-->即RedisSentinel内的private void OnSentinelError(Exception ex)方法。而这个方法内部对打印日志和触发事件this.OnWorkerError后,又调用GetNextSentinel()重新给this.worker字段赋值。

需要注意:Dispose()方法实际是分别调用了this.sentinelClient和this.sentinePubSub的注销操作。

RedisNativeClient类的相关功能和实现

接着调用了RedisNativeClient类的
SentinelGetMasterAddrByName()方法:

这个类里的几个方法的含义综合起来就是:将哨兵客户端的查询指令通过Socket发送到服务端,并将返回结果格式化为所需的RedisEndpoint类型。

在方法SendReceive()内还包含了Socket连接、重试、频率控制、超时控制等机制。

查看代码

public List<string> SentinelGetMasterAddrByName(string masterName){List<byte[]> list = new List<byte[]>{Commands.Sentinel,Commands.GetMasterAddrByName,masterName.ToUtf8Bytes()};return this.SendExpectMultiData(list.ToArray()).ToStringList();}protected byte[][] SendExpectMultiData(params byte[][] cmdWithBinaryArgs){return this.SendReceive<byte[][]>(cmdWithBinaryArgs, new Func<byte[][]>(this.ReadMultiData), (this.Pipeline != null) ? new Action<Func<byte[][]>>(this.Pipeline.CompleteMultiBytesQueuedCommand) : null, false) ?? TypeConstants.EmptyByteArrayArray;}protected T SendReceive<T>(byte[][] cmdWithBinaryArgs, Func<T> fn, Action<Func<T>> completePipelineFn = null, bool sendWithoutRead = false){int num = 0;Exception ex = null;DateTime utcNow = DateTime.UtcNow;T t;for (;;){try{this.TryConnectIfNeeded();if (this.socket == null){throw new RedisRetryableException("Socket is not connected");}if (num == 0){this.WriteCommandToSendBuffer(cmdWithBinaryArgs);}if (this.Pipeline == null){this.FlushSendBuffer();}else if (!sendWithoutRead){if (completePipelineFn == null){throw new NotSupportedException("Pipeline is not supported.");}completePipelineFn(fn);t = default(T);t = t;break;}T t2 = default(T);if (fn != null){t2 = fn();}if (this.Pipeline == null){this.ResetSendBuffer();}if (num > 0){Interlocked.Increment(ref RedisState.TotalRetrySuccess);}Interlocked.Increment(ref RedisState.TotalCommandsSent);t = t2;}catch (Exception ex2){RedisRetryableException ex3 = ex2 as RedisRetryableException;if ((ex3 == null && ex2 is RedisException) || ex2 is LicenseException){this.ResetSendBuffer();throw;}Exception ex4 = ex3 ?? this.GetRetryableException(ex2);if (ex4 == null){throw this.CreateConnectionError(ex ?? ex2);}if (ex == null){ex = ex4;}if (!(DateTime.UtcNow - utcNow < this.retryTimeout)){if (this.Pipeline == null){this.ResetSendBuffer();}Interlocked.Increment(ref RedisState.TotalRetryTimedout);throw this.CreateRetryTimeoutException(this.retryTimeout, ex);}Interlocked.Increment(ref RedisState.TotalRetryCount);Thread.Sleep(RedisNativeClient.GetBackOffMultiplier(++num));continue;}break;}return t;}

总结

本文着重以Redis连接创建、获取为线索,对SDK内部的实现机制有了更深入的了解。在此基础上,分析生产环境Redis SDK相关故

ServiceStack.Redis C#驱动实战指南:V3.9版本全面解析 本文还有配套的精品资源,点击获取 简介:ServiceStack.Redis是C#中集成Redis官方驱动,版本为 . .* . ,支持.NET应用高效使用Redis数据存储。涵盖键值操作、集合处理、发布订阅、事务、脚本处理、持久化和性能优化等。本指南提供详细知识点,帮助开发者提升.NET应用性能和扩展性。 1. ServiceStac... 阅读详情

相关推荐

在.NET中使用ServiceStack.Redis操作Redis缓存

Redis是一个开源的高性能键值存储数据库,常被用作数据结构服务器。由于其提供原子操作支持,并且在内存中执行所有操作,因此能够在极短的时间内完成大量的数据读写。ServiceStack.Redis库因其简洁直观的API设计而广受欢迎,其设计哲学使得开发者能够快速上手并高效地进行Redis操作。相比其他类似的库,ServiceStack.Redis在易用性方面做得很出色。

weixin_42173218的博客 1098

ServiceStack.Redis

1、管理 NuGet 添加引用 ServiceStack.Redis 2、RedisHelper.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using ServiceStack.Redis; namespace Test.CoreLibrary ...

KingCruel的专栏 1729

ServiceStack.Redis 源码

ServiceStack.Redis 源代码,可以编译通过。Redis C#连接源代码

C# ServiceStack.Redis和StackExchange.Redis 使用心得

最近因项目需要在C#使用redis,在网上随意找一下看到挺多C#中使用ServiceStack.Redis 文章同时好像也是redis推介的C#客户端,就在没在仔细了解的情况下就直接使用了ServiceStack.Redis。在使用的过程中发现ServiceStack.Redis在频繁的读写后或运行一段时间后报错,后来在网上翻资料发现它已商业化,免费版每小时只能访问redis6000次。给出的解决方案有2个: StackExchange.Redis 使用方法及注意事项...

reinforceI的博客 2876

Workbench下列车转向架随机振动疲劳分析

结果中添加功率谱响应工具(Response PSD Tool),可以查看几何体以及远程点上的功率谱密度,如下图11所示,这里查看几何体上某一硬点的加速度功率谱密度响应曲线,如下图12所示。结果中添加疲劳工具(Fatigue Tool),查看列车转向架的疲劳寿命情况,这里采用窄带的寿命假设理论,曝光时间为1s指明计算出的疲劳寿命的基本单位是秒,寿命结果如下图14所示,可以看到最大寿命为1e35s,最小寿命为2.3542e18s,注意单位制,可再次基础上将其转换为小时或天。频域上的统计计算,软件很快计算完成。

ansysxuexizhe的博客 2605

告别Modern Standby烦恼:在Windows 11中手动启用S3睡眠模式的完整指南

本文详细介绍了如何在Windows 11中手动启用S3睡眠模式,解决Modern Standby(S0模式)导致的笔记本睡眠后耗电问题。通过注册表修改、电源选项调整、BIOS设置等步骤,帮助用户恢复传统深度睡眠功能,显著提升电池续航表现。

weixin_30271335的博客 559

C# 通过ServiceStack 操作Redis

nuget包是外国人写的,在国内并没有完整的中文文档,也没有专门的人来翻译、封装它,所以上面的代码方法不是很全,还有很多api方法需要自己去官网找然后自己封装。//删除不存在的数据,返回false。RedisBase-- 是redis操作的基类,继承自IDisposable接口,主要用于释放内存。//删除成功,返回true。//10. 设置key的过期时间(30秒后自动销毁)//5. 数值自增/减,返回自增、自减后的值。//8.获取多个key的 value值集合。//自增20,可以自增负值。

zhiqingcn的专栏 1987

Python遥感技术实战:NDWI与MNDWI水体提取算法对比与优化

本文详细对比了NDWI与MNDWI两种水体提取算法在Python遥感技术中的应用。通过实战代码演示,分析了二者在自然与城镇场景下的表现差异,并重点介绍了阈值优化与后处理技巧,旨在帮助读者掌握高效、精准的水体提取方法,提升遥感数据分析能力。

f6g7h8i9j的博客 499

Redis -- ServiceStack.Redis和StackExchange.Redis区别

目前Redis已经更新到了6.0.2,那目前StackExchange.Redis 和 ServiceStack.Redis 两个客户端有什么区别呢? StackExchange.Redis 客户端是开源免费,而ServiceStack.Redis目前我测试了4.0以上版本就有每个小时6000的限制。 性能方面,对比测试,ServiceStack比StackExchange性能上高将近50%。 以上分别是5000条和10w条数据写入读入比对,我这是将ServiceStack解除了每小时6000条数据的

qq_32911691的博客 2295

SiC双向车载充电器技术解析与V2G应用

碳化硅(SiC)功率器件凭借其高击穿电场强度、优异热导率和低开关损耗特性,正在重塑电力电子系统的设计边界。作为第三代半导体材料的代表,SiC MOSFET通过降低80%的开关损耗,使车载充电器(OBC)效率突破96.5%。在双向能量转换架构中,图腾柱PFC与CLLC谐振变换器的组合实现了ZVS软开关,配合三维集成散热方案使功率密度达54W/in³。这些技术进步直接支撑了V2G(车辆到电网)应用场景,使电动车成为虚拟电厂(VPP)的关键单元。通过智能充放电策略优化,电池循环寿命可提升至4000次以上,为电力市

weixin_30693683的博客 278

MaxENT生态位模型实战:从数据准备到论文发表的完整指南

本文提供MaxENT生态位模型从数据准备到论文发表的完整实战指南,涵盖物种分布数据处理、环境变量筛选、参数优化及结果可视化等关键步骤。特别介绍如何通过R语言进行高级建模优化,提升模型AUC值,并分享海洋生物专题研究中的数据处理技巧。适合生态学研究者快速掌握这一强大的物种分布预测工具,产出高质量研究成果。

tensor9flow的博客 303

C#使用ServiceStack.Redis通过密码连接Redis

1.前言 最近系统被国内行业某龙头企业采用准备本地化部署,但是在操作Redis方面代码里面一直有个隐患,可能过不了该企业的网络安全扫描,所以花了半天的时间对该问题进行了深究。 一直以来我们只是对Redis的使用端口做了控制,局域网内免密码操作的Redis,但是免密操作总是存在风险,但是如何使用ServiceStack.Redis通过密码连接Redis? 2.正题 ServiceStack.Redis在4.0之后需要商用授权,而我们又使用的是很久的版本2.2,这个版本的ServiceStack.Redis在进

m0_54849806的博客 949

ClaudeCode入门01-环境安装(小白入门:手把手教你配置,超简单的一种接入方式)

文手把手教你从零搭建 Claude Code 开发环境。针对国内网络现状,我们采用 OpenRouter + Claude Code Router 的方案,支持支付宝/微信充值,无需科学上网即可完成配置。内容涵盖 Node.js 安装(macOS/Windows/Linux)、OpenRouter 注册与充值、Claude Code 和 Router 安装配置,以及一键启动脚本的编写。跟着截图一步步操作,10分钟搞定全部环境!

yueyeguzhuo的专栏 282

记一次 .NET某智慧出行系统 CPU爆高分析

一:背景 1. 讲故事 前些天有位朋友找到我,说他们的系统出现了CPU 100%的情况,让我帮忙看一下怎么回事?dump也拿到了,本想着这种情况让他多抓几个,既然有了就拿现有的分析吧。 二:WinDbg 分析 1. 为什么会爆高 既然说是 100%,作为调试者得拿数据说话,可以使用 !tp 来观测一下。 0:000:x86> !tp CPU utilization: 100% Worke...

weixin_35856883的博客 191

ROS从入门到精通0-4:VSCode 搭建 ROS 工程环境

为了提高开发效率,可以先安装集成开发工具和使用方便的工具,本教程用VSCode搭建ROS工程环境

FRIGIDWINTER的博客 1万+

【openGauss实战1】openGauss基于CentOS8的部署

基于openGauss数据库在CentOS8上的安装实践。

IT邦德 3050

ServiceStack.Redis 破解

在github上下载了ServiceStack.Redis,做测试发现有限制,居然从v4开始就收费,无聊时,做了个源码分析 废话不多,上测试代码 try { for (int i = 0; i < 7000; i++) { r...

weixin_30888413的博客 515

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

破解ServiceStack.Redis每小时6000次限制

这个组件每小时默认访问次数是6000次的限制,这个在一个稍微大一点的项目里, 没几分钟就够了, 除非购买license或者降低版本使用,降低版本不考虑了,类型限制是20,这个组件自带序列化功能, 使得我们可以直接把对象保存到Redis库里, 但是我们保存类型复杂的时候, 就会有这个限制来报错.首先我们以16进制来打开该文件, 然后查找6000对应的值,从上图我们知道 这个是int类型存储的, int 是实用的4个字节来存储的 ,下面我们要做的就是把这个值改大一些, 直接改成int 的最大值。...

m0_67394002的博客 1546

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

.Net使用Redis详解之ServiceStack.Redis(七)

序言 本篇从.Net如何接入Reis开始,直至.Net对Redis的各种操作,为了方便学习与做为文档的查看,我做一遍注释展现,其中会对list的阻塞功能和事务的运用做二个案例,进行记录学习。 Redis官方推荐的.NET驱动类库为Service.Stack.Redis。然而网上对这个类库的中文文档不是很全面与合理,这篇文章主要就对这个类库做注释展现。不足遗漏之处还望见谅,海涵。 .Net使用...

weixin_34275734的博客 498

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

上一篇: Redis Pipeline还可以这么用的
下一篇: 让Redis循环写入时提高10倍的技巧
Java_ttcd
博客等级 码龄4年 198粉丝 190原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值