博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
那些年我们一起追过的缓存写法(四)
阅读量:6117 次
发布时间:2019-06-21

本文共 3899 字,大约阅读时间需要 12 分钟。

阅读目录: 

介绍

之前有童鞋问到关于首次为空的问题,这里简单补充下:

  • 一般来说并发量小、缓存数据量小的网站让用户自行触发页面让其缓存即可。
  • 大点网站都会多台部署,用负载均衡路由。常见的策略是在每台机器发布应用时,节点从负载均衡节点集合中移除,发布结束后,首次访问通过人工或自动请求下页面让其缓存,也包括预编译。
  • 还有一种是并发量大,缓存数据量大的情况,这也是本文的主题,下面会详细介绍。

如果缓存数据量大的情况下,预热就麻烦些。比如LZ公司单在内存中的缓存大小都过G,每次预热都需要数分钟,假设放在应用进程内,对运维工作非常不方便的。如果有意外导致进程池回收,对用户来说就是灾难性的。所以需要把应用进程的数据缓存给单独抽离出来存放,与应用解耦。

关于高并发的解决方案包括缓存更新策略可参见前几篇博客的介绍。

进程缓存

在网站架构演化中,这个阶段就需要引入分布式缓存了,比如memcached、redis。好处就不多讲了,坏处就是速度慢。这里速度慢是与本机内存缓存相比,跨机器通信跟直接读内存差的不是一数量级,对于并发量高、操作频繁的数据就不适用了。

所以把应用进程缓存的数据抽离出来,放在单独进程中,给应用提供一层缓存。缓存的业务逻辑、并发处理在独立进程中做,使用进程通信进行交互。这样不但解决了数据量大预热的麻烦,还能解耦部分应用的业务。

另外单独的进程也可以供外部使用,比如以WCF服务的方式提供给其他子系统使用。

缺点是跨进程读取的速度比进程内读取要稍慢。

通信方式

独立进程与应用进程的几种常见通信方式:

Namedpipe

Namedpipe一种相对高效的进程通信方式,支持局域网内通信。

Service端:

var txt = File.ReadAllText("b.txt");        ServerPipeConnection PipeConnection = new ServerPipeConnection("MyPipe", 512, 512, 5000, false);        Console.WriteLine("listening..");        while (true)        {            try            {                PipeConnection.Disconnect();                PipeConnection.Connect();                string request = PipeConnection.Read();                if (!string.IsNullOrEmpty(request))                {                    PipeConnection.Write(txt);                    if (request.ToLower() == "break") break;                }            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);                break;            }        }        PipeConnection.Dispose();        Console.Write("press any key to exit..");        Console.Read();
View Code

client端:

IInterProcessConnection clientConnection = new ClientPipeConnection("MyPipe", ".");  clientConnection.Connect(); var val = clientConnection.Read(); clientConnection.Close();

Wcf Namedpipe

Wcf在原生namedpipe包装了一下,使用起来更为简单方便。

Service端:

ServiceHost host = new ServiceHost( typeof (CacheService)); var NamePipe = new NetNamedPipeBinding(); host.AddServiceEndpoint(typeof(ICacheService), NamePipe, "net.pipe://localhost/CacheService"); host.Open(); Console.WriteLine("服务可用"); Console.ReadLine();  host.Close();

Client端:

ChannelFactory pipeFactory = new ChannelFactory(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/CacheService"));ICacheService pipeProxy = pipeFactory.CreateChannel();var obj=pipeProxy.GetVal();

SharedMemory

共享内存是进程间通信最快的一种方式,数据无需在进程间复制传输,直接开辟一块公共内存,供其他进程进行读写。  

service端:

var mmf = MemoryMappedFile.CreateFromFile(@"a.txt", FileMode.Open, "cachea"); Console.ReadLine(); mmf.Dispose();

Client端: 

var mmf = MemoryMappedFile.OpenExisting("cachea"); var accessor = mmf.CreateViewAccessor(0, 2000000); accessor.ReadChar(1000);accessor.Dispose(); mmf.Dispose();

WCF TCP方式

使用WcfTcp的方式,可以供外部网络使用。

Service端:

var ServiceHost host = new ServiceHost( typeof (CacheService));  host.AddServiceEndpoint(typeof (ICacheService), new NetTcpBinding(), "net.tcp://192.168.0.115:8057/CacheService/");host.Open();Console.WriteLine("服务可用");Console.ReadLine();host.Close();

 Client端:

ChannelFactory NetcpFactory = new ChannelFactory(netTcpBindingBinding,new EndpointAddress("net.tcp://192.168.0.115:8057/CacheService/")); ICacheService tcpProxy= NetcpFactory.CreateChannel(); var obj=tcpProxy.GetVal();

速度对比

上图是在windows7 i5-3230CPU上跑的,13M和1M文本数据各100次传输测试的均值。
其中原生namedpipe相较已经非常快了,在可以接受的范围,共享内存的方式速度会更快些。

测试结果表明Wcf的namedpipe要慢于wcf-tcp的方式,这个让人有些意外。

WcfTcp绑的是保留地址:

new ChannelFactory(netTcpBindingBinding, new EndpointAddress("net.tcp://192.168.0.115:8057/CacheService/"));

WcfTcp localhost绑的是127.0.0.1:

new ChannelFactory(netTcpBindingBinding, new EndpointAddress("net.tcp://localhost:8057/CacheService/"));

总结

在大型网站开发中,缓存是个永远避免不了的话题,也不存在一种方案能解决所有的问题。

而缓存开发过程经常碰到的问题:过期策略(惰性)、缓存更新(独立)、多级缓存、分布 式缓存(分片)、高可用(单点)、高并发(雪崩)、命中率(穿透)、缓存淘汰(LRU)等。

其多级缓存方案的层级关系大都是由浏览器->cdn->反向代理缓存->线程级->内存级->进程级->文件(静态资源)->分布式(redis)->Db结果。

多数内容在LZ前面博文中有过介绍,有兴趣的童鞋可以看看。

参考资源

[1]  http://www.codeproject.com/Articles/7176/Inter-Process-Communication-in-NET-Using-Named-Pip

转载地址:http://hepka.baihongyu.com/

你可能感兴趣的文章
高利率时代的结局,任重道远,前途叵测
查看>>
Debian 6.05安装后乱码
查看>>
欢迎大家观看本人录制的51CTO精彩视频课程!
查看>>
IntelliJ IDEA中设置忽略@param注释中的参数与方法中的参数列表不一致的检查
查看>>
关于软件开发的一些感悟
查看>>
uva 10806
查看>>
纯CSS3绘制的黑色图标按钮组合
查看>>
Linux中环境变量文件及配置
查看>>
从0开始学Flutter
查看>>
mysql操作入门基础之对数据库和表的增删改查
查看>>
IIS负载均衡
查看>>
分布式事务,EventBus 解决方案:CAP【中文文档】
查看>>
Linux下的CPU性能瓶颈分析案例
查看>>
spring mvc入门
查看>>
2012在数据库技术会议上的讲话PPT打包
查看>>
【Android】 TextView设置个别字体样式
查看>>
python svn
查看>>
raise语句
查看>>
sequence2(高精度dp)
查看>>
ABP实战--集成Ladp/AD认证
查看>>