QPS达到30万的elasticsearch架设之道

本文详细介绍了如何构建基于Elasticsearch (ES)、Logstash 和 Kafka的日志系统。包括ES集群的部署与优化、Kafka的部署及Topic创建、Logstash部署方式以及日志消费程序Hangout的使用。

 

架构是数据被logstash打到kafka,然后消费端从kafka通过hangout消费。最后到es来索引。

原理网上比较多,就不细说,现在主要来讲实战。

 

一、ES集群部署优化之道

 

部署准备:

1.修改文件limit

#!/bin/bash

max=2500000

#check permission
uid=$(id -u)
if [[ -z $uid ]];then
echo "please use root to run this"
exit 201
fi
if [[ $uid -ne 0 ]];then
echo "please use root to run this"
exit 201
fi

#check value
#linux default: 1024 * 1024 = 1048576
if [[ $max -lt 1048576 ]];then
echo "max value must >= 1048576"
exit 202
fi

#set temporary
sysctl -w fs.nr_open=$max
if [[ $? -ne 0 ]];then
echo "sysctl set failed"
exit 1
fi

#set forever
grep -P "^\s*fs.nr_open" /etc/sysctl.conf &>/dev/null
if [[ $? -eq 0 ]];then
#update
sed -i "s/^\s*fs.nr_open.*/fs.nr_open = $max /g" /etc/sysctl.conf
if [[ $? -ne 0 ]];then
echo "update value failed"
exit 2
fi
else
#add 
echo "fs.nr_open = $max" >> /etc/sysctl.conf
if [[ $? -ne 0 ]];then
echo "add value failed"
exit 3
fi
fi
sed -i "s/.*-.*nofile.*/\* - nofile $max/g" /etc/security/limits.conf

2.修改内存lock

# allow user 'kafka' mlockall
kafka soft memlock unlimited
kafka hard memlock unlimited

添加到/etc/security/limits.conf

3.然后将es在其中的部署目录打包。

tar cf elast.tar /data/apps/elasticsearch-2.2.0

4.将包传到任意需要部署机器。

然后解压缩

tar xf elast.tar

5.修改配置文件

/data/apps/elasticsearch-2.2.0/config/elasticsearch.yml

 

cluster.name: 修改为同一集群代号

node.name: 修改为本机hostname

path.data: 修改为本机数据目录,用逗号分隔

bootstrap.mlockall: true 优化es内存设置,起来lock住内存

network.host: 修改为本机ip

discovery.zen.ping.unicast.hosts:修改为集群所有的ip列表,利于发现其他节点

 

以下为优化内存,防止gc和加速recovery的设置,默认加入即可。

indices.recovery.concurrent_streams: 24
indices.recovery.concurrent_small_file_streams: 12
indices.recovery.max_bytes_per_sec: 200mb

indices.fielddata.cache.size: 20%
indices.breaker.fielddata.limit: 20%
indices.breaker.request.limit: 20%
indices.breaker.total.limit: 40%

6.启动es,采用如下方式,注意内存不要超过32G。

export JAVA_HOME=/data/apps/jdk1.8.0_65
export ES_HEAP_SIZE=28g
cd /data/apps/elasticsearch-2.1.1/bin && ./elasticsearch -d --Xmx 28g --Xms 28g

 

二、KAFKA部署信息,与相关TOPIC创建

采用直接解压部署到

/data/app/kafka_2.10-0.9.0.1/

文件配置采用默认kafka配置。

/data/app/kafka_2.10-0.9.0.1/config/server.properties

这里需要修改下brok.id

broker.id= 每台kafka都有一个唯一id

启动方式是:

sudo -u kafka nohup bin/kafka-server-start.sh config/server.properties &

三、logstash部署方式介绍

由于每台日志机器需要采集日志到kafka队列。

所以采取每台日志机部署logstash方式。现在kss/ks3机器上都已经部署logstash.

部署logstash需要将该目录打包,然后传送到任一采集机,然后解压,修改如下启动脚本后启动即可。

bin/logstash -e 'input{file{ type=>".23.8" path=>"/data/logs/nginx/access.log"}}output{kafka{ bootstrap_servers => "xxx.68:10002" topic_id => "xxxslog" }}'

#type为标志本机ip

#path为日志路径

#output是kafka的地址列表,上表是武清机房的kafka地址

