发表于: 2021-09-25 20:28:24
1 1201
一,今天完成的事情
任务六
1,Redis我自己用的安全策略。
调试的时候,能在我的本地windows利用Redis Desktop Manager查看远程,帮助调试。但是只是需要用这个本地工具的时候开放。
本来Redis是没有密码的,一般安装后就设置密码。
平时不对公网开放。包括在阿里云移走Redis等不希望公开的端口。
2,缓存击穿防止代码
我的项目没有用bloom filter,项目六就不加这个代码了。但是我测试了一个容易让人理解的方式。打开我本地的Redis演示。RedisConfigTest这个测试类中具体代码如下:
@Test
public void avoidCBExcStudentsTest(){
//避免缓存击穿是否生效设置
ExcellentStudent student12 = null;
String key = "student12";
long id = 12L;
boolean hasKey = redisTemplate.hasKey(key);
if( hasKey ){
student12 = (ExcellentStudent) redisTemplate.opsForValue().get(key);
System.out.println("------query student12 from Redis --------");
}else{
student12 =
excellentStudentDao.queryById(id);
if( null == student12 ) {
//防止为空的总是查询
redisTemplate.opsForValue().set( key, null);
System.out.println("------setting student null --------");
} else{
redisTemplate.opsForValue().set(key, student12);
System.out.println("------setting student not null --------");
}
}
if( null == student12) {
System.out.println( "----Student 12 name : null ----------");
}
}
ID为12的记录是不存在的,运行成功。第一次打印出来的情况如下:
之后运行成功,如我所想,设置一个key,Redis取出,不要数据库取出。
所以,防止cache breakdown这样已经可以。可以配合设置缓存存在时间,甚至把值为null的缓存设置的expire的时间不同,让Redis利用更合理。
3,AOP打印代码运行的耗时时间。
首先打印service,就exc stu的返回列表然后用在Jsp;对比返回json,不带图片的。
service层。网络带宽一般的时候,锅都应该在传输前端各种大文件,不是数据库,包括NoSQL性能不好。
pom.xml中加入
<!--AOP相关jar包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
spring-mvc.xml中加入
<!--包含切面类的包-->
<context:component-scan base-package="com.nicole.tileslogin.aspectj"/>
<aop:aspectj-autoproxy/>
package com.nicole.tileslogin.aspectj;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.apache.log4j.Logger;
@Aspect
@Component
public class TilesLoginRedisAspect {
private final static Logger logger = Logger.getLogger(TilesLoginRedisAspect.class);
// private final static Logger logger = LoggerFactory.getLogger(ArtAspect.class);
/**
* 定义切入点所有service,完成service计时要求
*/
@Pointcut("execution(* com.nicole.tileslogin.service.*Service.*(..))")
private void logRecordServiceTime(){};
/**
* 定义切入点,记录入参,返回值。选择记录controller,如果还要记录service
*"execution(* com.nicole.ssm.controller.*Controller.*(..)) ||
* execution(* com.nicole.ssm.service.*Service.*(..))"
*/
@Pointcut("execution(* com.nicole.tileslogin.controller.*Controller.*(..))")
private void logRecordArgs(){};
/**
* around所有service,完成service计时要求
*/
@Around("logRecordServiceTime()")
public Object around(ProceedingJoinPoint joinPoint) {
String fullMethodName = joinPoint.getSignature().toString();
logger.info("Method Name : [" + fullMethodName + "] ---> AOP around Service Time start");
long startTimeMillis = System.currentTimeMillis();
// proceed() 执行符合pointcut定义的方法
Object result = null;
try {
result = joinPoint.proceed();
} catch (Throwable throwable) {
logger.error("error : "+throwable.getMessage());
}
long execTimeMillis = System.currentTimeMillis() - startTimeMillis;
logger.info("method name : [" + fullMethodName + "] ---> uses time : " + execTimeMillis+"ms");
return result;
}
/**
* 定义切入点,记录入参,返回值。选择记录controller入参和返回值
*/
@Around("logRecordArgs()")
private Object getControllerLog(ProceedingJoinPoint jPoint) {
//return val, package name, class name, method name
String fullMethodName = jPoint.getSignature().toString();
StringBuilder sb = new StringBuilder();
// 下面两个数组中,参数值和参数名的个数和位置是一一对应的。
// 参数值
Object[] argsVal = jPoint.getArgs();
// 参数名
String[] paramsName = ((MethodSignature) jPoint.getSignature()).getParameterNames();
sb.append( fullMethodName ).append( " parameter(s) are : { ");
if( argsVal != null && paramsName != null && argsVal.length > 0 && paramsName.length > 0 ) {
for (int i = 0 ; i < paramsName.length ; i++ ) {
sb.append(" ").append( paramsName[i] ).append(" = ")
.append(argsVal[i]).append(",");
}
sb.deleteCharAt(sb.length()-1);
}
sb.append(" } ");
Object result = null;
try {
result = jPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
logger.error("error message : "+throwable.getMessage());
}
sb.append(" return (result) :{ ").append(result).append(" } ");
// 记录日志
logger.info(sb.toString());
// 调用结果返回
return result;
}
}
有Redis
第一次要各种访问,连接。
第二次访问后。
无Redis。第一次也要各种访问,连接。
4,sql在数据库中直接看耗时,其实就是只看dao层,那就直接在mysql用同样的命令查询一遍。如果是远程,我的网页图片不少,大量消耗在网络传送图片很正常。
在一个条目不多的表,找一个,几个,不是问题。
----------------------------------------------
任务六深度思考和答案
1,Load balancing,即负载均衡,是一种计算机技术,用来在多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。
2,如果用户是直连到 web 服务器,如果这个服务器宕机了,那么用户自然也就没办法访问了。另外,如果同时有很多用户试图访问服务器,超过了其能处理的极限,就会出现加载速度缓慢或根本无法连接的情况。
1)如果加入一个负载均衡器和至少一个额外的 web 服务器,可以缓解这个故障。解决并发压力,提高应用处理性能(增加吞吐量,加强网络处理能力)。用多台普通处理器代替单台高配置处理器,一般更便宜。
2)提供故障转移,实现高可用:有多台服务器可选,允许集群中少量处理器停机。
3)通过添加或减少服务器数量,提供网站伸缩性(扩展性)。根据需求增减处理器,哪里需要哪里搬。
4)负载均衡处理器做此层安全防护,在负载均衡设备上做一些过滤,黑白名单等处理。
2.为什么要使用memcache?memcache有什么作用?
前提希望说的一个知识:memcache 是一个原生版本,完全是在 PHP 框架内开发的,支持 OO(面向对象) 和非 OO 两套接口并存,而 memcached 是建立在 libmemcached 的基础上的,只支持 OO 接口。这就意味着在安装 memcache 扩展的时候不要求安装其他的东西,但是在安装 memcached 的时候会要求你安装 libmemcached。
因为 libmemcached 是 memcache 的 C 客户端,它具有低内存,线程安全等优点。memcached,在高并发下,稳定性果断提高。
1,使用memcache作为缓存,缓解关系型数据库的压力。提高网站访问速度,通过在内存中缓存数据和对象来减少读取数据库的次数。
2,在内存中存储数据,防止高并发影响数据库性能,减少数据库压力,并提高查询速度。
3.后台只允许有列表页和详情页,列表页分为搜索区和列表区和操作区,原因是什么?有没有其他设计方式,相比之下各自的好处是什么?
一般看到后台的前端,第一感觉是丑,继续看理工科会觉得简洁,没有浪费的东西。
1,后台只允许有列表页和详情页:这是一个结论。展示列表优。
详情页能够获取最详细的信息。从列表看到标题再进入详细看。
2,列表页分为搜索区和列表区和操作区:列表页至少有这3个区。
列表区:后台系统的用户希望列表的内容又多又全面。
搜索区,包含筛选:在操作时又能支持快速定位。
操作区:准确处理。
3,列表页建议至少有题干中的3个部分。不存在「最好」的通用方案,只有应对具体需求「最合适」的解决方案。其它设计方案:如果更复杂的还有 “导航区”和“分页”等。
加入导航区,配合列表,把不同列表进一步分类。多分层,每层内容少,根据分类看更快。避免内容太多导致的认知负担和操作成本。隐藏低优先级信息,需要的时候才允许他们出现。
如果内容多,需要再分页。
转换信息呈现的形式。
比如1)允许用户配置表头项,隐藏暂不需要的内容。
2)使用展开行。适合主次层级对比强烈的列表。将重要度低的内容放入展开行内,这样可以避免横向滑动。
3)树形数据。可以将一组有父子关系的数据聚合呈现。
4)使用图像代替文字。图像比文字在信息传递上更直观。
4.什么叫集群?缓存应该在什么情况下使用集群?有哪些实现集群的方案?
1,计算机集群(cluster)指一些松散的计算机系统,通过告诉网络连接,协同工作。集群对用户来说就像单台计算机系统,只不过是有更高的性能和更高的可靠性。集群中的每台计算机叫做节点。
2,缓存集群缓解数据库压力。应对不定时突然的大流量,比如容易出现不定期的热点情况,同时数据量比较大,用户访问频繁。可预期范围内短时间内高速大量访问的需求,每天定时推送给终端客户信息,有可能需要在极短时间内的高QPS数据的查询。如果一台不够用,能力不足,使用集群,甚至添加更多层次。
其它集群使用场景:后端负载均衡。数据库。
3,实现集群的方案:看业务类型。
1)前端。考虑群集的健康监控,负载算法平衡。2)资源类型的业务,可以有分布式存储,对象存储这类解决方案。单纯内网小规模业务可以用samba共享这样的存储共享方式实现。3)数据库,可以用数据存储实现数据一致和安全。也可以通过数据库群集项目实现多节点的数据同步。
集群之前需要解决通信问题。
任务六通过代理(nginx)的 upstream实现集群。
客户端分片:客户端分片是把分片的逻辑放在Redis客户端实现,通过Redis客户端预先定义好的路由规则,把对Key的访问转发到不同的Redis实例中,最后把返回结果汇集。
5.什么是压测,为什么要进行压力测试?JMETER工具的使用
1,在软件测试中:压力测试(Stress Test),也称为强度测试、负载测试。压力测试是模拟实际应用的软硬件环境及用户使用过程的系统负荷,长时间或超大负荷地运行测试软件,来测试被测系统的性能、可靠性、稳定性等。考察当前软硬件环境下系统所能承受的最大负荷并帮助找出系统瓶颈所在。可以模拟巨大的工作负荷以查看应用程序在峰值使用情况下如何执行操作。
2,目的是在软件投入使用以前或软件负载达到极限以前,通过执行可重复的负载测试,了解系统可靠性、性能瓶颈等,以提高软件系统的可靠性、稳定性,减少系统的宕机时间和因此带来的损失。
测试应用的抗压能力,预估应用的承载能力,为后面的运维提供扩容的依据。
3,用JMeter 来测试 Restful API方便。JMeter 开源免费。
6.Memcache和Redis可否做集群?什么样的情况下应该做集群?
1,可以。单台能做的,都可以扩展成集群。
2,一台做一件事经过评估干不了。规模大到一定程度。
7.什么是脏数据,缓存中是否可能产生脏数据,如果出现脏数据该怎么处理?
1,脏数据(Dirty data),通常是指跟期待的数据不一样、会影响系统正常行为的数据。Dirty data, also known as rogue data, are inaccurate, incomplete or inconsistent data, especially in a computer system or database. Dirty data can contain such mistakes as spelling or punctuation errors, incorrect data associated with a field, incomplete or outdated data, or even data that has been duplicated in the database.
2,缓存中可能产生脏数据。缓存也是数据库,数据库就可能产生脏数据。
3,数据科学中“脏数据”分类以及处理方法
1)数据缺失:缺一些记录,或者一条记录里缺一些值(空值),或者两者都缺。原因可能有很多种,系统导致的或人为导致的可能性都存在。如果有空值,为了不影响分析的准确性,要么不将空值纳入分析范围,要么进行补值。前者会减少分析的样本量,后者需要根据分析的计算逻辑,选择用平均数、零、或者等比例随机数等来填补。如果是缺一些记录,若业务系统中还有这些记录,则通过系统再次导入,若业务系统也没有这些记录了,只能手工补录或者放弃。
2)数据重复:相同的记录出现多条,这种情况相对好处理,去掉重复记录即可。但是怕就怕不完全重复,比如两条会员记录,其余值都一样,就是住址不一样,这就麻烦了,有时间属性的还能判断以新值为准,没有时间属性的就无从下手了,只能人工判断处理。
3)数据错误:数据没有严格按照规范记录。比如异常值,价格区间明明是100以内,偏偏有价格=200的记录;比如格式错误,日期格式录成了字符串;比如数据不统一,有的记录叫北京,有的叫BJ,有的叫beijing。对于异常值,可以通过区间限定来发现并排除;对于格式错误,需要从系统级别找原因;对于数据不统一,系统无能为力,因为它并不是真正的“错误”,系统并不知道BJ和beijing是同一事物,只能人工干预,做一张清洗规则表,给出匹配关系,第一列是原始值,第二列是清洗值,用规则表去关联原始表,用清洗值做分析,再好一些的通过近似值算法自动发现可能不统一的数据。
4)数据不可用:数据正确,但不可用。比如地址写成“北京海淀中关村”,想分析“区”级别的区域时还要把“海淀”拆出来才能用。这种情况最好从源头解决,即数据治理。事后补救只能通过关键词匹配,且不一定能全部解决。
4,对于一般的计算机科学,处理脏数据:数据要遵守到第三范式。通过加写锁等方式,首先避免读到脏数据。如果数据先后顺序逻辑联系紧密,宁愿不并发处理,等到前数据处理好再处理后面的数据。
如果确认是脏数据,尽快把脏数据删除,导入正确数据。
8.插入,更新和查询数据的时候,读写缓存和DB的顺序应该是怎么样的?
一般回答是:
1,新数据插入DB。没查询前根据算法判定是否放入缓存。
2,更新DB。先判断缓存值是否为空,为空直接将DB的数据添加到缓存。缓存已经存在的情况,检查DB和缓存的值是否相等,相等不进行操作,不相等进行更新缓存中数据的操作。
3,查询:先查询缓存值,判断是否为空,不为空,直接返回缓存的值。为空,去DB查询值添加到缓存当中。
LRU常用。这道题正好没问删除。
9.JVM缓存和Memcache这种缓存的区别在哪里?是否可以不使用Memcache,只用虚拟机内存做缓存?
1,jvm的缓存用ehcache或者OSCache;没有IO开销会有更高的效率,使用起来也更加灵活。Memcache是IO级别的缓存。
2,Memcache的相当于在jvm进程外,是一个独立的内存区。
3,jvm的缓存ehcache,可以通过java命令运行jar包使用。
4,jvm的缓存不能在多个应用不能被你的集群共享,造成内存的浪费,适用于不需要集群的小型应用,只用jvm就能单打独斗。Memcache 独立的缓存,可以被集群或者多个应用共享,大一些的应用可以考虑加入Memcache,Redis等IO缓存。
5,OSCache或者EHCache常用于服务器本地缓存,直接使用适合单个应用进程存取。如果开了多个进程或部署多台服务器的话,每个进程只能访问本地的缓存,如果需要缓存同步,需要写相关的同步代码。ehcache还支持RMI、JGroups、JMS的分布式缓存,就不需要手写同步代码了,还可以搭建单独的EhCache Server,这种情况就跟Memcache差不多了。
Memcache缓存是单独的进程,好处是使用进程之间少了缓存同步,因为数据在Memcache上只有一份,而不是ehcache在每个进程上都有一份;但访问需要进程间通信,多了通信的开销。
10.缓存应该在Service里,还是应该存放在Controller里,为什么?
MVC引入SERVICE层为了提高代码重用性,沟通CONTROL和MODEL。
我采取的方案是只在一个层面上提供 cache 功能,其它的层面都不提供,以避免其复杂性并且降低耦合性。所以需要只在Service写有关数据库,所以包括Cache的功能。写入各种不同数据库操作的可重用逻辑,为controller提供服务,针对的逻辑更单一,但是比DAO层更进一步。
如果觉得是后续长时间逻辑不变cache数据,考虑写在controller。复杂处理的逻辑。
11.什么叫穿透DB?什么情况下会发生,穿透DB后会发生什么事情?
1,定义:缓存穿透指的是用户查询数据,在数据库中没有,自然在缓存中也没有,每次查询都是两次无意义的查询,也是绕过缓存,直接查数据库的。所以,“透,穿”过了缓存,到了希望被缓存保护的数据库层。
2,比如,有人用数据库中不存在的某个key访问,数据库中没有该key值,自然缓存中也不会有,该请求会直接到数据库。如果对该key的并发访问量过大,则会压垮数据库。
3,结果:高频率的穿透到数据库,数据处理不过来就崩了。
4,多说一点解决方案:
1)采用过滤器,把所有数据库中不可能存在的数据hash到一张大的bitmap中,如果key在数据库中不存在,将会被bitmap拦截。
2)对查出为空的key,也在缓存中建立key value对,只是过期时间设的短一点,比如5minetes。
1,命中:可以直接通过缓存获取到需要的数据。
不命中:无法直接通过缓存获取到想要的数据,需要再次查询数据库或者执行其它的操作。原因可能是由于缓存中根本不存在,或者缓存已经过期。
命中率=命中数/(命中数+没有命中数)
比如在memcached中,运行state命令可以查看memcached服务的状态信息,其中cmd_get表示总的get次数,get_hits表示get的总命中次数,命中率 = get_hits/cmd_get。
2,缓存命中率越高越好,能根据历史数据控制更高更好。如果超过50%,就等于挡住了超过50%的数据库新查询。
1,适合存在缓存中的数据:很少被修改的数据。不是会对运算结果产生重要影响的数据,此时允许出现偶尔并发。不会被并发访问的数据。参考数据,不保证真实。只有单一应用使用的数据。数据量不是很大。
特别要提的:很明显就是热点的数据(谁谁结婚等文字内容更新内容频率不是很高)。访问频率高。
2,缓存的淘汰算法,只说常用。前两名排名不分先后。
1)LFU(Least Frequently Used)
根据数据的历史访问频率来淘汰数据,其核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”。
2)LRU(LeastRecently User)
根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
3)LRU-K(LeastRecently Used K)
相比LRU,LRU-K需要多维护一个队列,用于记录所有缓存数据被访问的历史。只有当数据的访问次数达到K次的时候,才将数据放入缓存。当需要淘汰数据时,LRU-K会淘汰第K次访问时间距当前时间最大的数据。
4)FIFO(First in First out)
最先进入的数据,最先被淘汰。一个很简单的算法。只要使用队列数据结构即可实现。那么FIFO淘汰算法基于的思想是”最近刚访问的,将来访问的可能性比较大”
5)2Q(Two Queues)
同样也是为了解决LRU算法的缓存污染问题。类似于LRU-2,不同点在于2Q将LRU-2算法中的访问历史队列改为一个FIFO缓存队列,即:2Q算法有两个缓存队列,一个是FIFO队列,一个是LRU队列。
当数据第一次访问时,2Q算法将数据缓存在FIFO队列里面,当数据第二次被访问时,则将数据从FIFO队列移到LRU队列里面,两个队列各自按照自己的方法淘汰数据。
1,一致性hash是一种算法,为了解决简单哈希函数“在节点数量动态变化的情况下会造成大量的数据迁移,导致网络通信压力的剧增,严重情况,还可能导致数据库宕机。”。 一定要用哈希算法:对于分布式存储,不同机器上存储不同对象的数据,使用哈希函数建立从数据到服务器之间的映射关系。
2,一致性哈希的提出就是为了解决分布式Cache如何分配任务的问题。分布式cache包括Memcache和Redis。它可以保证当机器增加或者减少时,节点之间的数据迁移只限于两个节点之间,不会造成全局的网络问题。一致性哈希算法具体采用环形Hash空间, 将数据通过hash算法映射到环上,将机器通过hash算法映射到环上来分配任务到相应的机器上。
15.缓存的失效策略有哪几种,分别适合什么场景?
1,没有完美的方案,只有契合场景的更适合的方案。问题13的答案包含淘汰算法,也是这道题问的失效策略。
2,在这个问题加上适用场景。
1)LFU(Least Frequently Used)
缓存算法。LFU作为负载均衡算法:保证每次使用都是最不经常使用的节点。
2)LRU(LeastRecently User)
缓存类:底层的内存管理,页面置换算法。一般的缓存服务,memcache\redis之类。
也可以作为负载均衡的算法 ,每次使用了每个节点的时候,就将该节点放置在最后面(做缓存时 放在前面),这样就保证每次使用的节点都是最近最久没有使用过的节点。
3)LRU-K(LeastRecently Used K)
同2)。
4)FIFO
适合用于数据的缓冲。按进入顺序。
1,支持数据类型不同:Redis相对Memcached支持更多的数据类型。Redis支持简单的k/v类型的数据,提供list,set,zset,hash等数据结构的存储。
2,内存管理机制不同:Memcache使用slab allocator机制来内存管理。Redis底层实现通过对malloc/free进行封装来实现,通过存储数据的size,来申请一段连续的内存空间
3,数据存储及持久化:
Redis支持持久化,可以保存到硬盘上。Memcache原始不支持持久化。掉电即失,可靠性差,用于动态系统中减轻数据库负载,提升性能。做缓存,适合多读少写,大数据量的情况,比如浏览非动态文章信息。
4,集群管理。
Memcache不支持集群,只能用客户端通过哈希算法实现分布式。
Redis支持分布式。可靠性高,适用于对读写效率要求都很高,数据处理业务复杂和对安全性要求较高的系统。
5,Redis支持数据的备份,即master-slave模式的数据备份。
一般日活数指分析日均活跃用户数量(Daily Active User,DAU)。通过压力测试,测试系统能够运转,拟定一个错误率,不超过那个错误率的QPS,TPS等数据。预估每个客户访问次数。=每天的总访问率/每个客户每天访问次数 ,少一点,算90%,大约就是系统可以承载的日活数。
18.什么是JMeter?Jmeter是否可以在多台机器上分布式部署?为什么要分布式部署?
1,JMeter是用于测试客户端/服务端结构的软件(例如web应用程序)。它可以用来测试静态和动态资源的性能。JMeter可用于模拟大量负载来测试一台服务器,网络或者对象的健壮性或者分析不同负载下的整体性能。
2,Jmeter可以在多台机器上分布式部署。
3,压力测试单独一台机器也会不够用。受制于客户机的性能。可能由于网络带宽,CPU,内存的限制不能给到服务器足够的压力,这个时候你就需要用到分布式方案来解决客户机的瓶颈,压测的结果也会更加接近于真实情况。
19.什么是TPS,什么是每秒并发数,什么是90%Line?分别应该到达多少算符合系统上线的要求?
1,每秒事务处理量 TPS是Transaction per Second的缩写,也就是事务数/秒。它是软件测试结果的测量单位,一个事务是指一个客户机向服务器发送请求后服务器做出反应的过程。客户端在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。
2,并发数是指系统同时能处理的请求数量,这个也反应了系统的负载能力。每秒并发数是指1s内系统同时能处理的请求数量。
3,90%Line就是一组数按照由小到大进行排列,找到他的第90%个数P,那么这个数组中有90%的数将小于等于P,(100%-90%=10%)的数大于等于P。90%Line在性能测试的响应时间非常有意义,用来表示90%用户响应时间不会超过P秒。所以,如果一组数据从小到大进行排列,第90%的数假如是2s,将有90%的数小于2s。
4,分别应该到达多少算符合系统上线的要求:TPS 100。每秒并发数100。90%Line 200ms。这是希望达到的值。
---------------------------------------
任务六小结:
任务六首先要求测试,告知需要使用的工具是JMeter。查看TPS,90%Line等等。
使用NoSQL。要求的是Memcache和Redis。比较使用NoSQL和不使用的区别。
做到Nginx的Upstream,对upstream还有相关参数有概念。
问题,困惑,疑难:
Redis的设计理念更先进。格式使用,格式转换,多看源码。
二,今天问题
中国联通最近向部分客户发短信询问,知道“三千兆光纤”吗?现在光纤入户。三千兆也准备在三大运营商中强势出击。如果是公司,三千兆的光纤不算什么,而且上下行还很可能是同速。但是现在是走向千家万户的家用网络。计算机相关提升效率是各种维度的,computer engineering 和 CS 还有 EE 就没有那么大的差别,折中。EE和物理的某些方向也没差很远。
三,今天的收获
网页图片不少,大量消耗在网络传送图片很正常。
bloom filter。要好好背八股问答题,觉得基本都能理解。
如果是远程,我的网页图片不少,大量消耗在网络传送图片等前端资源很正常。
漂亮的网页,漂亮的网站。
四,明天的计划
任务7
评论