• 关于 信息率问题怎么解决 的搜索结果

回答

在1024*768或者800*600的分辨率下可以自动调整成适用于该客户端分辨率的大小。 第一种方法:做一个网页解决问题(长了点) 如果只是因为浏览者改变了浏览器的设置,或者因为浏览器不兼容,使自己精心制作的网页变得"面目全非",那多令人沮丧!下面我们以网页爱好者的常用工具Dreamweaver(以下简称DW)为例,列出几个网页制作初学者较常见的网页布局问题以及解决方法,希望对初学者们有所帮助。 一、消除任意缩放浏览器窗口对网页的影响 一番辛苦做出来的网页,在全屏状态下浏览一切正常。但在改变浏览窗口大小之后,网页就变得"不堪入目"了,这是个很值得注意的问题。 问题的根源还得从网页的布局说起,在DW中,网页内容的定位一般是通过表格来实现的,解决表格的问题也就成功了大半。 大家应该注意到,在DW中表格属性面板的高宽设定选择上提供了两种不同类型:百分比和像素值。百分比的使用将会产生前面说到的那个毛病。这里所说的百分比是指表格的高或宽设置为上层标记所占区域高或宽的百分比,如在一个表格单元的宽度是600,在它里面嵌入了另外一个表格,表格宽度占表格单元的50%,则这个表格的宽度为300,依此类推,如果在一个表格不是嵌于另一个表格单元中,则其百分比是相对于当时窗口的宽度的。IE浏览器中,随便改动主页窗口的大小时,表格的内容也随之错位、变形,就是因为表格的百分比也要随着窗口的大小而改变成相应的百分比宽度。 自然,解决这个问题的办法就是将表格宽度设置成固定宽度(也就是像素值)。另外如果外层表格已做好固定宽度设置,内层表格也可以适当使用百分比设置。清楚这个原则以后,如果出现类似的问题大家也知道怎么解决。 二、让网页居中 说到了窗口大小就会顺着路子想到分辨率的问题,在800×600分辨率下制作的网页在1024×768分辨率的机器上打开,整个网页就会跑到左边;1024×768分辨率的网页在800×600分辨率的机器上有时也会变得"不堪入目"。两种分辨率各做一个吧?做起来费时,看起来也费劲。怎么办呢? 现在大多数网民都还在用800*600的分辨率,所以我们一般可以以此分辨率为主,要想让网页在1024*768时居中,只要在网页原代码的<body>后紧加一句<center>,</body>前加一句</center>就OK了。不过有几个问题这是要注意一下,第一个就是上面说到的百分比的问题,表格、单元格的宽度单位最好要使用像素单位,而不要用百分比。例如width=770。如果你的表格宽度设的是百分比,那么使用大于800×600的像素时,网页就会拉宽,这样网页可能会变形。在<body>中加入leftmargin=0,即<body leftmargin=0>这种情况下,800×600支持的表格宽度为780像素时不会出现滚动条。还有一点要注意的是不能用DW中的层来定位。 以下是引用片段: <html> <head></head> <body topmargin=0 leftmargin=0> <center> <table cellspacing cellpadding width=760><tr><td></td></tr></table> </center> </body> </html> 三、定义固定大小的文字 大家都知道,在IE浏览器的功能设置中,有一个可以自由设置窗口内容字体大小的功能,这样由于不同访问者的设置习惯不同,呈现在他们面前的网页有时也会不不相同。比如你可能本来设计时用的是2号字体,结果由于用户对浏览器的额外设定,变的更大了,这时你的网页也可能变得"不堪入目"。虽然不是你的错,但客户是上帝。 如果使用了网页中的CSS样式表技术,就不会出现上述情况了。使用快捷键"Shift+F11"打开样式表"CSS style"编辑器,在窗口中单击鼠标右键执行"New CSS style..."命令新建一个样式表,然后在给出的列表中选择"类型"选项,定义文字属性参数(一般文字的大小选择12px较为适宜)。完成后选择网页编辑窗中的文本,单击新的样式表名称,可以看到选中的文本发生了变化。预览时试试定义的文本字体尺寸还会不会随浏览器的选择字体大小而改变。 四、让网页适应不同的浏览器 浏览器的格局现在是两分天下,一分是IE,另一分是NetScape,在国内Ie有绝对的占有率,在这种情况下我们设计的网页只要兼容它就行了,但NetScape在国外还是有很多人使用,毕竟它是浏览器的元老。 虽然没有办法做出让所有浏览器都兼容的网站,但只要注意以下几点,做出来的网页在各个浏览器都中能达到比较好的显示效果: 不要混合使用层和表格排版,如果是父子关系,如层中表格,不在此原则范围内。 内联式的 CSS 在 Netscape Navigator 中经常会出现问题,使用链式或内嵌式。 有时需要在空层插入表格或者透明图片,以保证在 Netscape Navigator 里的效果。 对于只有几个像素宽度或高度的层,改用图片来实现。 避免使用 W3C 组织不推荐的排版属性,用 CSS 代替。 第二种方法:做两个适合不同分辨率的页面,一个是800×600,一个是1024×768,在800×600的页面中加入一下代码就可以实现跳转了: 解决分辨率问题在Dreamweaver中没有此项功能,我们只能手动加入一段Javascript代码。首先在change-ie.html或change-nc.html页面代码中的< head>和< /head>中加入以下代码: 以下是引用片段: < script language=JavaScript> < !-- function redirectPage(){ var url800x600=〃index-ie.html〃; //定义两个页面,此处假设index-ex.html和1024-ie.html同change-ie.html在同一个目录下 var url1024x768=〃1024-ie.html〃; if ((screen.width==800) && (screen.height==600)) //在此处添加screen.width、screen.height的值可以检测更多的分辨率 window.location.href= url800x600; else if ((screen.width==1024) && (screen.height==768)) window.location.href=url1024x768; else window.location.href=url800x600; } // --> < /script> 然后再在< body…>内加入onLoad=〃redirectPage()〃 最后,同样地,在< body>和< /body>之间加入以下代码来显示网页的工作信息: 以下是引用片段: < script language=JavaScript> < !-- var w=screen.width var h=screen.height document.write(〃系统已检测到您的分辨率为:〃); document.write(〃< font size=3 color=red>〃); document.write(w+〃×〃+h); document.write(〃< /font>〃); document.write(〃正在进入页面转换,请稍候…〃); // --> < /script> 答案来源网络,供参考,希望对您有帮助

问问小秘 2019-12-02 03:01:07 0 浏览量 回答数 0

回答

回4楼vinning的帖子 嗯,关于曝光率是这样的,我把它作为公司邮箱,放在网站上。目前又把他上升至业务邮箱,很多重要信息。难免会受到黑客的攻击,只是怎样才能保证到密码不被盗?及时丢失密码后还能找回?阿里云没有二次验证功能吗? ------------------------- 回6楼vinning的帖子 还有一个问题,出现将近有2个月了,我同时拥有阿里云的账号和阿里云邮箱的账号。每次登录的时候都使用360浏览器,阿里云账号输入登录邮箱密码就能直接登录了,而阿里云邮箱输入正确地邮箱和密码后,又跳转到登录页面,在第二次输入同样的账号和密码后才能够正真登入,不知道这样的现象是怎么产生的?我查了电脑,没有木马,会不会是有人利用第一次的登录存储我的邮箱账号和密码呢?很是疑惑,阿里云账号只登录一次,而阿里云邮箱要登录2次才能进入。 ------------------------- 回6楼vinning的帖子 此外,我在使用中还有一个问题。我在使用网页版的阿里云邮箱同时,还在iphone手机上下载了阿里云手机客户端,我发现一个很特别的问题。3月期间,我在网页版的邮箱里修改了大约3-4次密码,但是一点也不影响手机客户端接收邮件,但是会影响foxmail终端的接收,也就是说,网页上修改密码后,客户端还是会收到邮件,而foxmail里就接收不了了,这是怎么回事?漏洞?这种情况同样适用到gmail邮箱吗?hotmail邮箱? ------------------------- 回9楼vinning的帖子 7楼我问到的问题,怎么解决呢? ------------------------- 回11楼vinning的帖子 好的,我私信你。 ------------------------- 回13楼vinning的帖子 广州登录 加拿大登录 刚才我登录邮箱看历史明细里,仍旧还有异地SWTP发信失败的状态,我应该怎么处理这种情况? ------------------------- 回15楼vinning的帖子 我3月初就将这个功能禁用了,怎么还会出现这个问题呢?

冬瓜苗苗 2019-12-02 01:55:56 0 浏览量 回答数 0

问题

关于备案信息问题,有经验的大佬们能告诉我该怎么办?

skyole 2019-12-01 20:27:57 9736 浏览量 回答数 8

新用户福利专场,云服务器ECS低至96.9元/年

新用户福利专场,云服务器ECS低至96.9元/年

问题

【精品问答集锦】关于“网站打不开”热门问题收集

zuntop_com 2019-12-01 19:55:41 38 浏览量 回答数 1

问题

HBase 优化实战

pandacats 2019-12-20 21:12:25 0 浏览量 回答数 0

回答

在开始谈我对架构本质的理解之前,先谈谈对今天技术沙龙主题的个人见解,千万级规模的网站感觉数量级是非常大的,对这个数量级我们战略上 要重 视 它 , 战术上又 要 藐 视 它。先举个例子感受一下千万级到底是什么数量级?现在很流行的优步(Uber),从媒体公布的信息看,它每天接单量平均在百万左右, 假如每天有10个小时的服务时间,平均QPS只有30左右。对于一个后台服务器,单机的平均QPS可以到达800-1000,单独看写的业务量很简单 。为什么我们又不能说轻视它?第一,我们看它的数据存储,每天一百万的话,一年数据量的规模是多少?其次,刚才说的订单量,每一个订单要推送给附近的司机、司机要并发抢单,后面业务场景的访问量往往是前者的上百倍,轻松就超过上亿级别了。 今天我想从架构的本质谈起之后,希望大家理解在做一些建构设计的时候,它的出发点以及它解决的问题是什么。 架构,刚开始的解释是我从知乎上看到的。什么是架构?有人讲, 说架构并不是一 个很 悬 乎的 东西 , 实际 上就是一个架子 , 放一些 业务 和算法,跟我们的生活中的晾衣架很像。更抽象一点,说架构其 实 是 对 我 们 重复性业务 的抽象和我 们 未来 业务 拓展的前瞻,强调过去的经验和你对整个行业的预见。 我们要想做一个架构的话需要哪些能力?我觉得最重要的是架构师一个最重要的能力就是你要有 战 略分解能力。这个怎么来看呢: 第一,你必须要有抽象的能力,抽象的能力最基本就是去重,去重在整个架构中体现在方方面面,从定义一个函数,到定义一个类,到提供的一个服务,以及模板,背后都是要去重提高可复用率。 第二, 分类能力。做软件需要做对象的解耦,要定义对象的属性和方法,做分布式系统的时候要做服务的拆分和模块化,要定义服务的接口和规范。 第三, 算法(性能),它的价值体现在提升系统的性能,所有性能的提升,最终都会落到CPU,内存,IO和网络这4大块上。 这一页PPT举了一些例子来更深入的理解常见技术背后的架构理念。 第一个例子,在分布式系统我们会做 MySQL分 库 分表,我们要从不同的库和表中读取数据,这样的抽象最直观就是使用模板,因为绝大多数SQL语义是相同的,除了路由到哪个库哪个表,如果不使用Proxy中间件,模板就是性价比最高的方法。 第二看一下加速网络的CDN,它是做速度方面的性能提升,刚才我们也提到从CPU、内存、IO、网络四个方面来考虑,CDN本质上一个是做网络智能调度优化,另一个是多级缓存优化。 第三个看一下服务化,刚才已经提到了,各个大网站转型过程中一定会做服务化,其实它就是做抽象和做服务的拆分。第四个看一下消息队列,本质上还是做分类,只不过不是两个边际清晰的类,而是把两个边际不清晰的子系统通过队列解构并且异步化。新浪微博整体架构是什么样的 接下我们看一下微博整体架构,到一定量级的系统整个架构都会变成三层,客户端包括WEB、安卓和IOS,这里就不说了。接着还都会有一个接口层, 有三个主要作用: 第一个作用,要做 安全隔离,因为前端节点都是直接和用户交互,需要防范各种恶意攻击; 第二个还充当着一个 流量控制的作用,大家知道,在2014年春节的时候,微信红包,每分钟8亿多次的请求,其实真正到它后台的请求量,只有十万左右的数量级(这里的数据可能不准),剩余的流量在接口层就被挡住了; 第三,我们看对 PC 端和移 动 端的需求不一样的,所以我们可以进行拆分。接口层之后是后台,可以看到微博后台有三大块: 一个是 平台服 务, 第二, 搜索, 第三, 大数据。到了后台的各种服务其实都是处理的数据。 像平台的业务部门,做的就是 数据存储和读 取,对搜索来说做的是 数据的 检 索,对大数据来说是做的数据的 挖掘。微博其实和淘宝是很类似 微博其实和淘宝是很类似的。一般来说,第一代架构,基本上能支撑到用户到 百万 级别,到第二代架构基本能支撑到 千万 级别都没什么问题,当业务规模到 亿级别时,需要第三代的架构。 从 LAMP 的架构到面向服 务 的架构,有几个地方是非常难的,首先不可能在第一代基础上通过简单的修修补补满足用户量快速增长的,同时线上业务又不能停, 这是我们常说的 在 飞 机上 换 引擎的 问题。前两天我有一个朋友问我,说他在内部推行服务化的时候,把一个模块服务化做完了,其他部门就是不接。我建议在做服务化的时候,首先更多是偏向业务的梳理,同时要找准一个很好的切入点,既有架构和服务化上的提升,业务方也要有收益,比如提升性能或者降低维护成本同时升级过程要平滑,建议开始从原子化服务切入,比如基础的用户服务, 基础的短消息服务,基础的推送服务。 第二,就是可 以做无状 态 服 务,后面会详细讲,还有数据量大了后需要做数据Sharding,后面会将。 第三代 架构 要解决的 问题,就是用户量和业务趋于稳步增加(相对爆发期的指数级增长),更多考虑技术框架的稳定性, 提升系统整体的性能,降低成本,还有对整个系统监控的完善和升级。 大型网站的系统架构是如何演变的 我们通过通过数据看一下它的挑战,PV是在10亿级别,QPS在百万,数据量在千亿级别。我们可用性,就是SLA要求4个9,接口响应最多不能超过150毫秒,线上所有的故障必须得在5分钟内解决完。如果说5分钟没处理呢?那会影响你年终的绩效考核。2015年微博DAU已经过亿。我们系统有上百个微服务,每周会有两次的常规上线和不限次数的紧急上线。我们的挑战都一样,就是数据量,bigger and bigger,用户体验是faster and faster,业务是more and more。互联网业务更多是产品体验驱动, 技 术 在 产 品 体验上最有效的贡献 , 就是你的性能 越来越好 。 每次降低加载一个页面的时间,都可以间接的降低这个页面上用户的流失率。微博的技术挑战和正交分解法解析架构 下面看一下 第三代的 架构 图 以及 我 们 怎么用正交分解法 阐 述。 我们可以看到我们从两个维度,横轴和纵轴可以看到。 一个 维 度 是 水平的 分层 拆分,第二从垂直的维度会做拆分。水平的维度从接口层、到服务层到数据存储层。垂直怎么拆分,会用业务架构、技术架构、监控平台、服务治理等等来处理。我相信到第二代的时候很多架构已经有了业务架构和技术架构的拆分。我们看一下, 接口层有feed、用户关系、通讯接口;服务层,SOA里有基层服务、原子服务和组合服务,在微博我们只有原子服务和组合服务。原子服务不依赖于任何其他服务,组合服务由几个原子服务和自己的业务逻辑构建而成 ,资源层负责海量数据的存储(后面例子会详细讲)。技 术框架解决 独立于 业务 的海量高并发场景下的技术难题,由众多的技术组件共同构建而成 。在接口层,微博使用JERSY框架,帮助你做参数的解析,参数的验证,序列化和反序列化;资源层,主要是缓存、DB相关的各类组件,比如Cache组件和对象库组件。监 控平台和服 务 治理 , 完成系统服务的像素级监控,对分布式系统做提前诊断、预警以及治理。包含了SLA规则的制定、服务监控、服务调用链监控、流量监控、错误异常监控、线上灰度发布上线系统、线上扩容缩容调度系统等。 下面我们讲一下常见的设计原则。 第一个,首先是系统架构三个利器: 一个, 我 们 RPC 服 务组 件 (这里不讲了), 第二个,我们 消息中 间 件 。消息中间件起的作用:可以把两个模块之间的交互异步化,其次可以把不均匀请求流量输出为匀速的输出流量,所以说消息中间件 异步化 解耦 和流量削峰的利器。 第三个是配置管理,它是 代码级灰度发布以及 保障系统降级的利器。 第二个 , 无状态 , 接口 层 最重要的就是无状 态。我们在电商网站购物,在这个过程中很多情况下是有状态的,比如我浏览了哪些商品,为什么大家又常说接口层是无状态的,其实我们把状态从接口层剥离到了数据层。像用户在电商网站购物,选了几件商品,到了哪一步,接口无状态后,状态要么放在缓存中,要么放在数据库中, 其 实 它并不是没有状 态 , 只是在 这 个 过 程中我 们 要把一些有状 态 的 东 西抽离出来 到了数据层。 第三个, 数据 层 比服 务层 更需要 设计,这是一条非常重要的经验。对于服务层来说,可以拿PHP写,明天你可以拿JAVA来写,但是如果你的数据结构开始设计不合理,将来数据结构的改变会花费你数倍的代价,老的数据格式向新的数据格式迁移会让你痛不欲生,既有工作量上的,又有数据迁移跨越的时间周期,有一些甚至需要半年以上。 第四,物理结构与逻辑结构的映射,上一张图看到两个维度切成十二个区间,每个区间代表一个技术领域,这个可以看做我们的逻辑结构。另外,不论后台还是应用层的开发团队,一般都会分几个垂直的业务组加上一个基础技术架构组,这就是从物理组织架构到逻辑的技术架构的完美的映射,精细化团队分工,有利于提高沟通协作的效率 。 第五, www .sanhao.com 的访问过程,我们这个架构图里没有涉及到的,举个例子,比如当你在浏览器输入www.sanhao网址的时候,这个请求在接口层之前发生了什么?首先会查看你本机DNS以及DNS服务,查找域名对应的IP地址,然后发送HTTP请求过去。这个请求首先会到前端的VIP地址(公网服务IP地址),VIP之后还要经过负载均衡器(Nginx服务器),之后才到你的应用接口层。在接口层之前发生了这么多事,可能有用户报一个问题的时候,你通过在接口层查日志根本发现不了问题,原因就是问题可能发生在到达接口层之前了。 第六,我们说分布式系统,它最终的瓶颈会落在哪里呢?前端时间有一个网友跟我讨论的时候,说他们的系统遇到了一个瓶颈, 查遍了CPU,内存,网络,存储,都没有问题。我说你再查一遍,因为最终你不论用上千台服务器还是上万台服务器,最终系统出瓶颈的一定会落在某一台机(可能是叶子节点也可能是核心的节点),一定落在CPU、内存、存储和网络上,最后查出来问题出在一台服务器的网卡带宽上。微博多级双机房缓存架构 接下来我们看一下微博的Feed多级缓存。我们做业务的时候,经常很少做业务分析,技术大会上的分享又都偏向技术架构。其实大家更多的日常工作是需要花费更多时间在业务优化上。这张图是统计微博的信息流前几页的访问比例,像前三页占了97%,在做缓存设计的时候,我们最多只存最近的M条数据。 这里强调的就是做系统设计 要基于用 户 的 场 景 , 越细致越好 。举了一个例子,大家都会用电商,电商在双十一会做全国范围内的活动,他们做设计的时候也会考虑场景的,一个就是购物车,我曾经跟相关开发讨论过,购物车是在双十一之前用户的访问量非常大,就是不停地往里加商品。在真正到双十一那天他不会往购物车加东西了,但是他会频繁的浏览购物车。针对这个场景,活动之前重点设计优化购物车的写场景, 活动开始后优化购物车的读场景。 你看到的微博是由哪些部分聚合而成的呢?最右边的是Feed,就是微博所有关注的人,他们的微博所组成的。微博我们会按照时间顺序把所有关注人的顺序做一个排序。随着业务的发展,除了跟时间序相关的微博还有非时间序的微博,就是会有广告的要求,增加一些广告,还有粉丝头条,就是拿钱买的,热门微博,都会插在其中。分发控制,就是说和一些推荐相关的,我推荐一些相关的好友的微博,我推荐一些你可能没有读过的微博,我推荐一些其他类型的微博。 当然对非时序的微博和分发控制微博,实际会起多个并行的程序来读取,最后同步做统一的聚合。这里稍微分享一下, 从SNS社交领域来看,国内现在做的比较好的三个信息流: 微博 是 基于弱关系的媒体信息流 ; 朋友圈是基于 强 关系的信息流 ; 另外一个做的比 较 好的就是今日 头 条 , 它并不是基于关系来构建信息流 , 而是基于 兴趣和相关性的个性化推荐 信息流 。 信息流的聚合,体现在很多很多的产品之中,除了SNS,电商里也有信息流的聚合的影子。比如搜索一个商品后出来的列表页,它的信息流基本由几部分组成:第一,打广告的;第二个,做一些推荐,热门的商品,其次,才是关键字相关的搜索结果。 信息流 开始的时候 很 简单 , 但是到后期会 发现 , 你的 这 个流 如何做控制分发 , 非常复杂, 微博在最近一两年一直在做 这样 的工作。刚才我们是从业务上分析,那么技术上怎么解决高并发,高性能的问题?微博访问量很大的时候,底层存储是用MySQL数据库,当然也会有其他的。对于查询请求量大的时候,大家知道一定有缓存,可以复用可重用的计算结果。可以看到,发一条微博,我有很多粉丝,他们都会来看我发的内容,所以 微博是最适合使用 缓 存 的系统,微博的读写比例基本在几十比一。微博使用了 双 层缓 存,上面是L1,每个L1上都是一组(包含4-6台机器),左边的框相当于一个机房,右边又是一个机房。在这个系统中L1缓存所起的作用是什么? 首先,L1 缓 存增加整个系 统 的 QPS, 其次 以低成本灵活扩容的方式 增加 系统 的 带宽 。想象一个极端场景,只有一篇博文,但是它的访问量无限增长,其实我们不需要影响L2缓存,因为它的内容存储的量小,但它就是访问量大。这种场景下,你就需要使用L1来扩容提升QPS和带宽瓶颈。另外一个场景,就是L2级缓存发生作用,比如我有一千万个用户,去访问的是一百万个用户的微博 ,这个时候,他不只是说你的吞吐量和访问带宽,就是你要缓存的博文的内容也很多了,这个时候你要考虑缓存的容量, 第二 级缓 存更多的是从容量上来 规划,保证请求以较小的比例 穿透到 后端的 数据 库 中 ,根据你的用户模型你可以估出来,到底有百分之多少的请求不能穿透到DB, 评估这个容量之后,才能更好的评估DB需要多少库,需要承担多大的访问的压力。另外,我们看双机房的话,左边一个,右边一个。 两个机房是互 为 主 备 , 或者互 为热备 。如果两个用户在不同地域,他们访问两个不同机房的时候,假设用户从IDC1过来,因为就近原理,他会访问L1,没有的话才会跑到Master,当在IDC1没找到的时候才会跑到IDC2来找。同时有用户从IDC2访问,也会有请求从L1和Master返回或者到IDC1去查找。 IDC1 和 IDC2 ,两个机房都有全量的用户数据,同时在线提供服务,但是缓存查询又遵循最近访问原理。还有哪些多级缓存的例子呢?CDN是典型的多级缓存。CDN在国内各个地区做了很多节点,比如在杭州市部署一个节点时,在机房里肯定不止一台机器,那么对于一个地区来说,只有几台服务器到源站回源,其他节点都到这几台服务器回源即可,这么看CDN至少也有两级。Local Cache+ 分布式 缓 存,这也是常见的一种策略。有一种场景,分布式缓存并不适用, 比如 单 点 资 源 的爆发性峰值流量,这个时候使用Local Cache + 分布式缓存,Local Cache 在 应用 服 务 器 上用很小的 内存资源 挡住少量的 极端峰值流量,长尾的流量仍然访问分布式缓存,这样的Hybrid缓存架构通过复用众多的应用服务器节点,降低了系统的整体成本。 我们来看一下 Feed 的存 储 架构,微博的博文主要存在MySQL中。首先来看内容表,这个比较简单,每条内容一个索引,每天建一张表,其次看索引表,一共建了两级索引。首先想象一下用户场景,大部分用户刷微博的时候,看的是他关注所有人的微博,然后按时间来排序。仔细分析发现在这个场景下, 跟一个用户的自己的相关性很小了。所以在一级索引的时候会先根据关注的用户,取他们的前条微博ID,然后聚合排序。我们在做哈希(分库分表)的时候,同时考虑了按照UID哈希和按照时间维度。很业务和时间相关性很高的,今天的热点新闻,明天就没热度了,数据的冷热非常明显,这种场景就需要按照时间维度做分表,首先冷热数据做了分离(可以对冷热数据采用不同的存储方案来降低成本),其次, 很容止控制我数据库表的爆炸。像微博如果只按照用户维度区分,那么这个用户所有数据都在一张表里,这张表就是无限增长的,时间长了查询会越来越慢。二级索引,是我们里面一个比较特殊的场景,就是我要快速找到这个人所要发布的某一时段的微博时,通过二级索引快速定位。 分布式服务追踪系统 分布式追踪服务系统,当系统到千万级以后的时候,越来越庞杂,所解决的问题更偏向稳定性,性能和监控。刚才说用户只要有一个请求过来,你可以依赖你的服务RPC1、RPC2,你会发现RPC2又依赖RPC3、RPC4。分布式服务的时候一个痛点,就是说一个请求从用户过来之后,在后台不同的机器之间不停的调用并返回。 当你发现一个问题的时候,这些日志落在不同的机器上,你也不知道问题到底出在哪儿,各个服务之间互相隔离,互相之间没有建立关联。所以导致排查问题基本没有任何手段,就是出了问题没法儿解决。 我们要解决的问题,我们刚才说日志互相隔离,我们就要把它建立联系。建立联系我们就有一个请求ID,然后结合RPC框架, 服务治理功能。假设请求从客户端过来,其中包含一个ID 101,到服务A时仍然带有ID 101,然后调用RPC1的时候也会标识这是101 ,所以需要 一个唯一的 请求 ID 标识 递归迭代的传递到每一个 相关 节点。第二个,你做的时候,你不能说每个地方都加,对业务系统来说需要一个框架来完成这个工作, 这 个框架要 对业务 系 统 是最低侵入原 则 , 用 JAVA 的 话 就可以用 AOP,要做到零侵入的原则,就是对所有相关的中间件打点,从接口层组件(HTTP Client、HTTP Server)至到服务层组件(RPC Client、RPC Server),还有数据访问中间件的,这样业务系统只需要少量的配置信息就可以实现全链路监控 。为什么要用日志?服务化以后,每个服务可以用不同的开发语言, 考虑多种开发语言的兼容性 , 内部定 义标 准化的日志 是唯一且有效的办法。最后,如何构建基于GPS导航的路况监控?我们刚才讲分布式服务追踪。分布式服务追踪能解决的问题, 如果 单一用 户发现问题 后 , 可以通 过请 求 ID 快速找到 发 生 问题 的 节 点在什么,但是并没有解决如何发现问题。我们看现实中比较容易理解的道路监控,每辆车有GPS定位,我想看北京哪儿拥堵的时候,怎么做? 第一个 , 你肯定要知道每个 车 在什么位置,它走到哪儿了。其实可以说每个车上只要有一个标识,加上每一次流动的信息,就可以看到每个车流的位置和方向。 其次如何做 监 控和 报 警,我们怎么能了解道路的流量状况和负载,并及时报警。我们要定义这条街道多宽多高,单位时间可以通行多少辆车,这就是道路的容量。有了道路容量,再有道路的实时流量,我们就可以基于实习路况做预警? 对应于 分布式系 统 的话如何构建? 第一 , 你要 定义 每个服 务节 点它的 SLA A 是多少 ?SLA可以从系统的CPU占用率、内存占用率、磁盘占用率、QPS请求数等来定义,相当于定义系统的容量。 第二个 , 统计 线 上 动态 的流量,你要知道服务的平均QPS、最低QPS和最大QPS,有了流量和容量,就可以对系统做全面的监控和报警。 刚才讲的是理论,实际情况肯定比这个复杂。微博在春节的时候做许多活动,必须保障系统稳定,理论上你只要定义容量和流量就可以。但实际远远不行,为什么?有技术的因素,有人为的因素,因为不同的开发定义的流量和容量指标有主观性,很难全局量化标准,所以真正流量来了以后,你预先评估的系统瓶颈往往不正确。实际中我们在春节前主要采取了三个措施:第一,最简单的就是有降 级 的 预 案,流量超过系统容量后,先把哪些功能砍掉,需要有明确的优先级 。第二个, 线上全链路压测,就是把现在的流量放大到我们平常流量的五倍甚至十倍(比如下线一半的服务器,缩容而不是扩容),看看系统瓶颈最先发生在哪里。我们之前有一些例子,推测系统数据库会先出现瓶颈,但是实测发现是前端的程序先遇到瓶颈。第三,搭建在线 Docker 集群 , 所有业务共享备用的 Docker集群资源,这样可以极大的避免每个业务都预留资源,但是实际上流量没有增长造成的浪费。 总结 接下来说的是如何不停的学习和提升,这里以Java语言为例,首先, 一定要 理解 JAVA;第二步,JAVA完了以后,一定要 理 解 JVM;其次,还要 理解 操作系统;再次还是要了解一下 Design Pattern,这将告诉你怎么把过去的经验抽象沉淀供将来借鉴;还要学习 TCP/IP、 分布式系 统、数据结构和算法。

hiekay 2019-12-02 01:39:25 0 浏览量 回答数 0

回答

回 5楼(冬瓜苗苗) 的帖子 二次验证暂时还没有,我们有冻结的情况,就是说如果密码错误超过5次,帐号会被冻结15分钟,不可以再连接.如果他一直连接,过15分钟后释放后再尝试超过5次同样还是会冻结的. ------------------------- 回 8楼(冬瓜苗苗) 的帖子 手机端的APP是通过私密协是我们自己的客户端,是存在更改密码是不去做验证的问题,已经在解决了.目前只有手机阿里云邮这个不验证,其它的客户端都验证.我们已经在协调处理中. ------------------------- 回 7楼(冬瓜苗苗) 的帖子 亲, 问一下你是所有的浏览器都会有,还是只有IE或者360有,可否下载一个chrome试试,不好意思,信息太多,漏掉了. 如果都是这种,把你的帐号提供一下,我这里查一下原因,应该跟木马没有关系的,这个可能是帐号后台系统有问题,我先查了才清楚. ------------------------- 回 12楼(冬瓜苗苗) 的帖子 亲,不要把你的电话放到公共场所,对你并没有什么好处,你具体什么问题,可以私信给我吧。谢谢! ------------------------- 回 14楼(冬瓜苗苗) 的帖子 如果亲最近几天使用率不高.可以发邮件给我.做临时冻结处理,然后过几天再解冻.另外可以登录网页设置里面客户端权限关闭掉,这样他们通过SMTP.就无法连通了.关闭后.SMTP服务就关闭了,即使他拿到你的密码,也无法使用SMTP发信了. ------------------------- 回 16楼(冬瓜苗苗) 的帖子 关闭了就不会影响.他怎么连也不会通,都是失败的.

仙游 2019-12-02 01:55:56 0 浏览量 回答数 0

问题

【精品回答】移动推送

montos 2020-04-09 09:57:11 14 浏览量 回答数 1

回答

ReIDC行业头脑风暴室-有视频、有真相、讨论开始啦 个人觉得关键还是“云”这个东西怎么去运营,单纯还是以IDC的概念和营销模式去做,可能依旧还会是起不来,云的概念是可得,共享,阿里云其实概念很好,为什么起不来,我也很纳闷 ------------------------- 回21楼shutong的帖子 完全公有云去解决全部云计算貌似是不太现实,现在有些社区在弄云社区方案,习惯的做法是在社区自建机房架设服务器,考虑到社区住户信息的安全性,基本不太可能再将这些信息去接入公共云平台 ------------------------- 回27楼lizhan的帖子 非常同意楼主的观点,阿里云对云资源中的源数据和后进数据利用的好,也许不久就可以有好的产品面世,期待 ------------------------- ReIDC行业头脑风暴室-有视频、有真相、讨论开始啦 “觉得有两个为难的事情。一个是老机器如何处理。一个是原先觉得能够维护好机器就是服务的一大核心竞争力” 这个是不是可以理解为成本问题,对于云提供商来讲,机器利用率和成本是可以很好置换的,如果指旧设备的处理,其实外面是有产业链的 ,关键可能会在于云提供商对每台设备使用寿命的把控吧;维护这边其实云服务商的优势,这无疑是帮IDC厂商节省了人力成本,但从侧面来说也是一个挑战,网络节点和区域带宽速度的把控是不是要考虑呢,技术部的人员怎么考虑这点呢?

mrmarx 2019-12-01 23:48:03 0 浏览量 回答数 0

问题

想打造一款成功的移动应用?

sunny夏筱 2019-12-01 21:36:33 5662 浏览量 回答数 7

问题

有人遇到这情况么?因为用百度加速乐要被阿里云撤销

惹尘_1225 2019-12-01 21:36:24 10249 浏览量 回答数 8

问题

阿里云监控/云盾Agent服务造成内存泄露的临时解决方案

asbai 2019-12-01 21:53:42 24171 浏览量 回答数 17

回答

问题①:现在Web前端开发的薪资待遇怎么样? 问题②:学了Web前端开发技术出来是否好找工作? 问题③:Web前端开发需要掌握哪些技术知识点? 问题④:非科班出生学习Web前端是否能做找到工作? 第一:前端技术在我国发展的还算是比较完善,只要你现在能把前端技术学好,具备一定的开发经验,想要找到合适的岗位工作,基本上还是没有什么问题。21世纪是信息时代,随着互联网快速的发展,市场上对前端技术也会持续增加。我们来看下目前前端开发在一线城市的薪资待遇水平: 可以看出现在前端开发在一线城市的薪资待遇水平是在16k左右,当然这是具备一定开发经验的,一般就我们刚学完前端技术出来,能顺利通过企业岗位工作面试,基本上能拿到的薪资待遇在3-7k左右,据你的技术水平而定。 第二:学了前端技术出来是否好找工作呢?这个没有绝对肯定的回答。这个要根据你的技术水平而定,我上第一点的时候已经说了,只要你可以把市场需求的前端技术知识点都掌握,具备一定的开发经验,想要找到合适的岗位工作,基本上没什么问题。如果说你就学了一点简单的HTML,CSS就想找到这方面的工作,那我建议你还是放弃吧。 第三:想要从事前端开发方面的岗位工作,需要掌握哪方面的技术知识点? 1、HTML HTML页面固定,标签不多,学起来比较容易,这也是很多零基础转行IT首选前端的主要原因。HTML是页面结构的基础组成部分,是网站的基础,编写HTML代码需遵循HTML代码规范,臃肿混乱的HTML代码不但会影响其本身的表现,而且与其对应的CSS和Javascript代码也会变得难以编写和维护。 2、CSS CSS负责网页类容的表现,也是前端开发需要掌握的核心内容之一。CSS和HTML代码一样,没用复杂的逻辑,上手也比较容易,其主要难点在于如何合理利用CSS的组合和继承特性来编写简洁,维护性好的CSS代码。 3、JavaScript JavaScript是一种基于对象和事件驱动的客户端脚本语言,是页面实时动态交互的技术基础。开发人员在熟悉Javascript基本语法和基本的编码规范之外,还应该了解并解决在不同浏览区中JavaScript的兼容性问题。另外,目前流行的Web编程方式会有部分后端代码存在于前端页面中,和前端HTML、Javascript等混合在一起,如PHP、JSP、http://ASP.NET等,因此,前端开发工程师也有必要了解一些后端编程技术。 4、跨平台、跨浏览器 跨平台指移动设备(如智能手机和平板电脑)和PC端; 随着IE6,IE7市场占有率下降和众多浏览器标准的重视,目前流行的前端框架已经很好滴解决了浏览器兼容问题。尽管如此,还需熟悉常见的浏览器兼容问题,如IE7、IE8的兼容,HTML5中新特性的兼容等。 5、前端框架 前端框架的出现在很大程度上降低了前端开发的难度,框架统一了编码的方式,封装了浏览器兼容问题并添加了大量的扩展功能。目前比较常用的前端开源框架有很多,比如jQuery(Javascript库)、angular2、vue.js、react等。 6、调试工具 对于前端代码,在调试过程中需要查看HTML结构变化,CSS渲染效果,Javascript代码执行情况以及HTTP请求和返回的数据,并了解网站各部分的性能等。主流浏览器都有对应的浏览器插件来辅助完成这个工作,如IE中的IE Dev Toolbar、Chrome中的Developer Tools、Firefox中的Firebug等。 7、实战经验 企业在招聘的过程中都想要选出上手即用的前端人才,这就需要求职者具备相应的开发经验、能够很快的接手工作。因此如果你想要学习Web前端,不仅要掌握理论知识,更要注重积累实战经验。 8、沟通表达能力 求职面试需要好的表达能力,在日常工作中前端人员也要具备好的沟通能力。Web前端是介于UI和后端逻辑开发之间的岗位,需要与UI设计师沟通确定效果,还需要和后端工程师沟通确定前后端交互,良好的沟通让你这些过程变得轻松许多。 第四:非科班出生学了前端技术出来可以找到工作吗? 对于这个问题,我想说,你考虑的地方有点多了,是否可以找到工作呢?我的回答是肯定的。前端技术没有一定说是只有科班出生才能学的,非科班出生也可以学前端。你看现在市场上上千万的做开发的人群,难道说他们都是科班出身的吗?不可能对吧。所有加油吧。

茶什i 2020-01-13 11:35:15 0 浏览量 回答数 0

问题

开发者论坛一周精粹(第五十四期)&nbsp;&nbsp;求购备案服务号1枚!

福利达人 2019-12-01 21:30:19 4028 浏览量 回答数 1

问题

如何彻底消灭Bug?

问问小秘 2020-06-29 11:07:58 13 浏览量 回答数 2

问题

阿里云服务器 如何处理网站高并发流量问题?(含教程)

元芳啊 2019-12-01 21:54:35 1511 浏览量 回答数 1

回答

提交注册表单到后端处理时,调用第三方短信服务(手机号码,后端生成验证码),限制多少时间内重发。验证码可以保存数据库中有效时间,或者session中设置过期时间问题有些太开放,宽松制约。重新考虑一下需求;如你所说的确实是个问题。或者其他人解答一下手机号码注册,短信只作验证功能(省事,用户群体比较有质量,手机号码唯一性,防止恶意刷注册用户数)/邮箱验证也可以,用户体验上手机较好(后期还可以通过手机号码去分析用户) 如果每次登陆都用短信验证码(短信服务还是要钱的...这个一天登陆一多就懂) ######首先 非常感谢你这么认真的回答。 我看完后 再回复你。先谢谢你###### 1. 你们服务端生成 短信 内容 提交到他们那,验证码可以放到缓存里,用户确定的时候检查缓存.写一个公共的服务组件, Linux可用crontab Win可用定时任务,在指定时间段内 每分钟查询下数据库,提交到短信提供商.最好不要使用短信登陆. ######关于问题1 ,一般都是用户前台输入手机号,点击获取验证码按钮后先在自己服务器根据短信服务商的接口规范生成url(包括验证码的生成,生成之后保存在session或者数据库中),然后用curl发请求,收到一个唯一的短信id就表示发送成功了(但是有可能是对方服务器出了问题,收到了id用户还没收到短信,我遇到过这个问题,最后他们换了一个线路解决了)###### 引用来自“p2ng”的评论 提交注册表单到后端处理时,调用第三方短信服务(手机号码,后端生成验证码),限制多少时间内重发。验证码可以保存数据库中有效时间,或者session中设置过期时间问题有些太开放,宽松制约。重新考虑一下需求;如你所说的确实是个问题。或者其他人解答一下手机号码注册,短信只作验证功能(省事,用户群体比较有质量,手机号码唯一性,防止恶意刷注册用户数)/邮箱验证也可以,用户体验上手机较好(后期还可以通过手机号码去分析用户) 如果每次登陆都用短信验证码(短信服务还是要钱的...这个一天登陆一多就懂) 回复1: 一般大家的普通做法是 保持数据库中还是SESSION中 还是内存中啊。  验证码好像就是临时的吧。 这个手机验证码 是需要我自定义生成吗? 我做过登陆图形验证码。用户输入后判断下。就行。提交一次重新生成。 但这个貌似可以提交多次,直到你输入正确的短信验证码是吧? 回复2: 举个简单例子吧: 我加入要做个提醒的功能。  我在web网站上 设置好时间,设置后内容。然后我当天那个时间收到这个短信内容。 我就是提供给会员这个事情。  比如我做一个比赛预告的WEB页面,用户点击比赛前1小时短信提醒我。  回复3: 每次短信登陆的确很麻烦也很费钱。 但类似微博就是这种的啊。 可以提供手机短信登陆的啊。 短信登陆唯一好处就是 用户注册/登陆都一样的,这样用户注册的时候就没有密码设置这一项,用户第一次实用的体验度会很好。。。。 ###### 引用来自“金马超”的评论 你们服务端生成 短信 内容 提交到他们那,验证码可以放到缓存里,用户确定的时候检查缓存.写一个公共的服务组件, Linux可用crontab Win可用定时任务,在指定时间段内 每分钟查询下数据库,提交到短信提供商.最好不要使用短信登陆. 回复1: 大体思路我明白了,只是之前没做过短信注册这个模块。 我看看第三方1069通道的 应该不难。 或者网上搜搜下 回复2: linux的crontab定时任务和win我都会,但我的意思是 一个用户 写周四下午3点 那我这边就执行一个定时任务会不会太浪费了?也太多了? 或者你说,每分钟查下数据库 也就是每隔一分钟执行一个php脚本文件,遍历循环下? 有的话就发 没有的 就不发。 就等于轮询? 这样是不是很耗费服务器资源? 有没有其他解解方法 回复3: 你的意思是 短信注册可以,然后引导用户设置密码。 但手机短信登陆不建议ma? 但我的意思,像weibo就是手机短信验证码直接登陆 携程也是这样 还有一种是你说的只能手机+密码来登陆 那我的意思是,如果二者并行,怎么设计这个表。。。 ###### 引用来自“西南茂”的评论关于问题1 ,一般都是用户前台输入手机号,点击获取验证码按钮后先在自己服务器根据短信服务商的接口规范生成url(包括验证码的生成,生成之后保存在session或者数据库中),然后用curl发请求,收到一个唯一的短信id就表示发送成功了(但是有可能是对方服务器出了问题,收到了id用户还没收到短信,我遇到过这个问题,最后他们换了一个线路解决了) 回复1: 你的流程是   用户填手机号---》用户点击提交获取验证码--》服务器生成一个验证码---》这个验证码通过sdk 用curl发送到短信运营商---》短信运营商服务器收到后发到用户手机号上---》 用户收到输入这个验证码--》我们后台核对  OK? ######对,差不多就是这个流程###### 引用来自“金马超”的评论 你们服务端生成 短信 内容 提交到他们那,验证码可以放到缓存里,用户确定的时候检查缓存.写一个公共的服务组件, Linux可用crontab Win可用定时任务,在指定时间段内 每分钟查询下数据库,提交到短信提供商.最好不要使用短信登陆. 引用来自“kacc850”的评论 回复1: 大体思路我明白了,只是之前没做过短信注册这个模块。 我看看第三方1069通道的 应该不难。 或者网上搜搜下 回复2: linux的crontab定时任务和win我都会,但我的意思是 一个用户 写周四下午3点 那我这边就执行一个定时任务会不会太浪费了?也太多了? 或者你说,每分钟查下数据库 也就是每隔一分钟执行一个php脚本文件,遍历循环下? 有的话就发 没有的 就不发。 就等于轮询? 这样是不是很耗费服务器资源? 有没有其他解解方法 回复3: 你的意思是 短信注册可以,然后引导用户设置密码。 但手机短信登陆不建议ma? 但我的意思,像weibo就是手机短信验证码直接登陆 携程也是这样 还有一种是你说的只能手机+密码来登陆 那我的意思是,如果二者并行,怎么设计这个表。。。 写成一个公共的组件...   这个服务从指定的一张表里查询数据 eg  ID 内容 下发时间 手机号 ... 只要代码没问题的话  对服务器来说不会是什么太大的问题.嗯   是这样的,不建议短信登陆,可以用短信找回密码. 你们公司不是微博/携程,没人家那种财力,最好不要这么做, 而且短信这个行业也不是你想的那么简单,提交就能发的. 如果要并行的话,单独建立一张表用来记录短信登陆比较好. 用户表只放基本信息,短信登陆表 带上用户名,手机号,登陆时间,IP可有可无. 和用户表稍微关联下就行. ######硕达通短信平台,发验证码5秒到,发通知5秒到,速度快,到达率98%以上,成功计费(失败不计费)实时状态报告(成功失败一目了然)支持上下行 北京硕达通  www.shdat.com  买短信有红包!######凌凯短信:快/3秒响应 ·12年品牌塑造,三网(移动、联通、电信)通道,覆盖所有手机号码 ·3秒快速响应,行业领先(www.028lk.com)######雨林木风短信平台,三网合一,五秒达到,到达率99%,欢迎站内信哟~~~~

kun坤 2020-06-11 10:43:41 0 浏览量 回答数 0

回答

nginx的静态页面都进不去的话应该是OS的TCP出了问题吧,要不看看你这个服务器当前的文件描述符数量`ulimit -n`。######回复 @snailkky : 解决了没?是这个原因吗?######回复 @口口口S口口口 : 真是太感谢你了! 我现在很怀疑就是这个原因造成的,我去试试看。######回复 @snailkky : :cold_sweat:我也只是知道这个东西,或许你可以写个测试用例试一下,用Jmeter定个6000进程访问看看######一般每个进程最多允许同时打开1024个文件,这1024个文件中还得除去每个进程必然打开的标准输入,标准输出,标准错误,服务器监听socket,进程间通讯的unix域socket等文件,那么剩下的可用于客户端socket连接的文件数就只有大概1024-10=1014个左右。也就是说缺省情况下,基于Linux的通讯程序最多允许同时1014个TCP并发连接。 是这个原因造成的吗?######65535###### 负载均衡,可以先开3个nginx,9个项目。######你这种就是性能不行, 上来就是分布式, 负载均衡。 明显几千连接,资源系统资源占用不高,是什么环节出了问题。 搞分布式,负载均衡就是掩耳盗铃######回复 @天空-sky : worker_connections 我配置了65535,另外worker_processes 我配置为8######nginx 还有worker_connections配置,可以了解下###### 密集IO情况下的Nginx调优方案: nginx进程数调到CPU核数的1.5倍,并且把每个进程平均绑到每个CPU上,多出来的让Linux自动调度到空闲CPU。 突然并发的情况下,Tomcat调优方法: 调成多进程+多线程运行模式,并且空闲时保留进程不少于CPU核数的一半。 nginx和tomcat采用fastcgi方式互交。###### 我简单看了一下,服务器很正确,监控正常,你的高峰瘫痪是指?######就是很多用户进不来,我自己也进不去,加载不出来,nginx部署的另一个静态页也无法访问###### 单机的配置降一降,拆分成多节点呗。###### 使用令牌桶做限流处理###### 我更好奇你这个监控是怎么看到的,为什么我的云监控没你的这么细######额,懂了,但是你好像是升级版的,我的是免费版的! 看了下升级版的,一个月都要1099:joy:######在云服务监控-云服务器ECS,你点进去,再点单个的监控,就可以显示这个图表了。###### 光看这个不太好分析,信息量太少。首先tomcat本身支持的并发就不高,到了6000肯定是没办法支持的,即使你将你的maxThread设置为2000,以你机器的性能也无法发挥线程的优势,反而增加了CPU线程切换的资源耗费。如果流量真的有这么大,那需要考虑做集群来承载。另外如果你的应用是IO型的,可以试试tomcat的NIO方式。######我是spring boot2,tomcat默认就是nio######高版本的tomcat好像默认都是nio,那如果是这样的话,高配服务器就发挥不了它的性能,感觉挺鸡肋的。######看症状貌似你的服务器是共享实例,积分用完之后cpu占用率不能超过20%######我这个是通用型实例 不是共享型###### 看下带宽######没有,因为我也怕是带宽的问题,然后我又升级到了60M,程序也没有变化。######回复 @snailkky : 出问题的那天,带宽使用情况怎么样?有没有出现不足######现在是5M带宽,但我那天临时升级到了20M

kun坤 2020-06-07 09:02:49 0 浏览量 回答数 0

问题

SaaS模式云数据仓库MaxCompute 百问百答合集(持续更新20200724)

亢海鹏 2020-05-29 15:10:00 9080 浏览量 回答数 2

问题

要么“被离职”要么几十万年终奖,程序员的年度绩效怎样做才公正?

游客pklijor6gytpx 2020-01-20 10:04:45 786 浏览量 回答数 2

问题

九个衡量Rails应用性能的小方法

sunny夏筱 2019-12-01 21:43:43 7571 浏览量 回答数 3

问题

Android 常见问题有哪些

猫饭先生 2019-12-01 21:59:21 792 浏览量 回答数 0

问题

九个衡量Rails应用性能的小方法

doudou1 2019-12-01 22:09:09 9032 浏览量 回答数 1

问题

干货分享:DBA专家门诊一期:索引与sql优化问题汇总

xiaofanqie 2019-12-01 21:24:21 74007 浏览量 回答数 38

问题

性能测试技术怎么进行?

猫饭先生 2019-12-01 21:26:08 1341 浏览量 回答数 0

问题

应该如何使用阿里云?高级篇

rippletek 2019-12-01 21:14:53 20970 浏览量 回答数 18

回答

回2楼啊里新人的帖子 在日常的业务开发中,常见使用到索引的地方大概有两类: 第一类.做业务约束需求,比如需要保证表中每行的单个字段或者某几个组合字段是唯一的,则可以在表中创建唯一索引; 比如:需要保证test表中插入user_id字段的值不能出现重复,则在设计表的时候,就可以在表中user_id字段上创建一个唯一索引: CREATE TABLE `test` (   `id` int(11) NOT NULL AUTO_INCREMENT,   `user_id` int(11) NOT NULL,   `gmt_create` datetime DEFAULT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `uk_userid` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ; 第二类.提高SQL语句执行速度,可以根据SQL语句的查询条件在表中创建合适的索引,以此来提升SQL语句的执行速度; 此过程好比是去图书找一本书,最慢的方法就是从图书馆的每一层楼每一个书架一本本的找过去;快捷一点的方法就是先通过图书检索来确认这一本书在几楼那个书架上,然后直接去找就可以了;当然创建这个索引也需要有一定的代价,需要存储空间来存放,需要在数据行插入,更新,删除的时候维护索引: 例如: CREATE TABLE `test_record` (   `id` int(11) NOT NULL AUTO_INCREMENT,   `user_id` int(11) NOT NULL,   `gmt_create` datetime DEFAULT NULL,   PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5635996 DEFAULT CHARSET=utf8 该表有500w的记录,我需要查询20:00后插入的记录有多少条记录: mysql> select count(*) from test_record where gmt_create>'2014-12-17 20:00:00'; +----------+ | count(*) | +----------+ |        1 | +----------+ 1 row in set (1.31 sec) 可以看到查询耗费了1.31秒返回了1行记录,如果我们在gmt_create字段上添加索引: mysql> alter table test_record add index ind_gmt_create(gmt_create); Query OK, 0 rows affected (21.87 sec) Records: 0  Duplicates: 0  Warnings: 0 mysql> select count(*) from test_record where gmt_create>'2014-12-17 20:00:00'; +----------+ | count(*) | +----------+ |        1 | +----------+ 1 row in set (0.01 sec) 查询只消耗了0.01秒中就返回了记录. 总的来说,为SQL语句(select,update,delete)创建必要的索引是必须的,这样虽然有一定的性能和空间消耗,但是是值得,尤其是在大并发的请求下,大量的数据被扫描造成系统IO和CPU资源消耗完,进而导致整个数据库不可服务. ------------------------- 怎么学好数据库是一个比较大题目,数据库不仅仅是写SQL那么简单,即使知道了SQL怎么写,还需要很清楚的知道这条SQL他大概扫描了多少数据,返回多少数据,是否需要创建索引。至于SQL优化是一个比较专业的技术活,但是可以通过学习是可以掌握的,你可以把一条sql从执行不出来优化到瞬间完成执行,这个过程的成就感是信心满满的。学习的方法可以有以下一些过程:1、自己查资料,包括书本,在线文档,google,别人的总结等等,试图自己解决2、多做实验,证明自己的想法以及判断3、如果实在不行,再去论坛问,或者问朋友4、如果问题解决了,把该问题的整个解决方法记录下来,以备后来的需要5、多关注别人的问题,或许以后自己就遇到了,并总是试图去多帮助别人6、习惯从多个方面去考虑问题,并且养成良好的总结习惯 下面是一些国内顶级数据库专家学习数据库的经验分享给大家: http://www.eygle.com/archives/2005/08/ecinieoracleouo.html 其实学习任何东西都是一样,没有太多的捷径可走,必须打好了坚实的基础,才有可以在进一步学习中得到快速提高。王国维在他的《人间词话》中曾经概括了为学的三种境界,我在这里套用一下: 古今之成大事业、大学问者,罔不经过三种之境界。"昨夜西风凋碧树。独上高楼,望尽天涯路。"此第一境界也。"衣带渐宽终不悔,为伊消得人憔悴。"此第二境界也。"众里寻他千百度,蓦然回首,那人却在灯火阑珊处。"此第三境界也。 学习Oracle,这也是你必须经历的三种境界。 第一层境界是说,学习的路是漫漫的,你必须做好充分的思想准备,如果半途而废还不如不要开始。 这里,注意一个"尽"字,在开始学习的过程中,你必须充分阅读Oracle的基础文档,概念手册、管理手册、备份恢复手册等(这些你都可以在http://tahiti.oracle.com 上找到);OCP认证的教材也值得仔细阅读。打好基础之后你才具备了进一步提升的能力,万丈高楼都是由地而起。 第二层境界是说,尽管经历挫折、打击、灰心、沮丧,也都要坚持不放弃,具备了基础知识之后,你可以对自己感兴趣或者工作中遇到的问题进行深入的思考,由浅入深从来都不是轻而易举的,甚至很多时候你会感到自己停滞不前了,但是不要动摇,学习及理解上的突破也需要时间。 第三次境界是说,经历了那么多努力以后,你会发现,那苦苦思考的问题,那百思不得其解的算法原理,原来答案就在手边,你的思路豁然开朗,宛如拨云见月。这个时候,学习对你来说,不再是个难题,也许是种享受,也许成为艺术。 所以如果你想问我如何速成,那我是没有答案的。 不经一番寒彻骨,哪得梅花扑鼻香。 当然这三种境界在实际中也许是交叉的,在不断的学习中,不断有蓦然回首的收获。 我自己在学习的过程中,经常是采用"由点及面法"。 当遇到一个问题后,一定是深入下去,穷究根本,这样你会发现,一个简单的问题也必定会带起一大片的知识点,如果你能对很多问题进行深入思考和研究,那么在深处,你会发现,这些面逐渐接合,慢慢的延伸到oracle的所有层面,逐渐的你就能融会贯通。这时候,你会主动的去尝试全面学习Oracle,扫除你的知识盲点,学习已经成为一种需要。 由实践触发的学习才最有针对性,才更能让你深入的理解书本上的知识,正所谓:" 纸上得来终觉浅,绝知此事要躬行"。实践的经验于我们是至为宝贵的。 如果说有,那么这,就是我的捷径。 想想自己,经常是"每有所获,便欣然忘食", 兴趣才是我们最好的老师。 Oracle的优化是一门学问,也是一门艺术,理解透彻了,你会知道,优化不过是在各种条件之下做出的均衡与折中。 内存、外存;CPU、IO...对这一切你都需要有充分的认识和相当的了解,管理数据库所需要的知识并不单纯。 作为一个数据库管理人员,你需要做的就是能够根据自己的知识以及经验在各种复杂情况下做出快速正确的判断。当问题出现时,你需要知道使用怎样的手段发现问题的根本;找到问题之后,你需要运用你的知识找到解决问题的方法。 这当然并不容易,举重若轻还是举轻若重,取决于你具备怎样的基础以及经验积累。 在网络上,Howard J. Rogers最近创造了一个新词组:Voodoo Tuning,用以形容那些没有及时更新自己的知识技能的所谓的Oracle技术专家。由于知识的陈旧或者理解的肤浅,他们提供的很多调整建议是错误的、容易使人误解的,甚至是荒诞的。他们提供的某些建议在有些情况下也许是正确的,如果你愿意回到Oracle5版或者6版的年代;但是这些建议在Oracle7.0,8.0 或者 Oracle8i以后往往是完全错误的。 后来基于类似问题触发了互联网内Oracle顶级高手的一系列深入讨论,TOM、Jonathan Lewis、HJR等人都参与其中,在我的网站上(www.eygle.com )上对这些内容及相关链接作了简要介绍,有兴趣的可以参考。 HJR给我们提了很好的一个提示:对你所需要调整的内容,你必须具有充分的认识,否则你做出的判断就有可能是错误的。 这也是我想给自己和大家的一个建议: 学习和研究Oracle,严谨和认真必不可少。 当然 你还需要勤奋,我所熟悉的在Oracle领域有所成就的技术人员,他们共同的特点就是勤奋。 如果你觉得掌握的东西没有别人多,那么也许就是因为,你不如别人勤奋。 要是你觉得这一切过于复杂了,那我还有一句简单的话送给大家: 不积跬步,无以至千里。学习正是在逐渐积累过程中的提高。 现在Itpub给我们提供了很好的交流场所,很多问题都可以在这里找到答案,互相讨论,互相学习。这是我们的幸运,我也因此非常感谢这个网络时代。 参考书籍: 如果是一个新人可以先买一些基本的入门书籍,比如MySQL:《 深入浅出MySQL——数据库开发、优化与管理维护 》,在进阶一点的就是《 高性能MySQL(第3版) 》 oracle的参考书籍: http://www.eygle.com/archives/2006/08/oracle_fundbook_recommand.html 最后建议不要在数据库中使用外键,让应用程序来保证。 ------------------------- Re:回 9楼(千鸟) 的帖子 我有一个问题想问问,现在在做一个与图书有关的项目,其中有一个功能是按图书书名搜索相似图书列表,问题不难,但是想优化一下,有如下问题想请教一下: 1、在图书数据库数据表的书名字段里,按图书书名进行关键字搜索,如何快速搜索相关的图书?   现在由于数据不多,直接用的like模糊查找验证功能而已; 如果数据量不大,是可以在数据库中完成搜索的,可以在搜索字段上创建索引,然后进行搜索查询: CREATE TABLE `book` (   `book_id` int(11) NOT NULL AUTO_INCREMENT,   `book_name` varchar(100) NOT NULL,   .............................   PRIMARY KEY (`book_id`),   KEY `ind_name` (`book_name`) ) ENGINE=InnoDB select book.*  from book , (select book_id from book where book_name like '%算法%')  book_search_id  where book.book_id=book_search_id.book_id; 但是当数据量变得很大后,就不在适合了,可以采用一些其他的第三方搜索技术比如sphinx; 2、如何按匹配的关键度进行快速排序?比如搜索“算法”,有一本书是《算法》,另一本书是《算法设计》,要求前者排在更前面。 现在的排序是根据数据表中的主键序号id进行的排序,没有达到想要的效果。 root@127.0.0.1 : test 15:57:12> select book_id,book_name from book_search where book_name like '%算%' order by book_name; +---------+--------------+ | book_id | book_name    | +---------+--------------+ |       2 | 算法       | |       1 | 算法设计 | ------------------------- 回 10楼(大黑豆) 的帖子 模糊查询分为半模糊和全模糊,也就是: select * from book where name like 'xxx%';(半模糊) select * from book where name like '%xxx%';(全模糊) 半模糊可以可以使用到索引,全模糊在上面场景是不能使用到索引的,但可以进行一些改进,比如: select book.*  from book , (select book_id from book where book_name like '%算法%')  book_search_id   where book.book_id=book_search_id.book_id; 注意这里book_id是主键,同时在book_name上创建了索引 上面的sql语句可以利用全索引扫描来完成优化,但是性能不会太好;特别在数据量大,请求频繁的业务场景下不要在数据库进行模糊查询; 非得使用数据库的话 ,建议不要在生产库进行查询,可以在只读节点进行查询,避免查询造成主业务数据库的资源消耗完,导致故障. 可以使用一些开源的搜索引擎技术,比如sphinx. ------------------------- 回 11楼(蓝色之鹰) 的帖子 我想问下,sql优化一般从那几个方面入手?多表之间的连接方式:Nested Loops,Hash Join 和 Sort Merge Join,是不是Hash Join最优连接? SQL优化需要了解优化器原理,索引的原理,表的存储结构,执行计划等,可以买一本书来系统的进行学习,多多实验; 不同的数据库优化器的模型不一样,比如oracle支持NL,HJ,SMJ,但是mysql只支持NL,不通的连接方式适用于不同的应用场景; NL:对于被连接的数据子集较小的情况,嵌套循环连接是个较好的选择 HJ:对于列连接是做大数据集连接时的常用方式 SMJ:通常情况下散列连接的效果都比排序合并连接要好,然而如果行源已经被排过序,在执行排序合并连接时不需要再排序了,这时排序合并连接的性能会优于散列连接 ------------------------- Re:回 19楼(原远) 的帖子 有个问题:分类表TQueCategory,问题表TQuestion(T-SQL) CREATE TABLE TQueCategory ( ID INT IDENTITY(1,1) PRIMARY KEY,        --问题分类ID NAME VARCHAR(20)        --问题分类名称 ) CREATE TABLE TQuestion ( ID INT IDENTITY(1,1) PRIMARY KEY,        --问题ID CateID INT NOT NULL,        --问题分类ID TITLE VARCHAR(50),        --问题标题 CONTENT VARCHAR(500)        --问题内容 ) 当前要统计某个分类下的问题数,有两种方式: 1.每次统计,在TQuestion通过CateID进行分组统计 SELECT CateID,COUNT(1) AS QueNum FROM TQuestion GROUP BY CateID WHERE 1=1 2.在TQueCategory表增加字段QueNum,用于标识该分类下的问题数量 ALTER TABLE TQueCategory ADD QueNum INT SELECT CateID,QueNum FROM TQueCategory 问:在哪种业务应用场景下采用上面哪种方式性能比较好,为什么? ############################################################################################### 方案 一 需要对 TQuestion 的 CateID字段 进行分组 ,可以在 CateID上创建一个索引,这样就可以索引扫描来完成查询; 方案 二 需要对 TQueCategory 进行扫描就可以得出结果,但是必须在问题表有插入,删除的时候维护quenum数量; 单单从SQL的性能来看, 分类表的数量应该是远远小于问题表的数量的,所以方案二的性能会比较好; 但是如果 TQuestion 的插入非常频繁的话,会带来对 TQueCategory的频繁更新,一次 TQuestion 的 insert或deleted就会带来一次 TQueCategory 的update,这个代价其实是蛮高的; 如果这个分类统计的查询不是非常频繁的话,建议还是使用方案一; 同时还可能还会其他的业务逻辑统计需求(例如: CateID +时间),这个时候在把逻辑放到 TQueCategory就不合适了。 ------------------------- 回 20楼(原远) 的帖子 经验之谈,仅供参考 使用外键在开发上确实省去了很多功夫,但是把业务逻辑交由数据库来完成,对后期的维护来说是很麻烦的事情,不利于维护. ------------------------- 回 21楼(玩站网) 的帖子 无关技术方面: 咨询一下,现在mysql新的版本,5.5.45后貌似修改了开源协议。 是否意味着今后我们商业化使用mysql将受到限制? 如果甲骨文真周到那一步,rds是否会受到影响? 一个疑惑: 为什么很少见到有人用mysql正则匹配?性能不好还是什么原因? ######################################## MySQL有商业版 和 社区版,RDS的MySQL采用开源的社区版进行改进,由专门的RDS MySQL源码团队来维护,国内TOP 10的mysql源码贡献者大部分都在RDS,包括了@丁奇 ,@彭立勋 ,@印风 等; 不在数据库中做业务计算,是保证数据库运行稳定的一个好的设计经验; 是否影响性能与你的sql的执行频率,需要参与的计算数据量相关,当然了还包括数据库所在主机的IO,cpu,内存等资源,离开了这些谈性能是没有多大意义的; ------------------------- 回 22楼(比哥) 的帖子 分页该怎么优化才行??? ######################### 可以参考这个链接,里面有很多的最佳实践,其中就包括了分页语句的优化: http://bbs.aliyun.com/read/168647.html?spm=5176.7114037.1996646101.1.celwA1&pos=1 普通写法: select  *  from t where sellerid=100 limit 100000,20 普通limit M,N的翻页写法,往往在越往后翻页的过程中速度越慢,原因 mysql会读取表中的前M+N条数据,M越大,性能就越差: 优化写法: select t1.* from  t t1,             (select id from t  sellerid=100 limit 100000,20) t2 where t1.id=t2.id; 优化后的翻页写法,先查询翻页中需要的N条数据的主键id,在根据主键id 回表查询所需要的N条数据,此过程中查询N条数据的主键ID在索引中完成 注意:需要在t表的sellerid字段上创建索引 create index ind_sellerid on t(sellerid); 案例: user_A (21:42:31): 这个sql该怎么优化,执行非常的慢: | Query   |   51 | Sending data | select id, ... from t_buyer where sellerId = 765922982 and gmt_modified >= '1970-01-01 08:00:00' and gmt_modified <= '2013-06-05 17:11:31' limit 255000, 5000 SQL改写:selectt2.* from (selectid from t_buyer where sellerId = 765922982   andgmt_modified >= '1970-01-01 08:00:00'   andgmt_modified <= '2013-06-05 17:11:31' limit255000, 5000)t1,t_buyer t2 where t1.id=t2.id index:seller_id,gmt_modified user_A(21:58:43): 好像很快啊。神奇,这个原理是啥啊。牛!!! user_A(21:59:55): 5000 rows in set (4.25 sec), 前面要90秒。 ------------------------- 回 27楼(板砖大叔) 的帖子 这里所说的索引都是普通的b-tree索引,mysql,sqlserver,oracle 的关系数据库都是默认支持的; ------------------------- 回 32楼(veeeye) 的帖子 可以详细说明一下“最后建议不要在数据库中使用外键,让应用程序来保证。 ”的原因吗?我们公司在项目中经常使用外键,用程序来保证不是相对而言更加复杂了吗? 这里的不建议使用外键,主要考虑到 : 第一.维护成本上,把一些业务逻辑交由数据库来保证,当业务需求发生改动的时候,需要同时考虑应用程序和数据库,有时候一些数据库变更或者bug,可能会导致外键的失效;同时也给数据库的管理人员带来维护的麻烦,不便于管理。 第二.性能上考虑,当大量数据写入的时候,外键肯定会带来一定的性能损耗,当出现这样的问题时候,再来改造去除外键,真的就不值得了; 最后,不在数据库中参与业务的计算(存储过程,函数,触发器,外键),是保证数据库运行稳定的一个好的最佳实践。 ------------------------- 回 33楼(优雅的固执) 的帖子 ReDBA专家门诊一期:索引与sql优化 十分想请大师分享下建立索引的经验 我平时简历索引是这样的 比如订单信息的话 建立 订单号  唯一聚集索引 其他的比如   客户编号 供应商编号 商品编号 这些建立非聚集不唯一索引   ################################################## 建立索引,需要根据你的SQL语句来进行创建,不是每一个字段都需要进行创建,也不是一个索引都不创建,,可以把你的SQL语句,应用场景发出来看看。 索引的创建确实是一个非常专业的技术活,需要掌握:表的存储方式,索引的原理,数据库的优化器,统计信息,最后还需要能够读懂数据库的执行计划,以此来判断索引是否创建正确; 所以需要进行系统的学习才能掌握,附件是我在2011年的时候的一次公开课的ppt,希望对你有帮助,同时可以把你平时遇到的索引创建的疑惑发到论坛上来,大家可以一起交流。 ------------------------- 回 30楼(几几届) 的帖子 我也是这样,简单的会,仔细写也会写出来,但是就是不知道有没有更快或者更好的 #################################################### 多写写SQL,掌握SQL优化的方法,自然这些问题不在话下了。 ------------------------- 回 40楼(小林阿小林) 的帖子 mysql如何查询需要优化的语句,比如慢查询的步奏,如何找出需要通知程序员修改或者优化的sql语句 ############################################################ 可以将mysql的慢日志打开,就可以记录执行时间超过指定阀值的慢SQL到本地文件或者数据库的slow_log表中; 在RDS中默认是打开了慢日志功能的:long_query_time=1,表示会记录执行时间>=1秒的慢sql; 如何快速找到mysql瓶颈: 简单一点的方法,可以通过监控mysql所在主机的性能(CPU,IO,load等)以及mysql本身的一些状态值(connections,thread running,qps,命中率等); RDS提供了完善的数据库监控体系,包括了CPU,IOPS,Disk,Connections,QPS,可以重点关注cpu,IO,connections,disk 4个 指标; cpu,io,connections主要体现在了性能瓶颈,disk主要体现了空间瓶颈; 有时候一条慢sql语句的频繁调用,也可能导致整个实例的cpu,io,connections达到100%;也有可能一条排序的sql语句,消耗大量的临时空间,导致实例的空间消耗完。 ------------------------- 下面是分析一个cpu 100%的案例分析:该实例的cpu已经到达100% 查看当前数据库的活动会话信息:当前数据库有较多的活跃线程在数据库中执行查看当前数据库正在执行的sql: 可以看到这条sql执行的非常缓慢:[tr=rgb(100, 204, 255)]delete from task_process where task_id='1801099' 查看这个表的索引: CREATE TABLE `task_process` (  `id` int(11) NOT NULL AUTO_INCREMENT,    ................  `task_id` int(11) NOT NULL DEFAULT '0' COMMENT '??????id',   ................  PRIMARY KEY (`id`),  KEY `index_over_task` (`is_over`,`task_id`),  KEY `index_over` (`is_over`,`is_auto`) USING BTREE,  KEY `index_process_sn` (`process_sn`,`is_over`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=32129710; 可以看到这个表有3KW的数据,但是没有task_id字段开头的索引,导致该sql语句删除需要进行全表扫描: 在我们的诊断报告中已经将该sql语句捕获到,同时给你提出该怎样进行索引的添加。 广告:诊断报告将会在1月底发布到控制台,到时候用户可以直接查看诊断建议,来完成你的数据库优化。 ------------------------- 回 45楼(dentrite) 的帖子 datetime和int都是占用数据库4个字节,所以在空间上没有什么差别;但是为了可读性,建议还是使用datetime数据类型。 ------------------------- 回 48楼(yuantel) 的帖子 麻烦把ecs_brand和ecs_goods的表结构发出来一下看看 。 ------------------------- 回 51楼(小林阿小林) 的帖子 普通的 ECS服务器上目前还没有这样的慢SQL索引建议的工具。 不过后续有IDBCloud将会集成这样的sql诊断功能,使用他来管理ECS上的数据库就可以使用这样的功能了 。

玄惭 2019-12-02 01:16:11 0 浏览量 回答数 0

回答

转自:阿飞的博客 一、数据库技术选型的思考维度 我们做选型的时候首先要问: 谁选型?是负责采购的同学、 DBA 还是业务研发? 如果选型的是采购的同学,他们更注重成本,包括存储方式、网络需求等。 如果选型的是 DBA 同学,他们关心的: ① 运维成本 首先是运维成本,包括监控告警是否完善、是否有备份恢复机制、升级和迁移的成本是否高、社区是否稳定、是否方便调优、排障是否简易等; ② 稳定性 其次,DBA会关注稳定性,包括是否支持数据多副本、服务高可用、多写多活等; ③ 性能 第三是性能,包括延迟、QPS 以及是否支持更高级的分级存储功能等; ④ 拓展性 第四是扩展性,如果业务的需求不确定,是否容易横向扩展和纵向扩容; ⑤ 安全 最后是安全,需要符合审计要求,不容易出现 SQL 注入或拖库情况。 ⑥ 其他 除了采购和 DBA之外,后台应用研发的同学同样会关注稳定性、性能、扩展性等问题,同时也非常关注数据库接口是否便于开发,是否便于修改数据库 schema 等问题。 接下来我们来看一下爱奇艺使用的数据库类型: MySQL,互联网业务必备系统; TiDB,爱奇艺的 TiDB 实践会有另外的具体介绍; Redis,KV 数据库,互联网公司标配; Couchbase,这个在爱奇艺用得比较多,但国内互联网公司用得比较少,接下来的部分会详细说明; 其他,比如 MongoDB、图数据库、自研 KV 数据库 HiKV 等; 大数据分析相关系统,比如 Hive、Impala 等等。 可以看到爱奇艺的数据库种类还是很多的,这会造成业务开发的同学可能不太清楚在他的业务场景下应该选用哪种数据库系统。 那么,我们先对这些数据库按照接口(SQL、NoSQL)和面向的业务场景(OLTP、OLAP)这两位维度进行一个简单非严谨的分类。 下图中,左上角是面向 OLTP、支持 SQL 的这样一类系统,例如 MySQL,一般支持事务不同的隔离级别, QPS 要求比较高,延时比较低,主要用于交易信息和关键数据的存储,比如订单、VIP 信息等。 左下角是 NoSQL 数据库,是一类针对特殊场景做优化的系统,schema 一般比较简单,吞吐量较高、延迟较低,一般用作缓存或者 KV 数据库。 整个右侧都是 OLAP 的大数据分析系统,包括 Clickhouse、Impala等,一般支持SQL、不支持事务,扩展性比较好,可以通过加机器增加数据的存储量,响应延迟较长。 还有一类数据库是比较中立的,在数据量比较小的时候性能比较好,在数据量较大或复杂查询的时候性能也不差,一般通过不同的存储引擎和查询引擎来满足不同的业务需求,我们把它叫做 HTAP,TiDB 就是这样一种数据库。 二、iQIYI对数据库的优化与完善 前面我们提到了很多种的数据库,那么接下来就和大家介绍一下在爱奇艺我们是怎么使用这些数据库的。 1、MySQL在爱奇艺的使用 ① MySQL 首先是 MySQL。MySQL 基本使用方式是 master-slave + 半同步,支持每周全备+每日增量备份。我们做了一些基本功能的增强,首先是增强了数据恢复工具 Xtrabackup 的性能。 之前遇到一个情况,我们有一个全量库是 300G 数据,增量库每天 70G 数据,总数据量 700G 左右。我们当时只需要恢复一个表的数据,但该工具不支持单表恢复,且整库恢复需要 5 个小时。 针对这个情况我们具体排查了原因,发现在数据恢复的过程中需要进行多次写盘的 IO 操作并且有很多串行操作,所以我们做了一些优化。例如删减过程中的一些写盘操作,减少落盘并将数据处理并行化,优化后整库恢复耗时减少到 100 分钟,而且可以直接恢复单表数据。 然后是适配 DDL 和 DML 工具到内部系统,gh-ostt 和 oak-online-alter-table 在数据量大的时候会造成 master-slave 延时,所以我们在使用工具的时候也增加了延时上的考虑,实时探测Master-Slave 库之间延时的情况,如果延时较大会暂停工具的使用,恢复到正常水平再继续。 ② MySQL高可用 第二是 MySQL 高可用。Master-slave 加上半同步这种高可用方式不太完善,所以我们参照了 MHA 并进行了改动,采用 master + agent 的方式。Agent 在每一个物理机上部署,可以监控这个物理机上的所有实例的状态,周期性地向 master 发送心跳,Master 会实时监测各个Agent的状态。 如果 MySQL故障,会启动 Binlog 补偿机制,并切换访问域名完成 failover。考虑到数据库跨机房跨地区部署的情况,MHA 的 master 我们也做了高可用设计,众多 master 会通过 raft 组成一个 raft group,类似 TiDB 的 PD 模块。目前 MySQL failover 策略支持三种方式:同机房、同地域跨机房以及跨地域。 ③ MySQL拓展能力 第三是提高MySQL扩展能力,以提供更大容量的数据存储。扩展方式有 SDK,例如开源的 ShardingSphere,在爱奇艺的使用也比较广泛。另外就是 Proxy,开源的就更多了。但是 SDK 和 Proxy 使用的问题是支持的 SQL 语句简单,扩容难度大,依赖较多且运维复杂,所以部分业务已经迁移至 TiDB。 ④ 审计 第四是审计。我们在 MySQL 上做了一个插件获取全量 SQL 操作,后端打到 Kafka,下游再接入包括 Clickhouse 等目标端进行 SQL 统计分析。除此之外还有安全策略,包括主动探索是否有 SQL 注入及是否存在拖库情况等,并触发对应的告警。 MySQL 审计插件最大的问题是如何降低对 MySQL 性能的影响,对此我们进行了一些测试,发现使用 General Log 对性能损耗较大,有 10%~20% 的降低。 于是我们通过接口来获取 MySQL 插件里的监控项,再把监控项放到 buffer 里边,用两级的 RingBuffer 来保证数据的写入不会有锁资源竞争。在这个插件里再启动一个线程,从 RingBuffer 里读取数据并把数据打包写到 FIFO 管道里。 我们在每台 MySQL 的物理机里再启动一个 Agent,从管道里阻塞地读取数据发至 Kafka。优化后我们再次进行压测,在每台机器上有 15 万的更新、删除或插入操作下不会丢失数据,性能损耗一般情况下小于 2%。 目前已经在公司内部的集群上线了一年时间,运行比较稳定,上线和下线对业务没有影响。 ⑤ 分级存储 第五是分级存储。MySQL 里会存一些过程性的数据,即只需要读写最近一段时间存入的数据,过段时间这些数据就不需要了,需要进行定时清理。 分级存储就是在 MySQL 之上又用了其他存储方式,例如 TiDB 或其他 TokuDB,两者之间可以进行数据自动搬迁和自动归档,同时前端通过 SDK + Proxy 来做统一的访问入口。这样一来,业务的开发同学只需要将数据存入 MySQL 里,读取时可能从后端接入的任意数据库读出。这种方式目前只是过渡使用,之后会根据 TiDB 的特性进行逐步迁移。 Redis在爱奇艺的使用 接下来是 Redis。Redis 也是使用 master - slave 这种方式,由于网络的复杂性我们对 Sentinel 的部署进行了一些特殊配置,在多机房的情况下每个机房配置一定数量 Sentinel 来避免脑裂。 备份恢复方面介绍一个我们的特殊场景,虽然 Redis 是一个缓存,但我们发现不少的业务同学会把它当做一个 KVDB 来使用,在某些情况下会造成数据的丢失。 所以我们做了一个 Redis 实时备份功能,启动一个进程伪装成 Redis 的 Slave 实时获取数据,再放到后端的 KV 存储里,例如 ScyllaDB,如果要恢复就可以从 ScyllaDB 里把数据拉出来。 我们在用 Redis 时最大的痛点就是它对网络的延迟或抖动非常敏感。如有抖动造成 Redis Master 超时,会由 Sentinel 重新选出一个新的节点成为 Master,再把该节点上的数据同步到所有 Slave 上,此过程中数据会放在 Master 节点的 Buffer 里,如果写入的 QPS 很高会造成 Buffer 满溢。如果 Buffer 满后 RDB 文件还没有拷贝过去,重建过程就会失败。 基于这种情况,我们对 Redis 告警做了自动化优化,如有大量 master - slave 重建失败,我们会动态调整一些参数,例如把 Buffer 临时调大等, 此外我们还做了 Redis 集群的自动扩缩容功能。 我们在做 Redis 开发时如果是 Java 语言都会用到 Jedis。用 Jedis 访问客户端分片的 Redis 集群,如果某个分片发生了故障或者 failover,Jedis 就会对所有后端的分片重建连接。如果某一分片发生问题,整个 Redis 的访问性能和 QPS 会大幅降低。针对这个情况我们优化了 Jedis,如果某个分片发生故障,就只针对这个分片进行重建。 在业务访问 Redis 时我们会对 Master 绑定一个读写域名,多个从库绑定读域名。但如果我们进行 Master failover,会将读写域名从某旧 Master 解绑,再绑定到新 Master 节点上。 DNS 本身有一个超时时间,所以数据库做完 failover 后业务程序里没有立刻获取到新的 Master 节点的 IP的话,有可能还会连到原来的机器上,造成访问失败。 我们的解决方法是把 DNS 的 TTL 缩短,但对 DNS 服务又会造成很大的压力,所以我们在 SDK 上提供 Redis 的名字服务 RNS,RNS 从 Sentinel 里获取集群的拓扑和拓扑的变化情况,如果集群 failover,Sentinel 会接到通知,客户端就可以通过 RNS 来获取新的 Master 节点的 IP 地址。我们去掉域名,通过 IP 地址来访问整个集群,屏蔽了 DNS 的超时,缩短了故障的恢复时间。 SDK 上还做了一些功能,例如 Load Balance 以及故障检测,比如某个节点延时较高的话会被临时熔断等。 客户端分片的方式会造成 Redis 的扩容非常痛苦,如果客户端已经进行了一定量的分片,之后再增加就会非常艰难。 Redis 在 3.0 版本后会提供 Redis Cluster,因为功能受限在爱奇艺应用的不是很多,例如不支持显示跨 DC 部署和访问,读写只在主库上等。 我们某些业务场景下会使用 Redis 集群,例如数据库访问只发生在本 DC,我们会在 DC 内部进行 Cluster 部署。 但有些业务在使用的过程中还是想做 failover,如果集群故障可以切换到其他集群。根据这种情况我们做了一个 Proxy,读写都通过它来进行。写入数据时 Proxy 会做一个旁路,把新增的数据写在 Kafka 里,后台启用同步程序再把 Kafka 里的数据同步到其他集群,但存在一些限制,比如我们没有做冲突检测,所以集群间数据需要业务的同学做单元化。线上环境的Redis Cluster 集群间场景跨 DC 同步 需要 50 毫秒左右的时间。 2、Couchbase在爱奇艺的使用 Redis 虽然提供 Cluster 这种部署方式,但存在一些问题。所以数据量较大的时候(经验是 160G),就不推荐 Redis 了,而是采用另一种存储方式 Couchbase。 Couchbase 在国内互联网公司用的比较少,一开始我们是把他当做一个 Memcached 来使用的,即纯粹的缓存系统。 但其实它性能还是比较强大的,是一个分布式高性能的 KV 系统,支持多种存储引擎 (bucket)。第一种是 Memcached bucket,使用方式和 Memcached 一样为 KV 存储,不支持数据持久化也没有数据副本,如果节点故障会丢失数据; 第二种是 Couchbase bucket,支持数据持久化,使用 Json 写入,有副本,我们一般会在线上配置两个副本,如果新加节点会对数据进行 rebalance,爱奇艺使用的一般是 Couchbase bucket 这种配置。 Couchbase 数据的分布如下图,数据写入时在客户端上会先进行一次哈希运算,运算完后会定位 Key 在哪一个 vBucket (相当于数据库里的某个分片)。之后客户端会根据 Cluster Map 发送信息至对应的服务端,客户端的 Cluster Map 保存的是 vBucket 和服务器的映射关系,在服务端数据迁移的过程中客户端的 Cluster Map 映射关系会动态更新,因此客户端对于服务端的 failover 操作不需要做特殊处理,但可能在 rebalance 过程中会有短暂的超时,导致的告警对业务影响不大。 Couchbase 在爱奇艺应用比较早,2012 年还没有 Redis Cluster 的时候就开始使用了。集群管理使用 erlang 语言开发,最大功能是进行集群间的复制,提供多种复制方式:单向、双向、星型、环式、链式等。 爱奇艺从最初的 1.8 版本使用到如今的 5.0 版本,正在调研的 6.0,中间也遇到了很多坑,例如 NTP 时间配置出错会导致崩溃,如果每个集群对外 XDCR 并发过高导致不稳定,同步方向变更会导致数据丢失等等,我们通过运维和一些外部工具来进行规避。 Couchbase 的集群是独立集群,集群间的数据同步通过 XDCR,我们一般配置为双向同步。对于业务来说,如果 Cluster 1 写入, Cluster 2 不写入,正常情况下客户端会写 Cluster 1。如果 Cluster 1 有故障,我们提供了一个 Java SDK,可以在配置中心把写入更改到 Cluster 2,把原来到 Cluster 1 的连接逐步断掉再与Cluster 2 新建连接。这种集群 failover 的过程对于客户端来说是相对透明和无感的。 3、爱奇艺自研数据库HiKV的使用 Couchbase 虽然性能非常高,并且数据的存储可以超过内存。但是,如果数据量超过内存 75% 这个阈值,性能就会下降地特别快。在爱奇艺,我们会把数据量控制在可用内存的范围之内,当做内存数据库使用。但是它的成本非常高,所以我们后面又开发了一个新的数据库—— HiKV。 开发 HiKV 的目的是为了把一些对性能要求没那么高的 Couchbase 应用迁移到 HiKV 上。HiKV 基于开源系统 ScyllaDB,主要使用了其分布式数据库的管理功能,增加了单机存储引擎 HiKV。 ScyllaDB 比较吸引人的是它宣称性能高于 Cassandra 十倍,又完全兼容 Cassandra 接口,设计基本一致,可以视为 C++ 版 Cassandra 系统。 ScyllaDB 性能的提升主要是使用了一些新的技术框架,例如 C++ 异步框架 seastar,主要原理是在j每台物理机的核上会 attach 一个应用线程,每个核上有自己独立的内存、网络、IO 资源,核与核之间没有数据共享但可以通信,其最大的好处是内存访问无锁,没有冲突过程。 当一个数据读或写到达 ScyllaDB 的 server 时,会按照哈希算法来判断请求的 Key 是否是该线程需要处理的,如果是则本线程处理,否则会转发到对应线程上去。 除此之外,它还支持多副本、多数据中心、多写多活,功能比较强大。 在爱奇艺,我们基于 SSD 做了一个 KV 存储引擎。Key 放在内存里,Value 放在盘上的文件里,我们在读和写文件时,只需要在内存索引里定位,再进行一次盘的 IO 开销就可以把数据读出来,相比 ScyllaDB 原本基于 LSM Tree 的存储引擎方式对 IO 的开销较少。 索引数据全部放在内存中,如果索引长度较长会限制单机可存储的数据量,于是我们通过开发定长的内存分布器,对于比较长的 Key 做摘要缩短长度至 20 字节,采用红黑树索引,限制每条记录在内存里的索引长度至为 64 字节。内存数据要定期做 checkpoint,客户端要做限流、熔断等。 HiKV 目前在爱奇艺应用范围比较大,截至目前已经替换了 30% 的 Couchbase,有效地降低了存储成本。 4、爱奇艺的数据库运维管理 爱奇艺数据库种类较多,如何高效地运维和管理这些数据库也是经历了不同的阶段。 最初我们通过 DBA 写脚本的方式管理,如果脚本出问题就找 DBA,导致了 DBA 特别忙碌。 第二个阶段我们考虑让大家自己去查问题的答案,于是在内部构建了一个私有云,通过 Web 的方式展示数据库运行状态,让业务的同学可以自己去申请集群,一些简单的操作也可以通过自服务平台实现,解放了 DBA。一些需要人工处理的大型运维操作经常会造成一些人为故障,敲错参数造成数据丢失等。 于是在第三个阶段我们把运维操作 Web 化,通过网页点击可以进行 90% 的操作。 第四个阶段让经验丰富的 DBA 把自身经验变成一些工具,比如有业务同学说 MySQL master-slave 延时了,DBA 会通过一系列操作排查问题。现在我们把这些操作串起来形成一套工具,出问题时业务的同学可以自己通过网页上的一键诊断工具去排查,自助进行处理。 除此之外我们还会定期做预警检查,对业务集群里潜在的问题进行预警报告;开发智能客服,回答问题;通过监控的数据对实例打标签,进行削峰填谷地智能调度,提高资源利用率。 三、不同场景下数据库选型建议 1、实用数据库选型树 最后来说一些具体数据库选型建议。这是 DBA 和业务一起,通过经验得出来的一些结论。 对于关系型数据库的选型来说,可以从数据量和扩展性两个维度考虑,再根据数据库有没有冷备、要不要使用 Toku 存储引擎,要不要使用 Proxy 等等进行抉择。 NoSQL 也是什么情况下使用 master-slave,什么情况下使用客户端分片、集群、Couchbase、HiKV 等,我们内部自服务平台上都有这个选型树信息。 2、一些思考 ① 需求 我们在选型时先思考需求,判断需求是否真实。 你可以从数据量、QPS、延时等方面考虑需求,但这些都是真实需求吗?是否可以通过其他方式把这个需求消耗掉,例如在数据量大的情况下可以先做数据编码或者压缩,数据量可能就降下来了。 不要把所有需求都推到数据库层面,它其实是一个兜底的系统。 ② 选择 第二个思考的点是对于某个数据库系统或是某个技术选型我们应该考虑什么?是因为热门吗?还是因为技术上比较先进?但是不是能真正地解决你的问题?如果你数据量不是很大的话就不需要选择可以存储大数据量的系统。 ③ 放弃 第三是放弃,当你放弃一个系统时真的是因为不好用吗?还是没有用好?放弃一个东西很难,但在放弃时最好有一个充分的理由,包括实测的结果。 ④ 自研 第四是自研,在需要自己开发数据库时可以参考和使用一些成熟的产品,但不要盲目自研。 ⑤ 开源 最后是开源,要有拥抱开源的态度。

茶什i 2019-12-27 14:17:56 0 浏览量 回答数 0

问题

【每日一题】SQL 知识大测验 | 持续更新

茶什i 2019-12-01 22:03:05 20900 浏览量 回答数 37

回答

一。zval、引用计数、变量分离、写时拷贝我们一步步来理解1、php语言特性PHP是脚本语言,所谓脚本语言,就是说PHP并不是独立运行的,要运行PHP代码需要PHP解析器,用户编写的PHP代码最终都会被PHP解析器解析执行PHP的执行是通过Zend engine(ZE, Zend引擎),ZE是用C编写的用户编写的PHP代码最终都会被翻译成PHP的虚拟机ZE的虚拟指令(OPCODES)来执行也就说最终会被翻译成一条条的指令既然这样,有什么结果和你预想的不一样,查看php源码是最直接最有效的 2、php变量的存储结构在PHP中,所有的变量都是用一个结构zval结构来保存的,在Zend/zend.h中可以看到zval的定义:zval结构包括:① value —— 值,是真正保存数据的关键部分,定义为一个联合体(union)② type —— 用来储存变量的类型 ③ is_ref —— 下面介绍④ refcount —— 下面介绍 声明一个变量$addr="北京";PHP内部都是使用zval来表示变量的,那对于上面的脚本,ZE是如何把addr和内部的zval结构联系起来的呢?变量都是有名字的(本例中变量名为addr)而zval中并没有相应的字段来体现变量名。PHP内部肯定有一个机制,来实现变量名到zval的映射在PHP中,所有的变量都会存储在一个数组中(确切的说是hash table)当你创建一个变量的时候,PHP会为这个变量分配一个zval,填入相应的信息,然后将这个变量的名字和指向这个zval的指针填入一个数组中。当你获取这个变量的时候,PHP会通过查找这个数组,取得对应的zval 注意:数组和对象这类复合类型在生成zval时,会为每个单元生成一个zval3、我们经常说每个变量都有一个内存地址,那这个zval和变量的内存地址,这俩有什么关系吗?定义一个变量会开辟一块内存,这块内存好比一个盒子,盒子里放了zval,zval里保存了变量的相关信息,需要开辟多大的内存,是由zval所占空间大小决定的zval是内存对象,垃圾回收的时候会把zval和内存地址(盒子)分别释放掉 4、引用计数、变量分离、写时拷贝zval中的refcount和is_ref还没有介绍,我们知道PHP是一个长时间运行的服务器端脚本。那么对于它来说,效率和资源占用率是一个很重要的衡量标准,也就是说,PHP必须尽量减少内存占用率。考虑下面这段代码:第一行代码创建了一个字符串变量,申请了一个大小为9字节的内存,保存了字符串“laruence”和一个NULL(0)的结尾第二行定义了一个新的字符串变量,并将变量var的值“复制”给这个新的变量第三行unset了变量var 这样的代码是很常见的,如果PHP对于每一个变量赋值都重新分配内存,copy数据的话,那么上面的这段代码就要申请18个字节的内存空间,为了申请新的内存,还需要cpu执行某些计算,这当然会加重cpu的负载而我们也很容易看出来,上面的代码其实根本没有必要申请两份空间,当第三句执行后,$var被释放了,我们刚才的设想(申请18个字节内存空间)突然变的很滑稽,这次复制显得好多余。如果早知道$var不用了,直接让$var_dup用$var的内存不就行了,还复制干嘛?如果你觉得9个字节没什么,那设想下如果$var是个10M的文件内容,或者20M,是不是我们的计算机资源消耗的有点冤枉呢?呵呵,PHP的开发者也看出来了: 刚才说了,PHP中的变量是用一个存储在symbol_table中的符号名,对应一个zval来实现的,比如对于上面的第一行代码,会在symbol_table中存储一个值“var”,对应的有一个指针指向一个zval结构,变量值“laruence”保存在这个zval中,所以不难想象,对于上面的代码来说,我们完全可以让“var”和“var_dup”对应的指针都指向同一个zval就可以了(额,鸟哥一会说hash table,一会说symbol_table,暂且理解为symbol_table是hash table的子集) PHP也是这样做的,这个时候就需要介绍一下zval结构中的refcount字段了refcount,引用计数,记录了当前的zval被引用的次数(这里的引用并不是真正的 & ,而是有几个变量指向它)比如对于代码:第一行,创建了一个整形变量,变量值是1。 此时保存整形1的这个zval的refcount为1第二行,创建了一个新的整形变量(通过赋值的方式),变量也指向刚才创建的zval,并将这个zval的refcount加1,此时这个zval的refcount为2所以,这个时候(通过值传递的方式赋值给别的变量),并没有产生新的zval,两个变量指向同一zval,通过一个计数器来共用zval及内存地址,以达到节省内存空间的目的当一个变量被第一次创建的时候,它对应的zval结构的refcount的值会被初始化为1,因为只有这一个变量在用它。但是当你把这个变量赋值给别的变量时,refcount属性便会加1变成2,因为现在有两个变量在用这个zval结构了 PHP提供了一个函数可以帮助我们了解这个过程debug_zval_dump输出:long(1) refcount(2)long(1) refcount(3)如果你奇怪 ,var的refcount应该是1啊?我们知道,对于简单变量,PHP是以传值的形式传参数的。也就是说,当执行debug_zval_dump($var)的时候,$var会以传值的方式传递给debug_zval_dump,也就是会导致var的refcount加1,所以只要能看到,当变量赋值给一个变量以后,能导致zval的refcount加1这个结果即可现在我们回头看上面的代码, 当执行了最后一行unset($var)以后,会发生什么呢?unset($var)的时候,它删除符号表里的$var的信息,准备清理它对应的zval及内存空间,这时它发现$var对应的zval结构的refcount值是2,也就是说,还有另外一个变量在一起用着这个zval,所以unset只需把这个zval的refcount减去1就行了上代码:输出:string(8) "laruence" refcount(2) 但是,对于下面的代码呢?很明显在这段代码执行以后,$var_dup的值应该还是“laruence”,那么这又是怎么实现的呢?这就是PHP的copy on write机制(简称COW):PHP在修改一个变量以前,会首先查看这个变量的refcount,如果refcount大于1,PHP就会执行一个分离的过程(在Zend引擎中,分离是破坏一个引用对的过程)对于上面的代码,当执行到第三行的时候,PHP发现$var想要改变,并且它指向的zval的refcount大于1,那么PHP就会复制一个新的zval出来,改变其值,将改变的变量指向新的zval(哪个变量指向新复制的zval其实已经无所谓了),并将原zval的refcount减1,并修改symbol_table里该变量的指针,使得$var和$var_dup分离(Separation)。这个机制就是所谓的copy on write(写时复制,这里的写包括普通变量的修改及数组对象里的增加、删除单元操作)如果了解了is_ref之后,上面说的并不严谨 上代码测试:输出:long(1) refcount(2)string(8) "laruence" refcount(2) 现在我们知道,当使用变量复制的时候 ,PHP内部并不是真正的复制,而是采用指向相同的zval结构来节约开销。那么,对于PHP中的引用,又是如何实现呢?这段代码结束以后,$var也会被间接的修改为1,这个过程称作(change on write:写时改变)那么ZE是怎么知道,这次的复制不需要Separation呢?这个时候就要用到zval中的is_ref字段了:对于上面的代码,当第二行执行以后,$var所代表的zval的refcount变为2,并且设置is_ref为1到第三行的时候,PHP先检查var_ref对应的zval的is_ref字段(is_ref 表示该zval是否被&引用,仅表示真或假,就像开关的开与关一样,zval的初始化情况下为0,即非引用),如果为1,则不分离,直接更改(否则需要执行刚刚提到的zval分离),更改共享的zval实际上也间接更改了$var的值,因为引擎想所有的引用变量都看到这一改变php源码做了这样一个判断,大体逻辑示意如下:如果这个zval中的if_ref为1(即被引用),或者该zval引用计数小于2任何一种方式:都不会进行分离 尽管已经存在写时复制和写时改变,但仍然还存在一些不能通过is_ref和refcount来解决的问题对于如下的代码,又会怎样呢?这里$var、$var_dup、$var_ref三个变量将共用一个zval结构(其实这是不可能的,一个zval不可能既被&,又被指向),有两个属于change-on-write组合($var和$var_ref),有两个属于copy-on-write组合($var和$var_dup),那is_ref和refcount该怎样工作,才能正确的处理好这段复杂的关系呢?答案是不可能!在这种情况下,变量的值必须分离成两份完全独立的存在当执行第二行代码的时候,和前面讲过的一样,$var_dup 和 $var 指向相同的zval, refcount为2当执行第三行的时候,PHP发现要操作的zval的refcount大于1,则PHP会执行Separation(也就是说php将一个zval的is_ref从0设为1 之前,当然此时refcount还没有增加,会看该zval的refcount,如果refcount>1,则会分离), 将$var_dup分离出去,并将$var和$var_ref做change on write关联。也就是,refcount=2, is_ref=1;所以内存会给变量var_dup 分配出一个新的zval,类型与值同 $var和$var_ref指向的zval一样,是新分配出来的,尽管他们拥有同样的值,但是必须通过两个zval来实现。试想一下,如果三者指向同一个zval的话,改边 $var_dup 的值,那么 $var和$var_ref 也会受到影响,这样就乱套了图解:下面的这段代码在内核中同样会产生歧义,所以需要强制复制!也就是说一个zval不会既被引用,又被指向,必须分离 基于这样的分析,我们就可以让debug_zval_dump出refcount为1的结果来:输出:string(8) "laruence" refcount(1) 为什么结果是refcount(1)呢debug_zval_dump()中参数是引用的话,refcount永远为1这两段代码在执行的时候是这样的逻辑:PHP先看变量指向的zval是否被引用,如果是引用,则不再产生新的zval甭管哪个变量引用了它,比如有个变量$a被引用了,$b=&$a,就算自己引用自己$a=&$a,$a所指向的zval都不会被复制,改变其中一个变量的值,另一个值也被改变(写时改变)如果is_ref为0且refcount大于1,改变其中一个变量时,复制新的zval(写时复制) 还有一个知识点需要了解下,就是PHP数组复制的机制复制一个数组,就是把一个数组赋值给一个变量便可。会把数组指针位置一同复制。这里面有两种情况:① 指针位置合法,这时直接复制,无影响② 原数组指针位置非法时(移出界),“新”数组指针会初始化(这里的新为什么要加引号?请看下文),而老的数组指针位置不变,还是false先看例子: 结果:!结果:出现这种情况好像不对?$arr2 难道不是新数组?新数组的数组指针应该重置了啊这里注意了:$arr2 = $arr1 ,在俩变量都没发生写操作时,他们其实引用的是同一个内存地址。在其中一个变量发生写操作后,内存地址会复制一份,发生改变的变量会去引用它,并把数组指针初始化。所以 $arr1 会去引用复制的内存地址,并将指针初始化二。.foreach循环时调用current等函数!结果: 56按照之前说的,foreach先赋值,再移动指针,再执行循环体,第一次结果为2可以理解为什么三次都是2呢?咋就这么2呢?因为current函数是按引用传递的函数 在zval笔记中说了,一个zval不能既被引用,又被指向所以,变量分离,重新拷贝一份数组专门用于current函数 当然,如果数组zval的is_ref为1,则不会拷贝数组了或者:结果:current是引用传参

杨冬芳 2019-12-02 02:26:33 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 云栖号物联网 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 云栖号弹性计算 阿里云云栖号 云栖号案例 云栖号直播