#topic_id是对应的topic

修改完毕的命令行可以直接以后台方式运行。这样就启动了日志采集进程。

 

四、日志消费程序部署与使用介绍

日志消费程序采用ctrip开源的hangout,具体git地址看这里。

https://github.com/childe/hangout

用ks3的具体配置为例:

inputs: #input为kafka
- Kafka:
codec: json #json格式
topic: 
kxxx3log: 2

########################################################

从Kafka读数据. 下面示例是说, 开2个线程取app这个topic的数据, 编码格式为plain纯文本. consumer_settings中的参数, 参考[kafka]官方文档](http://kafka.apache.org/documentation.html#consumerconfigs), 所有参数都可以在这里配置. 比较重要的是group.id, zookeeper.connect这两个, 一定要有. zookeeper.connect的格式为 hostname1:port1,hostname2:port2,hostname3:port3.

 ########################################################
consumer_settings:
group.id: hangout
zookeeper.connect: 11.4.22.15:2181
auto.commit.interval.ms: "5000"
socket.receive.buffer.bytes: "1048576"
fetch.message.max.bytes: "1048576"
num.consumer.fetchers: "4"
filters:
- Grok:
src: message
match:
- '^\"(?<upstream_http_x_kss_Bucketowner>.+)\" \"(?<upstream_http_x_kss_Bucketname>.+)\" \"\[(?<time_local>.+)\]\" \"(?<remote_addr>\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})\" \"(?<upstrea
m_http_x_kss_Requester>.+)\" \"(?<upstream_http_x_kss_request_id>.+)\" \"(?<upstream_http_x_kss_Op>.+)\" \"(?<upstream_http_x_kss_Key>.+)\" \"(?<request>.+)\" \"(?<status>.+)\" \"(?<upstrea
m_http_x_kss_ErrCode>.+)\" \"(?<content_length>.+)\" \"(?<body_bytes_sent>.+)\" \"(?<upstream_http_x_kss_ObjSize>.+)\" \"(?<request_time>.+)\" \"(?<upstream_response_time>.+)\" \"(?<http_re
ferer>.+)\" \"(?<http_user_agent>.+)\" \"(?<upstream_addr>.+)\" \"(?<http_kscdn>.+)\"$'
remove_fields: ['path']
- Json:
field: message # required
- Gsub:
fields: #由于以下字段会有-,所以要替换为0,免得出错
upstream_http_x_kss_ObjSize: ['-','0']
body_bytes_sent: ['-','0']
content_length: ['-','0']
upstream_response_time: ['-','0.00']
request_time: ['-','0.00']
outputs: #向es输出
- Elasticsearch:
cluster: xxx-ecs #es的集群名
hosts: #杭州es host
- 10.4.69.70:9300
- 10.4.71.100:9300
- 10.4.71.103:9300
- 10.4.71.102:9300
index: 'hangout-ks3-%{+YYYYMMdd}' #日志格式
index_type: logs # default logs
bulk_actions: 20000 #default 20000
bulk_size: 30 # default 15 MB
flush_interval: 10 # default 10 seconds
concurrent_requests: 0 # default 0, concurrent_requests设置成大于0的数, 意思着多线程处理, 以我应用的经验,还有是一定OOM风险的,强烈建议设置为0
timezone: "Asia/Shanghai" # defaut UTC 时区. 只用于生成索引名字的字符串格式化

 

关注微信公众号,获取更多精彩:

 

 

 

