即内容分发网络,其目的是通过在现有的Internet中增加一层新的网络架构,将网站的内容发布到最接近用户的网络边缘,使用户可就近取得所需的内容,提高用户访问网站的速度
灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式
AB test就是一种灰度发布方式,让一部用户继续用A,一部分用户开始用B
如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面 来灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度
知道RabbitMQ吗?
RabbitMQ也就是消息队列中间件,消息中间件是在消息的传息过程中保存消息的容器,消息中间件再将消息从它的源中到它的目标中标时充当中间人的作用
队列的主要目的是提供路由并保证消息的传递;如果发送消息时接收者不可用消息队列不会保留消息,直到可以成功地传递为止,当然,消息队列保存消息也是有期限地
Keepalived的工作原理?
在一个虚拟路由器中,只有作为MASTER的VRRP路由器会一直发送VRRP通告信息, BACKUP不会抢占MASTER,除非它的优先级更高。当MASTER不可用时(BACKUP收不到通告信息)
多台BACKUP中优先级最高的这台会被抢占为MASTER。这种抢占是非常快速的(<1s),以保证服务的连续性,于安全性考虑,VRRP包使用了加密协议进行加密。BACKUP不会发送通告信息,只会接收通告信息
keepalive的工作原理和如何做到健康检查
keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议。
虚拟路由冗余协议,可以认为是实现路由器高可用的协议,即将N台提供相同功能的路由器组成一个路由器组
这个组里面有一个master和多个backup,master上面有一个对外提供服务的vip(该路由器所在局域网内其他机器的默认路由为该vip),master会发组播,当backup收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级来选举一个backup当master。这样就可以保证路由器的高可用了
keepalived主要有三个模块,分别是core、check和vrrp。core模块为keepalived的核心,负责主进程的启动、维护及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式,vrrp模块是来实现VRRP协议的。
Nginx的优点是:
1、工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构。它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。
2、Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,这个也是它的优势之一,相反LVS对网络稳定性依赖比较大;
3、Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来LVS的配置、测试就要花比较长的时间了,LVS对网络依赖比较大。
4、可以承担高负载压力且稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载度比LVS相对小些。
5、Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了。
如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。
6、Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器,LNMP也是近几年非常流行的web架构,在高流量的环境中稳定性也很好。
7、Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可考虑用其作为反向代理加速器
8、Nginx可作为中层反向代理使用,这一层面Nginx基本上无对手,唯一可以对比Nginx的就只有lighttpd了,不过lighttpd目前还没有做到Nginx完全的功能,配置也不那么清晰易读,社区资料也远远没Nginx活跃
9、Nginx也可作为静态网页和图片服务器,这方面的性能也无对手。还有Nginx社区非常活跃,第三方模块也很多
Nginx的缺点是:
1、Nginx仅能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点
2、对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测,不支持Session的直接保持,但能通过ip_hash来解决
HAProxy的特点是:
我们用其作为解决session问题的一种方法;
LVS、Nginx、HAproxy有什么区别?工作中你怎么选择?
LVS: 是基于四层的转发
HAproxy: 是基于四层和七层的转发,是专业的代理服务器
Nginx: 是WEB服务器,缓存服务器,又是反向代理服务器,可以做七层的转发
区别: LVS由于是基于四层的转发所以只能做端口的转发而基于URL的、基于目录的这种转发LVS就做不了
工作选择:
HAproxy和Nginx由于可以做七层的转发,所以URL和目录的转发都可以做在很大并发量的时候我们就要选择LVS,像中小型公司的话并发量没那么大选择HAproxy或者Nginx足已,由于HAproxy由是专业的代理服务器配置简单,所以中小型企业推荐使用HAproxy
command ping yum copy service shell file replace user group
nginx的优化
gzip压缩优化
expires缓存
网络IO事件模型优化
隐藏软件名称和版本号
防盗链优化
禁止恶意域名解析
禁止通过IP地址访问网站
HTTP请求方法优化
防DOS攻击单IP并发连接的控制,与连接速率控制
严格设置web站点目录的权限
将nginx进程以及站点运行于监牢模式
通过robot协议以及HTTP_USER_AGENT防爬虫优化
配置错误页面根据错误码指定网页反馈给用户
nginx日志相关优化访问日志切割轮询,不记录指定元素日志、最小化日志目录权限
限制上传到资源目录的程序被访问,防止木马入侵系统破坏文件
FastCGI参数buffer和cache配置文件的优化
php.ini和php-fpm.conf配置文件的优化
有关web服务的Linux内核方面深度优化(网络连接、IO、内存等)
nginx加密传输优化(SSL)
web服务器磁盘挂载及网络文件系统的优化
Nginx是如何处理一个请求的呢?
首先,nginx启动会解析配置文件,得到需要监听的端口与ip地址,然后在nginx的master进程里面;先初始化好这个监控的socket,再进行listen
然后再fork出多个子进程出来, 子进程会竞争accept新的连接。
此时,客户端就可以向nginx发起连接了。当客户端与nginx进行三次握手,与nginx建立好一个连接后,此时,某一个子进程会accept成功,然后创建nginx对连接的封装,即ngx_connection_t结构体接着,根据事件调用相应的事件处理模块,如http模块与客户端进行数据的交换,最后,nginx或客户端来主动关掉连接,到此,一个连接就寿终正寝了
Nginx的master和worker是如何工作的?
这跟Nginx的多进程、单线程有关。(一个进程只有一个主线程)。
为什么不使用多进程?
pache: 创建多个进程或线程,而每个进程或线程都会为其分配cpu和内存(线程要比进程小的多,所以worker支持比perfork高的并发),并发过大会榨干服务器资源。
nginx: 采用单线程来异步非阻塞处理请求(管理员可以配置Nginx主进程的工作进程的数量),不会为每个请求分配cpu和内存资源,节省了大量资源,同时也减少了大量的CPU的上下文切换,所以才使得Nginx支持更高的并发。
简单过程:
主程序 Master process 启动后,通过一个 for 循环来 接收 和 处理外部信号 ;
主进程通过 fork() 函数产生 worker 子进程 ,每个子进程执行一个 for循环来实现Nginx服务器对事件的接收和处理 。
ngx_http_upstream_module模块了解吗?
ngx_http_upstream_module模块用于将多个服务器定义成服务器组,可通过fastcgi传递、proxy传递、uwsgi传递、memcached传递和scgi传递指令来引用的服务器组。
请解释Nginx如何处理HTTP请求。
Nginx使用反应器模式。主事件循环等待操作系统发出准备事件的信号,这样数据就可以从套接字读取,在该实例中读取到缓冲区并进行处理。单个线程可以提供数万个并发连接。
如何用Nginx解决前端跨域问题?
使用Nginx转发请求。把跨域的接口写成调本域的接口,然后将这些接口转发到真正的请求地址。
Nginx虚拟主机怎么配置?
1、基于域名的虚拟主机,通过域名来区分虚拟主机——应用:外部网站
2、基于端口的虚拟主机,通过端口来区分虚拟主机——应用:公司内部网站,外部网站的管理后台
3、基于ip的虚拟主机。
限流怎么做的?
Nginx限流就是限制用户请求速度,防止服务器受不了。Nginx的限流都是基于漏桶流算法
限流有3种:
正常限制访问频率(正常流量)
限制一个用户发送的请求,我Nginx多久接收一个请求。
Nginx中使用ngx_http_limit_req_module
模块来限制的访问频率,限制的原理实质是基于漏桶算法原理来实现的。在nginx.conf配置文件中可以使用limit_req_zone命令及limit_req命令限制单个IP的请求处理频率。
突发限制访问频率(突发流量)
限制一个用户发送的请求,Nginx多久接收一个。
上面的配置一定程度可以限制访问频率,但是也存在着一个问题:如果突发流量超出请求被拒绝处理,无法处理活动时候的突发流量,这时候应该如何进一步处理呢?Nginx提供burst参数结合nodelay参数可以解决流量突发的问题,可以设置能处理的超过设置的请求数外能额外处理的请求数。可以将之前的例子添加burst参数以及nodelay参数:
限制并发连接数
Nginx中的ngx_http_limit_conn_module
模块提供了限制并发连接数的功能,可以使用limit_conn_zone指令以及limit_conn执行进行配置。
location的作用是什么?
location指令的作用是根据用户请求的URI来执行不同的应用,也就是根据用户请求的网站URL进行匹配,匹配成功即进行相关的操作。
在Nginx中,如何使用未定义的服务器名称来阻止处理请求?
只需将请求删除的服务器就可以定义为:
Server { listen 80; server_name "" ; return 444; }
这里,服务器名被保留为一个空字符串,它将在没有“主机”头字段的情况下匹配请求,而一个特殊的Nginx的非标准代码444被返回,从而终止连接。
Nginx服务器上的Master和Worker进程分别是什么?
如何通过不同于80的端口开启Nginx?
为了通过一个不同的端口开启Nginx,你必须进入/etc/Nginx/sites-enabled/
,如果这是默认文件,那么你必须打开名为“default”的文件。编辑文件,并放置在你想要的端口:
Like server { listen 81; }
是否有可能将Nginx的错误替换为502错误、503?
502 =错误网关
503 =服务器超载
有可能,但是您可以确保fastcgi_intercept_errors被设置为ON,并使用错误页面指令。
stub_status和sub_filter指令的作用是什么?
Nginx是否支持将请求压缩到上游?
可以使用Nginx模块gunzip将请求压缩到上游。gunzip模块是一个过滤器,它可以对不支持“gzip”编码方法的客户机或服务器使用“内容编码:gzip”来解压缩响应。
如何在Nginx中获得当前的时间?
要获得Nginx的当前时间,必须使用SSI模块、date_local的变量。
Proxy_set_header THE-TIME $date_gmt;
Nginx配置高可用性怎么配置?
server { listen 80; server_name www.lijie.com; location / { ### 指定上游服务器负载均衡服务器 proxy_pass http://backServer; ###nginx与上游服务器(真实访问的服务器)超时时间 后端服务器连接的超时时间_发起握手等候响应超时时间 proxy_connect_timeout 1s; ###nginx发送给上游服务器(真实访问的服务器)超时时间 proxy_send_timeout 1s; ### nginx接受上游服务器(真实访问的服务器)超时时间 proxy_read_timeout 1s; index index.html index.htm; } }
Nginx怎么判断别IP不可访问?
# 如果访问的ip地址为192.168.9.115,则返回403 if ($remote_addr = 192.168.9.115) { return 403; }
怎么限制浏览器访问?
## 不允许谷歌浏览器访问 如果是谷歌浏览器返回500 if ($http_user_agent ~ Chrome) { return 500; }
Nginx怎么处理请求的?
nginx接收一个请求后,首先由listen和server_name指令匹配server模块,再匹配server模块里的location,location就是实际地址
server { listen 80; # 提供服务的端口,默认80 server_name localhost; # 提供服务的域名主机名 location / { root html; # 站点的根目录,相当于Nginx的安装目录 index index.html index.htm; # 默认的首页文件,多个用空格分开 } # 第一个location区块结果 }
Nginx目录结构有哪些?
[root@localhost ~]# tree /usr/local/nginx ├── client_body_temp ├── conf # Nginx所有配置文件的目录 ├── fastcgi_temp # fastcgi临时数据目录 ├── html # Nginx默认站点目录 ├── logs # Nginx日志目录 ├── proxy_temp # 临时目录 ├── sbin # Nginx命令目录 │ └── nginx # Nginx的启动命令 ├── scgi_temp # 临时目录 └── uwsgi_temp # 临时目录
常用的Nginx模块,用来做什么
rewrite模块,实现重写功能 access模块:来源控制 ssl模块:安全加密 ngx_http_gzip_module:网络传输压缩模块 ngx_http_proxy_module 模块实现代理 ngx_http_upstream_module 模块实现定义后端服务器列表 ngx_cache_purge 实现缓存清除功能
HAProxy负载均衡策略非常多,常见的有如下8种:
简述负载均衡四层和七层的区别?
四层负载均衡器也称为4层交换机,主要通过分析IP层及TCP/UDP层的流量实现基于IP加端口的负载均衡,如常见的LVS、F5等;
七层负载均衡器也称为7层交换机,位于OSI的最高层,即应用层,此负载均衡器支持多种协议,如HTTP、FTP、SMTP等。7层负载均衡器可根据报文内容,配合一定的负载均衡算法来选择后端服务器,即“内容交换器”。如常见的HAProxy、Nginx。
简述LVS、Nginx、HAproxy的什么异同?
相同:
三者都是软件负载均衡产品。
区别:
简述Keepalived及其工作原理?
Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案,可以解决静态路由出现的单点故障问题。
在一个LVS服务集群中通常有主服务器(MASTER)和备份服务器(BACKUP)两种角色的服务器,但是对外表现为一个虚拟IP,主服务器会发送VRRP通告信息给备份服务器,当备份服务器收不到VRRP消息的时候,即主服务器异常的时候,备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性
Keepalived如何通过健康检查来保证高可用?
Keepalived工作在TCP/IP模型的第三、四和五层,即网络层、传输层和应用层。
网络层,Keepalived采用ICMP协议向服务器集群中的每个节点发送一个ICMP的数据包,如果某个节点没有返回响应数据包,则认为此节点发生了故障,Keepalived将报告次节点失效,并从服务器集群中剔除故障节点。
传输层,Keepalived利用TCP的端口连接和扫描技术来判断集群节点是否正常。如常见的web服务默认端口80,ssh默认端口22等。Keepalived一旦在传输层探测到相应端口没用响应数据返回,则认为此端口发生异常,从而将此端口对应的节点从服务器集群中剔除。
应用层,可以运行FTP、telnet、smtp、dns等各种不同类型的高层协议,Keepalived的运行方式也更加全面化和复杂化,用户可以通过自定义Keepalived的工作方式,来设定监测各种程序或服务是否正常,若监测结果与设定的正常结果不一致,将此服务对应的节点从服务器集群中剔除。
Keepalived通过完整的健康检查机制,保证集群中的所有节点均有效从而实现高可用。
什么是Redis?
Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。
因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。
Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB,不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能。
比方说用他的List来做FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set可以做高性能的tag系统等等。
另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一 个功能加强版的memcached来用。 Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
Redis相比memcached有哪些优势?
Redis支持哪几种数据类型?
String(字符串)
String是简单的 key-value 键值对,value 不仅可以是 String,也可以是数字。String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。
String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。
应用场景
String是最常用的一种数据类型,普通的key/value存储都可以归为此类
List(列表)
Redis列表是简单的字符串列表,可以类比到C++中的std::list,简单的说就是一个链表或者说是一个队列。可以从头部或尾部向Redis列表添加元素。列表的最大长度为2^32 - 1,也即每个列表支持超过40亿个元素。
Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。
应用场景
Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表、粉丝列表等都可以用Redis的list结构来实现,再比如有的应用使用Redis的list类型实现一个简单的轻量级消息队列,生产者push,消费者pop/bpop。
Set(集合)
可以理解为一堆值不重复的列表,类似数学领域中的集合概念,且Redis也提供了针对集合的求交集、并集、差集等操作。
set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。
应用场景
Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
又或者在微博应用中,每个用户关注的人存在一个集合中,就很容易实现求两个人的共同好友功能。
Sorted Set(有序集合)
Redis有序集合类似Redis集合,不同的是增加了一个功能,即集合是有序的。一个有序集合的每个成员带有分数,用于进行排序。
Redis有序集合添加、删除和测试的时间复杂度均为O(1)(固定时间,无论里面包含的元素集合的数量)。列表的最大长度为2^32- 1元素(4294967295,超过40亿每个元素的集合)。
Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
使用场景
Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。
又比如用户的积分排行榜需求就可以通过有序集合实现。还有上面介绍的使用List实现轻量级的消息队列,其实也可以通过Sorted Set实现有优先级或按权重的队列。
hash(字典,哈希表)
Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
应用场景
假设有多个用户及对应的用户信息,可以用来存储以用户ID为key,将用户信息序列化为比如json格式做为value进行保存。
Redis主要消耗什么物理资源?
内存。
Redis官方为什么不提供Windows版本?
因为目前Linux版本已经相当稳定,而且用户量很大,无需开发windows版本,反而会带来兼容性等问题。
一个字符串类型的值能存储最大容量是多少?
512M
为什么Redis需要把所有数据放到内存中?
Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。
所以redis具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。
在内存越来越便宜的今天,redis将会越来越受欢迎。 如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。
Redis集群方案应该怎么做?都有哪些方案?
codis。目前用的最多的集群方案,基本和twemproxy一致的效果,但它支持在 节点数量改变情况下,旧节点数据可恢复到新hash节点。
redis cluster3.0自带的集群,特点在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持节点设置从节点。具体看官方文档介绍。
在业务代码层实现,起几个毫无关联的redis实例,在代码层,对key 进行hash计算,然后去对应的redis实例操作数据。 这种方式对hash层代码要求比较高,考虑部分包括,节点失效后的替代算法方案,数据震荡后的自动脚本恢复,实例的监控,等等。
Redis集群方案什么情况下会导致整个集群不可用?
有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用。
MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据?
redis内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。
Redis有哪些适合的场景?
会话缓存(Session Cache)
最常用的一种使用Redis的情景是会话缓存(session cache)。用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,他们还会这样吗?
幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。
全页缓存(FPC)
除基本的会话token之外,Redis还提供很简便的FPC平台。回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC。
再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。
此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。
队列
Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。
如果你快速的在Google中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为broker,你可以从这里去查看。
排行榜/计数器
Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。
发布/订阅
最后(但肯定不是最不重要的)是Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统!
Redis支持的Java客户端都有哪些?官方推荐用哪个?
Redisson、Jedis、lettuce等等,官方推荐使用Redisson。
Redis和Redisson有什么关系?
Redisson是一个高级的分布式协调Redis客服端,能帮助用户在分布式环境中轻松实现一些Java的对象
Jedis与Redisson对比有什么优缺点?
Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持;
Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。
Redis如何设置密码及验证密码?
设置密码:config set requirepass 123456
授权密码:auth 123456
说说Redis哈希槽的概念?
Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。
Redis集群的主从复制模型是怎样的?
为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品.
Redis集群会有写操作丢失吗?为什么?
Redis并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可能会丢失写操作。
redis的过期策略以及内存淘汰机制
比如你redis只能存5G数据,可是你写了10G,那会删5G的数据。怎么删的,这个问题思考过么?还有,你的数据已经设置了过期时间,但是时间到了,内存占用率还是比较高,有思考过原因么?
回答:
redis采用的是定期删除+惰性删除策略。
为什么不用定时删除策略?
定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略.
定期删除+惰性删除是如何工作的呢?
定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。
于是,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。
采用定期删除+惰性删除就没其他问题了么?
不是的,如果定期删除没删除key。然后你也没即时去请求key,也就是说惰性删除也没生效。这样,redis的内存会越来越高。那么就应该采用内存淘汰机制。
在redis.conf中有一行配置 maxmemory-policy volatile-lru
。该配置就是配内存淘汰策略的;
ps:如果没有设置 expire 的key, 不满足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致。
redis和数据库双写一致性问题
一致性问题是分布式常见问题,还可以再分为最终一致性和强一致性。数据库和缓存双写,就必然会存在不一致的问题。答这个问题,先明白一个前提。就是如果对数据有强一致性要求,不能放缓存。我们所做的一切,只能保证最终一致性。另外,我们所做的方案其实从根本上来说,只能说降低不一致发生的概率,无法完全避免。因此,有强一致性要求的数据,不能放缓存。
首先,采取正确更新策略,先更新数据库,再删缓存。其次,因为可能存在删除缓存失败的问题,提供一个补偿措施即可,例如利用消息队列。
如何应对缓存穿透和缓存雪崩问题
这两个问题,说句实在话,一般中小型传统软件企业,很难碰到这个问题。如果有大并发的项目,流量有几百万左右。这两个问题一定要深刻考虑。
缓存穿透,即黑客故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。
解决方案:
利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试
采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。
提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。
缓存雪崩,即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。
解决方案:
给缓存的失效时间,加上一个随机值,避免集体失效。
使用互斥锁,但是该方案吞吐量明显下降了。
双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时间。自己做缓存预热操作。然后细分以下几个小点
从缓存A读数据库,有则直接返回
A没有数据,直接从B读数据,直接返回,并且异步启动一个更新线程。
更新线程同时更新缓存A和缓存B。
使用redis有什么缺点
大家用redis这么久,这个问题是必须要了解的,基本上使用redis都会碰到一些问题,常见的也就几个。
主要是四个问题
单线程的redis为什么这么快
这个问题其实是对redis内部机制的一个考察。其实根据博主的面试经验,很多人其实都不知道redis是单线程工作模型。所以,这个问题还是应该要复习一下的。
主要是以下三点
如何解决redis的并发竞争key问题
分析:这个问题大致就是,同时有多个子系统去set一个key。这个时候要注意什么呢?大家思考过么。需要说明一下,博主提前百度了一下,发现答案基本都是推荐用redis事务机制。博主不推荐使用redis的事务机制。因为我们的生产环境,基本都是redis集群环境,做了数据分片操作。你一个事务中有涉及到多个key操作的时候,这多个key不一定都存储在同一个redis-server上。因此,redis的事务机制,十分鸡肋。
如何批量清理临时镜像文件?
可以使用sudo docker rmi $(sudo docker images -q -f danging=true)
命令
如何查看镜像支持的环境变量?
本地的镜像文件都存放在哪里
于Docker相关的本地资源存放在/var/lib/docker/目录下,其中container目录存放容器信息,graph目录存放镜像信息,aufs目录下存放具体的镜像底层文件。
构建Docker镜像应该遵循哪些原则?
整体远侧上,尽量保持镜像功能的明确和内容的精简,要点包括:
.dockerignore
文件或使用干净的工作目录容器退出后,通过docker ps 命令查看不到,数据会丢失么?
容器退出后会处于终止(exited)状态,此时可以通过 docker ps -a
查看,其中数据不会丢失,还可以通过docker start 来启动,只有删除容器才会清除数据。
如何停止所有正在运行的容器?
使用docker kill $(sudo docker ps -q)
如何清理批量后台停止的容器?
使用docker rm $(docker ps -a -q)
如何临时退出一个正在交互的容器的终端,而不终止它?
按Ctrl+p,后按Ctrl+q,如果按Ctrl+c会使容器内的应用进程终止,进而会使容器终止。
使用docker port 命令映射容器的端口时,系统报错Error: No public port ‘80’ published for …,是什么意思?
创建镜像时Dockerfile要指定正确的EXPOSE的端口,容器启动时指定PublishAllport=true
可以在一个容器中同时运行多个应用进程吗?
可以,但一般不推荐在同一个容器内运行多个应用进程,如果有类似需求,可以通过额外的进程管理机制,比如supervisord来管理所运行的进程
如何控制容器占用系统资源(CPU,内存)的份额?
在使用docker create命令创建容器或使用docker run 创建并运行容器的时候,可以使用-c|–cpu-shares[=0]
参数来调整同期使用CPU的权重,使用-m|–memory
参数来调整容器使用内存的大小。
仓库(Repository)、注册服务器(Registry)、注册索引(Index)有何关系?
首先,仓库是存放一组关联镜像的集合,比如同一个应用的不同版本的镜像,注册服务器是存放实际的镜像的地方,注册索引则负责维护用户的账号,权限,搜索,标签等管理。注册服务器利用注册索引来实现认证等管理。
**从非官方仓库(如:[http://dl.dockerpool.com)下载镜像的时候,有时候会提示“Error:Invaild registry endpoint **
Docker 自1.3.0版本往后以来,加强了对镜像安全性的验证,需要手动添加对非官方仓库的信任。DOCKER_OPTS=”–insecure-registry dl.dockerpool.com:5000”
重启docker服务
Docker的配置文件放在那里。如何修改配置?
Ubuntu系统下Docker的配置文件是/etc/default/docker
,CentOS系统配置文件存放在/etc/sysconfig/docker
如何更改Docker的默认存储设置?
Docker的默认存放位置是/var/lib/docker
, 如果希望将Docker的本地文件存储到其他分区,可以使用Linux软连接的方式来做。
Docker与LXC(Linux Container)有何不同?
LXC利用Linux上相关技术实现容器,Docker则在如下的几个方面进行了改进:
Docker与Vagrant有何不同?
两者的定位完全不同
Vagrant类似于Boot2Docker(一款运行Docker的最小内核),是一套虚拟机的管理环境,Vagrant可以在多种系统上和虚拟机软件中运行,可以在Windows。Mac等非Linux平台上为Docker支持,自身具有较好的包装性和移植性。
原生Docker自身只能运行在Linux平台上,但启动和运行的性能都比虚拟机要快,往往更适合快速开发和部署应用的场景。
开发环境中Docker与Vagrant该如何选择?
Docker不是虚拟机,而是进程隔离,对于资源的消耗很少,单一开发环境下Vagrant是虚拟机上的封装,虚拟机本身会消耗资源。
如何将一台宿主机的docker环境迁移到另外一台宿主机?
停止Docker服务,将整个docker存储文件复制到另外一台宿主机上,然后调整另外一台宿主机的配置即可
Docker容器创建后,删除了/var/run/netns 目录下的网络名字空间文件,可以手动恢复它:
查看容器进程ID,比如1234 sudo docker inspect --format='{{. State.pid}}' $container_id 1234
# 到proc目录下,把对应的网络名字空间文件链接到/var/run/netns
,然后通过正常的系统命令查看操作容器的名字空间。
当启动容器的时候提示:exec format error?如何解决问题
检查启动命令是否有可执行权限,进入容器手工运行脚本进行排查。
本地的镜像文件都存放在哪里?
与 Docker 相关的本地资源都存放在/var/lib/docker/
目录下,其中container目录存放容器信息,graph目录存放镜像信息,aufs目录下存放具体的内容文件。
退出容器时候自动删除?
使用 –rm 选项
Dockerfile中的命令COPY和ADD命令有什么区别?
一般而言,虽然ADD并且COPY在功能上类似,但是首选COPY。
那是因为它比ADD更易懂。COPY仅支持将本地文件复制到容器中,而ADD具有一些功能(如仅限本地的tar提取和远程URL支持),这些功能并不是很明显。因此,ADD的最佳用途是将本地tar文件自动提取到镜像中,如ADD rootfs.tar.xz /。
如何监控生产中的Docker?
Docker提供docker stats和docker events等工具来监控生产中的Docker。可以使用这些命令获取重要统计数据的报告。
Docker stats:当我们使用容器ID调用docker stats时,我们获得容器的CPU,内存使用情况等。它类似于Linux中的top命令。
Docker events:Docker events是一个命令,用于查看Docker守护程序中正在进行的任务。
一些常见的Docker事件是:attach,commit,die,detach,rename,destroy等。
Dockerfile中常见的指令?
elasticsearch主要特点
ES相关概念
ES 常用插件
head 插件:
kopf 插件
为什么要使用Elasticsearch?
因为在我们商城中的数据,将来会非常多,所以采用以往的模糊查询,模糊查询前置配置,会放弃索引,导致商品查询是全表扫面,在百万级别的数据库中,效率非常低下,而我们使用ES做一个全文索引,我们将经常查询的商品的某些字段,比如说商品名,描述、价格还有id这些字段我们放入我们索引库里,可以提高查询速度。
Elasticsearch是如何实现Master选举的?
Elasticsearch的选主是ZenDiscovery模块负责的,主要包含Ping(节点之间通过这个RPC来发现彼此)和Unicast(单播模块包含一个主机列表以控制哪些节点需要ping通)这两部分;
对所有可以成为master的节点(node.master: true)根据nodeId字典排序,每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第0位)节点,暂且认为它是master节点。
如果对某个节点的投票数达到一定的值(可以成为master节点数n/2+1)并且该节点自己也选举自己,那这个节点就是master。否则重新选举一直到满足上述条件。
补充:master节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data节点可以关闭http功能。
Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?
当集群master候选数量不小于3个时,可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题;
当候选数量为两个时,只能修改为唯一的一个master候选,其他作为data节点,避免脑裂问题。
详细描述一下Elasticsearch索引文档的过程。
协调节点默认使用文档ID参与计算(也支持通过routing),以便为路由提供合适的分片。
shard = hash(document_id) % (num_of_primary_shards)
当分片所在的节点接收到来自协调节点的请求后,会将请求写入到Memory Buffer,然后定时(默认是每隔1秒)写入到Filesystem Cache,这个从Momery Buffer到Filesystem Cache的过程就叫做refresh;
当然在某些情况下,存在Momery Buffer和Filesystem Cache的数据可能会丢失,ES是通过translog的机制来保证数据的可靠性的。其实现机制是接收到请求后,同时也会写入到translog中,当Filesystem cache中的数据写入到磁盘中时,才会清除掉,这个过程叫做flush;
在flush过程中,内存中的缓冲将被清除,内容被写入一个新段,段的fsync将创建一个新的提交点,并将内容刷新到磁盘,旧的translog将被删除并开始一个新的translog。
flush触发的时机是定时触发(默认30分钟)或者translog变得太大(默认为512M)时;
详细描述一下Elasticsearch更新和删除文档的过程
删除和更新也都是写操作,但是Elasticsearch中的文档是不可变的,因此不能被删除或者改动以展示其变更;
磁盘上的每个段都有一个相应的.del文件。当删除请求发送后,文档并没有真的被删除,而是在.del文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。当段合并时,在.del文件中被标记为删除的文档将不会被写入新段。
在新的文档被创建时,Elasticsearch会为该文档指定一个版本号,当执行更新时,旧版本的文档在.del文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。
详细描述一下Elasticsearch搜索的过程
搜索被执行成一个两阶段过程,我们称之为 Query Then Fetch;
在初始查询阶段时,查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。 每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。PS:在搜索的时候是会查询Filesystem Cache的,但是有部分数据还在Memory Buffer,所以搜索是近实时的。
每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。
接下来就是 取回阶段,协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每个分片加载并 丰富 文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了,协调节点返回结果给客户端。
补充:Query Then Fetch的搜索类型在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少的时候可能不够准确,DFS Query Then Fetch增加了一个预查询的处理,询问Term和Document frequency,这个评分更准确,但是性能会变差。
Elasticsearch对于大数据量(上亿量级)的聚合如何实现?
Elasticsearch 提供的首个近似聚合是cardinality 度量。它提供一个字段的基数,即该字段的distinct或者unique值的数目。它是基于HLL算法的。HLL 会先对我们的输入作哈希运算,然后根据哈希运算的结果中的 bits 做概率估算从而得到基数。其特点是:可配置的精度,用来控制内存的使用(更精确 = 更多内存);小的数据集精度是非常高的;我们可以通过配置参数,来设置去重需要的固定内存使用量。无论数千还是数十亿的唯一值,内存使用量只与你配置的精确度相关 .
在并发情况下,Elasticsearch如果保证读写一致?
可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突;
另外对于写操作,一致性级别支持quorum/one/all,默认为quorum,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,分片将会在一个不同的节点上重建。
对于读操作,可以设置replication为sync(默认),这使得操作在主分片和副本分片都完成后才会返回;如果设置replication为async时,也可以通过设置搜索请求参数_preference为primary来查询主分片,确保文档是最新版本。
ElasticSearch中的集群、节点、索引、文档、类型是什么?
群集是一个或多个节点(服务器)的集合,它们共同保存您的整个数据,并提供跨所有节点的联合索引和搜索功能。群集由唯一名称标识,默认情况下为“elasticsearch”。此名称很重要,因为如果节点设置为按名称加入群集,则该节点只能是群集的一部分。
节点是属于集群一部分的单个服务器。它存储数据并参与群集索引和搜索功能。
索引就像关系数据库中的“数据库”。它有一个定义多种类型的映射。索引是逻辑名称空间,映射到一个或多个主分片,并且可以有零个或多个副本分片。 MySQL =>数据库 ElasticSearch =>索引
文档类似于关系数据库中的一行。不同之处在于索引中的每个文档可以具有不同的结构(字段),但是对于通用字段应该具有相同的数据类型。 MySQL => Databases => Tables => Columns / Rows ElasticSearch => Indices => Types =>具有属性的文档
类型是索引的逻辑类别/分区,其语义完全取决于用户。
ElasticSearch中的分片是什么?
在大多数环境中,每个节点都在单独的盒子或虚拟机上运行。
索引 - 在Elasticsearch中,索引是文档的集合。
分片 -因为Elasticsearch是一个分布式搜索引擎,所以索引通常被分割成分布在多个节点上的被称为分片的元素。
ElasticSearch是否有架构?
ElasticSearch可以有一个架构。架构是描述文档类型以及如何处理文档的不同字段的一个或多个字段的描述。Elasticsearch中的架构是一种映射,它描述了JSON文档中的字段及其数据类型,以及它们应该如何在Lucene索引中进行索引。因此,在Elasticsearch术语中,我们通常将此模式称为“映射”。
Elasticsearch具有架构灵活的能力,这意味着可以在不明确提供架构的情况下索引文档。如果未指定映射,则默认情况下,Elasticsearch会在索引期间检测文档中的新字段时动态生成一个映射。
ElasticSearch中的副本是什么?
一个索引被分解成碎片以便于分发和扩展。副本是分片的副本。一个节点是一个属于一个集群的ElasticSearch的运行实例。一个集群由一个或多个共享相同集群名称的节点组成。
ElasticSearch中的分析器是什么?
在ElasticSearch中索引数据时,数据由为索引定义的Analyzer在内部进行转换。 分析器由一个Tokenizer和零个或多个TokenFilter组成。编译器可以在一个或多个CharFilter之前。分析模块允许您在逻辑名称下注册分析器,然后可以在映射定义或某些API中引用它们。
Elasticsearch附带了许多可以随时使用的预建分析器。或者,您可以组合内置的字符过滤器,编译器和过滤器器来创建自定义分析器。
什么是ElasticSearch中的编译器?
编译器用于将字符串分解为术语或标记流。一个简单的编译器可能会将字符串拆分为任何遇到空格或标点的地方。Elasticsearch有许多内置标记器,可用于构建自定义分析器。
启用属性,索引和存储的用途是什么?
enabled属性适用于各类ElasticSearch特定/创建领域,如index和size。用户提供的字段没有“已启用”属性。 存储意味着数据由Lucene存储,如果询问,将返回这些数据。
存储字段不一定是可搜索的。默认情况下,字段不存储,但源文件是完整的。因为您希望使用默认值(这是有意义的),所以不要设置store属性 该指数属性用于搜索。
索引属性只能用于搜索。只有索引域可以进行搜索。差异的原因是在分析期间对索引字段进行了转换,因此如果需要的话,您不能检索原始数据。