<think>嗯,用户提出的问题很专业,聚焦在十QPS下的秒杀系统日志方案设计。结合用户引用的资料来看,ta应该是个有分布式系统经验的开发者,尤其关注高并发场景的实践细节。ta特别强调"分布式日志"和"高并发处理",说明核心痛点在于如何避免日志成为性能瓶颈。从引用[1][3][5]能提炼关键约束:一是日志必须异步化不能阻塞主流程,二是要考虑与现有监控体系(如ElasticJob、Dubbo)的整合。用户没提具体技术栈,但引用里出现的Canal、Sentinel、Disruptor都是Java生态,所以示例代码用Java比较合理。设计时需要重点权衡三个矛盾:日志完整性vs性能、实时性vs可靠性、开发便利性vs系统稳定性。比如引用[3]提到的"本地缓存+批量写"方案,虽然可能丢失1秒日志,但换来了两个数量级的吞吐提升——这在秒杀场景是可接受的代价。用户可能没意识到的隐藏需求是日志分级。十QPS下全量日志不现实,需要像引用[5]的LongAdder那样做关键操作采样。另外引用[2]的Dubbo架构图提示了重要线索:日志采集点应该覆盖消费者/提供者/注册中心三层。最后要注意避坑:引用[4]警告过分布式系统时钟同步问题,所以日志必须用分布式ID串联;引用[1]的binlog同步机制也启示我们可以复用现有日志管,避免重复建设。</think> 在秒杀系统实现**十QPS并发**的日志记录方案,需围绕 **「高吞吐、低延迟、可扩展」** 三大核心目标设计。以下是关键设计原则与实现方案: --- ### **1. 日志采集架构(分布式异步化)** #### **核心组件** ```mermaid graph TD A[应用节点] -->|异步写入| B[本地磁盘缓冲区] B --> C[日志采集Agent] C -->|批量压缩传输| D[消息队列 Kafka] D --> E[流处理引擎 Flink] E --> F[持久化存储 ES/对象存储] ``` #### **设计要点** - **异步非阻塞写入** 使用 `Disruptor` 或 `Log4j2 AsyncAppender` 分离业务线程与日志线程,避免I/O阻塞。 示例配置(Log4j2): ```xml <AsyncLogger name="seckill" level="INFO"> <AppenderRef ref="KafkaAppender"/> </AsyncLogger> ``` - **本地缓存+批量发送** 采集Agent(如Filebeat/Fluentd)监控本地日志文件,按批次压缩发送至Kafka,降低网络开销。 --- ### **2. 日志分级与采样策略** #### **日志等级控制** | 日志类型 | 采集频率 | 用途 | |--------------|----------|--------------------------| | ERROR | 全量 | 故障追踪、告警触发 | | WARN | 全量 | 风险操作监控 | | INFO(关键链路)| 采样10% | 核心流程追踪(如订单创建)| | DEBUG | 关闭 | 生产环境禁用 | #### **动态采样实现** ```java // 基于TraceID的日志采样(使用分布式ID如Snowflake) if (traceId.hashCode() % 10 == 0) { log.info("秒杀订单创建: {}", order); } ``` --- ### **3. 高吞吐存储方案** #### **分层存储设计** ```mermaid graph LR G[Kafka] --> H[Flink实时处理] H --> I[ES:近7天热数据] H --> J[S3/HDFS:长期归档] ``` - **Elasticsearch优化** - 分片策略:按日期分索引(`logs-seckill-20240530`),分片数 = 数据节点数 × 1.5 - 禁用 `_source` + 使用 `best_compression` - 冷热分离:SSD存热数据,HDD存冷数据 - **归档存储** 通过Flink定时将过期数据转储至对象存储(如AWS S3),降低ES成本。 --- ### **4. 关键性能优化手段** 1. **日志格式精简** - 使用JSON替代文本:便于解析,但需压缩传输(Snappy压缩率70%) - 字段裁剪:仅保留必要信息(如`traceId, userId, action, result`) 2. **网络传输优化** - Kafka Producer配置: `linger.ms=500`(批量延迟) `compression.type=snappy` `batch.size=65536`(64KB) 3. **资源隔离** - 独立Kafka集群:与业务消息物理隔离,避免资源争抢 - 限流保护:Agent端限制单节点带宽 ≤ 50Mbps --- ### **5. 容灾与监控** #### **保障机制** - **端到端ACK**:Kafka → Flink → ES 开启事务传递 - **重试策略**:Kafka Producer配置 `acks=all` + `retries=10` - **降级方案**:当ES不可用时,Flink暂存数据至Redis/Pulsar #### **监控指标** | 指标 | 告警阈值 | 工具 | |---------------------|----------------|---------------| | 日志生产延迟 | > 500ms | Prometheus | | Kafka堆积量 | > 100,000条 | Grafana | | ES索引延迟 | > 1秒 | Kibana | --- ### **6. 典型代码实现** ```java // 使用MDC注入TraceID(结合分布式链路追踪) try (MDC.MDCCloseable closeable = MDC.putCloseable("traceId", Span.current().getTraceId())) { // 异步日志写入(Log4j2) logger.info("Seckill request: userId={}, itemId={}", userId, itemId); } ``` --- ### **
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值