为了保证正常业务不受影响,集群在启用安全功能的过程中还可正常提供服务,可以使用多阶段,多端口,多协议的方案。

  • 以增量替换的方式添加额外的安全端口(s)。
  • 客户端使用安全的端口来连接,而不是PLAINTEXT端口的(假设你是客户端需要安全连接broker)。
  • 再次增量的方式依次启用broker与broker之间的安全端口(如果需要)
  • 最后依次关闭PLAINTEXT端口。

本方案以confluentinc/cp-kafka:5.2.1 版本进行试验,SASL机制选择:SASL/SCRAM 特此说明。SCRAM全称为Salted Challenge Response Authentication Mechanism。

Kafka 支持如下SASL机制:

SASL机制 Kafka版本 特点
SASL/OAUTHBEARER 2.0.0 需自己实现接口实现token的创建和验证,需要额外Oauth服务
SASL/Kerberos 0.9.0.0 需要独立部署验证服务
SASL/PLAIN 0.10.0.0 不能动态增加用户
SASL/SCRAM 0.10.2.0 可以动态增加用户
阅读全文 »

生产者最佳实践

使用

默认send方法是异步,kafka会进行消息的端到端批量压缩。

配置

1
2
3
4
5
6
7
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("acks", "all");
props.put("retries", 0);
props.put("linger.ms", 1);
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

异步

1
2
3
4
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
for (int i = 0; i < 100; i++)
producer.send(new ProducerRecord<String, String>("my-topic", Integer.toString(i), Integer.toString(i)));
producer.close();

当然异步发送推荐添加callback

1
2
3
4
5
producer.send(new ProducerRecord<String, String>("my-topic", Integer.toString(i), Integer.toString(i)),(recordMetadata,exception)->{
if(exception!=null){
exception.printStackTrace();
}
});

数据量大的业务场景推荐首选异步,做好异常情况处理逻辑就好。

同步

1
2
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
producer.send(new ProducerRecord<>("my-topic","1","1")).get();

同步适合业务规模不大,但对数据一致性要求高的场景。根据合适场景采取合适的方式。

阅读全文 »

环境搭建与快速入门

Kafka搭建

在开始前,首先准备好自己的docker环境,可以安装Docker Desktop.

为了更方便的搭建学习环境,推荐使用confluent公司社区版docker镜像。

对于confluent版本和apache版本对照表如下:

Confluent Platform and Apache Kafka Compatibility

Confluent Platform Apache Kafka® Release Date Standard End of Support Platinum End of Support
7.0.x 3.0.x October 27, 2021 October 27, 2023 October 27, 2024
6.2.x 2.8.x June 8, 2021 June 8, 2023 June 8, 2024
6.1.x 2.7.x February 9, 2021 February 9, 2023 February 9, 2024
6.0.x 2.6.x September 24, 2020 September 24, 2022 September 24, 2023
5.5.x 2.5.x April 24, 2020 April 24, 2022 April 24, 2023
5.4.x 2.4.x January 10, 2020 January 10, 2022 January 10, 2023
5.3.x 2.3.x July 19, 2019 July 19, 2021 July 19, 2022
5.2.x 2.2.x March 28, 2019 March 28, 2021 March 28, 2022
5.1.x 2.1.x December 14, 2018 December 14, 2020 December 14, 2021
5.0.x 2.0.x July 31, 2018 July 31, 2020 July 31, 2021
4.1.x 1.1.x April 16, 2018 April 16, 2020 April 16, 2021
4.0.x 1.0.x November 28, 2017 November 28, 2019 November 28, 2020
3.3.x 0.11.0.x August 1, 2017 August 1, 2019 August 1, 2020
3.2.x 0.10.2.x March 2, 2017 March 2, 2019 March 2, 2020
3.1.x 0.10.1.x November 15, 2016 November 15, 2018 November 15, 2019
3.0.x 0.10.0.x May 24, 2016 May 24, 2018 May 24, 2019
2.0.x 0.9.0.x December 7, 2015 December 7, 2017 December 7, 2018
1.0.0 February 25, 2015 February 25, 2017 February 25, 2018

首先新建文件docker-compose.yml,并写入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
---
version: '3'
services:
zookeeper:
image: confluentinc/cp-zookeeper:7.0.1
container_name: zookeeper
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000

broker:
image: confluentinc/cp-kafka:7.0.1
container_name: broker
ports:
# To learn about configuring Kafka for access across networks see
# https://www.confluent.io/blog/kafka-client-cannot-connect-to-broker-on-aws-on-docker-etc/
- "9092:9092"
depends_on:
- zookeeper
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_INTERNAL:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092,PLAINTEXT_INTERNAL://broker:29092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1

然后在该文件目录下执行docker-compose up -d,既可启动zookeeper容器和kafka broker容器,docker-compose down可以关闭创建好的集群。

1
2
3
4
PS F:\docker-workspace\kafka> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aac9044963e5 confluentinc/cp-kafka:7.0.1 "/etc/confluent/dock…" 11 seconds ago Up 10 seconds 0.0.0.0:9092->9092/tcp broker
debcc3a0235d confluentinc/cp-zookeeper:7.0.1 "/etc/confluent/dock…" 13 seconds ago Up 12 seconds 2181/tcp, 2888/tcp, 3888/tcp zookeeper

如上情况,即为创建成功。

阅读全文 »

将页面设计好看,大概是所有程序员的朴素追求,命令行不在谈论范围。企业级中后台界面设计是一个很常见的场景,但是往往很多公司或者项目组,没有专业的前端和产品经理,因此就很有必要了解一下前端设计价值观(原则)。

通常来说设计价值观是用来评判是否好看,给设计提供标准,设计原则是用来践行好的设计价值观的,这里暂且将两者混合而谈。

声明作者能力有限,非前端设计/开发者,本文仅是将业界经验和自己的工作总结,欢迎找我交流补正!

这是一篇写给中后台开发者看的前端设计价值观。

资源

在开始之前推荐大家看业界优秀的文档,强烈安利!本文也只是自己根据这些的总结罢了。

  1. 腾讯 TDesign
  2. 蚂蚁 Ant Design
  3. Alibaba Fusion
  4. awesome-design-principles
  5. element-plus
  6. 网易云商Fish Design

不同企业定义的设计价值观不同,但总的来说脱离不了:清晰、高效、统一、美观、简单、可靠 ,当我们在写一个用户界面,可以用这几个原则来做衡量和取舍。

色彩

中后台设计中,色彩的使用建议是克制的,更多的是基于信息的传递、操作引导和交互反馈的目的。

通常包含主题色、功能色、中性色3部分。

数据可视化需要单独的颜色场景,本文不做介绍,需要了解的话推荐参考AntV色板

主题色

也可以称之为品牌色,主题色是产品中最核心、最高频使用的颜色,决定了产品整体的基调和风格。

应用场景包括:强调信息、引导操作,关键行动点,操作状态、重要信息高亮,图形化等场景。

大家有没有想过,科技的颜色?

不同品牌的色彩体系里,科技公司都比较倾向于蓝色色系,例如TDesign,Ant Design Pro, Fusion ,Fish Design等,我比较倾向于喜欢 Tencent Blue

1
2
3
rgba(0, 82, 217, 1)

#0052d9

如果需要选择自己的色彩,建议使用Ant Design 的基础色板,完全可以满足中后台设计中对于颜色的需求。

Ant Design 调色板的一部分

建议选择色板从浅至深的第六个颜色作为主色

阅读全文 »

面试系列笔记-Redis

本文来自

https://github.com/TrumanDu/knowledge/blob/main/%E7%BC%93%E5%AD%98.md

Redis必知知识点

String

内部编码int(8字节长整型)/embstr(小于等于44字节字符串)/raw(大于44个字节字符串)

适用场景:共享session、分布式锁,计数器、限流、缓存

List

内部编码:`ziplist(同时满足:所有字符串元素的长度都小于64字节,元素数量小于512个)、quicklist

适用场景:消息队列,文章列表

1
2
3
4
lpush+lpop=Stack(栈)
lpush+rpop=Queue(队列)
lpsh+ltrim=Capped Collection(有限集合)
lpush+brpop=Message Queue(消息队列)

ziplist是一段连续内存,节省内存空间。

quicklist 存储了一个双向列表,每个列表的节点是一个ziplist,

Set

内部编码intset(整数集合)、hashtable(哈希表)如果集合中的元素都是整数且元素个数小于512个,使用intset编码,否则使用hashtable编码

适用场景:用户标签,生成随机数抽奖、社交需求

Hash

内部编码ziplist(压缩列表)哈希类型元素个数小于512个,所有值小于64字节的话,使用ziplist编码,否则使用hashtable(哈希表)

适用场景

SortSet

内部编码ziplist(压缩列表)skiplist(跳跃表)当有序集合的元素个数小于128个,每个元素的值小于64字节时,使用ziplist编码,否则使用skiplist(跳跃表)编码

适用场景:排行榜,社交需求(如用户点赞)。

其他

  • Geospatial 存储地理位置信息
  • Hyperloglog 基数统计算法的数据结构,可以用来统计数量
  • Bitmap 位图,解决大数据利器
阅读全文 »

MongoDB 是通用、基于文档的分布式数据库。支持完整的 ACID 事务,具有强大的查询语言等。属于NoSQL数据库。

基本概念

SQL术语/概念 MongoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持
primary key primary key 主键,MongoDB自动将_id字段设置为主键

SQL术语/概念MongoDB术语/概念解释/说明databasedatabase数据库tablecollection数据库表/集合rowdocument数据记录行/文档columnfield数据字段/域indexindex索引table joins表连接,MongoDB不支持primary keyprimary key主键,MongoDB自动将_id字段设置为主键SQL术语/概念MongoDB术语/概念解释/说明databasedatabase数据库tablecollection数据库表/集合rowdocument数据记录行/文档columnfield数据字段/域indexindex索引table joins表连接,MongoDB不支持primary keyprimary key主键,MongoDB自动将_id字段设置为主键

适用场景与选型

MongoDB定位与优点

  • OLTP数据库
  • ACID事务
  • 横向扩展能力,数据量和并发量增加时候架构可以自动扩展
  • JSON数据结构 ,适合微服务/REST API
  • 灵活模型,适合迭代开发,数据模型多变的场景

基于功能选择

支持功能
亿及以上数据量
灵活表结构
高并发读/写
跨地区集群
分片集群
地理位置查询
聚合计算
异构数据
大宽表

支持功能亿及以上数据量灵活表结构高并发读/写跨地区集群分片集群地理位置查询聚合计算异构数据大宽表支持功能亿及以上数据量灵活表结构高并发读/写跨地区集群分片集群地理位置查询聚合计算异构数据大宽表### 基于场景选择

  • 移动应用
  • 商品信息
  • 内容管理
  • 物联网
  • Saas
  • 主机分流
  • 实时分析
  • 关系型数据库替换
阅读全文 »

常用垃圾回收器

  • CMS
  • G1
  • ZGC

通过如下命令,可以查看垃圾回收器的使用情况

1
$ java -XX:+PrintCommandLineFlags -version

jdk1.8 如下:

1
2
3
4
5
6
7
8
9
10
-XX:InitialHeapSize=534944128
-XX:MaxHeapSize=8559106048
-XX:+PrintCommandLineFlags
-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
-XX:-UseLargePagesIndividualAllocation
-XX:+UseParallelGC
openjdk version "1.8.0_181-1-redhat"
OpenJDK Runtime Environment (build 1.8.0_181-1-redhat-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)

jdk1.8 -XX:+UseParallelGC 默认使用的是 Parallel 垃圾回收器

jdk11 如下:

1
2
3
4
-XX:G1ConcRefinementThreads=10 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=534944128 -XX:MaxHeapSize=8559106048 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation
openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.6+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.6+10, mixed mode)

jdk11 -XX:+UseG1GC默认使用的垃圾回收器是G1

理解 JVM 垃圾回收有用的资源

  1. 新一代垃圾回收器 ZGC 的探索与实践
  2. JVM 系列–还不会选择合适的垃圾收集器?
  3. Java——七种垃圾收集器+JDK11 最新 ZGC
  4. JVM 调优

jvm 启动参数

java 启动参数共分为三类;
其一是标准参数(-),所有的 JVM 实现都必须实现这些参数的功能,而且向后兼容;
其二是非标准参数(-X),默认 jvm 实现这些参数的功能,但是并不保证所有 jvm 实现都满足,且不保证向后兼容;
其三是非 Stable 参数(-XX),此类参数各个 jvm 实现会有所不同,将来可能会随时取消,需要慎重使用;

常用非标准参数

通过 java -X 可以查看支持的非标准参数

1
2
3
4
-Xms6g //最小堆
-Xmx6g //最大堆
-Xss1m //线程栈的大小
-Xmn200m //设置年轻代大小为200M

常用非 Stable 参数

通过java -XX:+PrintFlagsFinal -version可以查看支持的非 Stable 参数

  • -XX:+<option>:代表启用 true
  • -XX:-<option>:代表禁用 false
1
2
-XX:+PrintGC
-XX:+PrintGCDetails

G1

G1 全称为 Garbage-First,意为垃圾优先,哪一块的垃圾最多就优先清理它。

常用参数

1
2
-XX:+UseG1GC //使用G1回收器
-XX:MaxGCPauseMillis=20 // 最大暂停时间为20ms 越小意味着堆小,回收频繁

ZGC

ZGC(The Z Garbage Collector)是 JDK 11 中推出的一款低延迟垃圾回收器,它的设计目标包括:

  • 停顿时间不超过 10ms;
  • 停顿时间不会随着堆的大小,或者活跃对象的大小而增加;
  • 支持 8MB~4TB 级别的堆(未来支持 16TB)。
1
2
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
-XX:ConcGCThreads=2 -XX:ParallelGCThreads=6

超低延迟(TP999 < 20ms)和高延迟(TP999 > 200ms)服务收益不大,吞吐量优先的场景,ZGC 可能并不适合。

更多信息参考:新一代垃圾回收器 ZGC 的探索与实践

jvm 性能查看工具

jstat

利用 jvm 内建的指令对 java 应用程序的资源和性能进行实时的命令行监控,包括针对 heap size 和垃圾回收情况的监控

1
2
3
4
$ jstat -gc 14724 1000 2 //间隔1s,统计两次
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
19968.0 22528.0 0.0 0.0 429056.0 185319.3 395264.0 33163.2 59160.0 55725.5 7808.0 7049.8 8 0.063 3 0.156 0.219
19968.0 22528.0 0.0 0.0 429056.0 185855.6 395264.0 33163.2 59160.0 55725.5 7808.0 7049.8 8 0.063 3 0.156 0.219

参数含义:
S0C:年轻代的第一个 survicor(幸存区)的容量(字节)
S1C:年轻代的第二个 survicor(幸存区)的容量(字节)
S0U:年轻代的第一个 survicor(幸存区)已经使用的空间(字节)
S1U:年轻代的第二个 survicor(幸存区)已经使用的空间(字节)
EC:年轻代中的 Eden(伊甸园)的容量
EU:年轻代中的 Een(伊甸园)已经使用的容量
OC:年老代的容量
OU:年老代已经使用的空间
MC:metadata 的容量
MU:metadata 已经使用的空间
CCSC:压缩类空间的大小
CCSU:压缩类空间的使用大小
YG:从应用程序启动到采样时年轻代中 gc 次数
YGCT:从应用程序启动到采样时年轻代中 gc 所用时间(s)
FGC:从应用程序启动到采样时年老代 gc 次数
FGCT:从应用程序启动到采样时年老代(全 gc)gc 所用时间(s)
GC: 从应用程序启动到采样时 gc 用的总时间(s)

jmap

查看 jvm 的内存分配情况

1
2
3
$ jmap -heap 14724
$ jmap -dump:format=b,file=D:\test\heap.hprof 14724
$ jmap -histo:live 14724 //只统计活的对象数量

jstack

查看 java 程序的线程运行情况

1
$ jstack 14724

jinfo

1
2
$ jinfo 14724 //查看jvm系统详细参数及环境变量
$ jinfo -flag MaxHeapSize 14724 //查看最大堆内存

最佳实践

输出 GC 日志

jdk11

1
java -Xlog:gc*:file=gc.log,filecount=10,filesize=10m

jdk8

1
-XX:+PrintGCDetails -Xloggc:<PATH_TO_GC_LOG_FILE>

dump

1
2
3
#出现 OOM 时生成堆 dump:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/home/jvmlogs/

手动 dump,拷贝压缩文件,使用 MAT 来进行分析

1
jmap -dump:format=b,file=/temp/kafka-streams/logs/dump.log 1

《如何成为学习高手》笔记

作者从5个方面分享了如何更好的学习,成为学习高手,花费一天时间走马观花,只是在个别章节里收益匪浅,按照文章的划分总结一下自己的收获。

底层思维

告别伪勤奋

1、花大量时间做容易的环节。

解决思路是:在你“踮一踮脚能够够得到”的层面去学习、去做事,只有去完成那些让你感到需要思考、需要克服困难的任务,才称得上“真勤奋”。

2、从来不去检测自己获得了什么。

解决思路是:学的东西,要立刻检测,检测自己有没有记住,检测自己是不是会做题。对于真正的勤奋来说,再功利主义也不为过。你要看到反馈,你要立刻看到反馈。一切不以检测和输出为目的的努力,都是耍流氓。

3、只是埋头苦学,从来不总结规律。

解决思路是:学习这件事,不仅包括对知识的学习,还包括对学习方法的学习。你要学会观察、分析、总结自己是如何学习的,对方法进行针对性的调整和完善,并且有意识地指导自己接下来的努力方向。

4、道德许可效应让你原地徘徊,沉迷于已经努力的幻觉之中。

解决思路是:将你想做的事情最简化,去掉所有花里胡哨的,不搞形式主义,直接开始。

掌握考试思维:成为一个特别会考试的人

1、考试,最重要的是“输出”,需要主动回想知识点,把它们从脑袋里调取出来,针对问题给出答案。你要学会用考试的思维去学习。

2、你要去研究考试题,包括它的出题范围和出题思路,去分析考试时,题目要求你怎样回忆知识点、怎样运用知识点。然后,据此决定学习的时候,如何学,以及学什么。

3、在学习的过程中,做到即用即学和即学即用,才能对知识点有透彻的理解和记忆,并且在考试中,做到更为高效准确地调取,以及运用。

4、检索式练习”是最为有效的学习方式,它是指通过提问和主动回想的方式,去巩固知识点。你在回想知识点的时候,所付出的认知努力越大,学习和记忆的效果就越好。

阅读全文 »

Elasticsearch在EventHub项目中的实战应用

前言

Event Hub是一个高度可缩放、分布式、基于时间序列的事件中心,能够实时的处理流式事件并进行告警和提醒。

Event Hub作为Newegg事件信息中枢,产品化新蛋各产品资源及平台底层基础设施服务生命周期与运转中的重要事件信息,并构建完善的事件消费渠道与流程,支撑线上监控与运维。

Event Hub产品化提供的事件信息,由Newegg内部各产品模块与底层基础设施服务获取,经过聚合,判定和收敛再最终呈现。信息源来自各模块底层的系统日志与监控项,保障客户透传客户的信息准确性与价值。关于Event Hub更详细介绍,请查看Newegg的事件中心之Event Hub

为了实现事件的多维度查询,事件的追溯性,我们将事件存储在elasticsearch中。我们设计了两个index:event_hub_currentevent_hub_history

事件是具有时间序列特征的,我们会在event_hub_historyindex中写入每条事件信息,通过事件唯一ID,在event_hub_current中更新事件信息,随着时间的流逝,大多数情况我们关注的结果。如果你了解过实时计算,可以参照Stream和Table。一个是流式的,一个是结果。

阅读全文 »

Elasticsearch速览学习笔记

声明:本来是打算春节期间在官网学习,温故一下相关知识,。无意间发现铭毅天下Elasticsearch文章很全,对快速了解一些知识点,很有帮助。尤其是知识星球里的内容,奈何收费。别人辛勤劳动成果,当然无可厚非。我就借鉴了他的知识图谱,确定自己的学习点,再结合官网文档和他的公众号。引用的地方已经标注,特此声明。

如果没钱没时间,收藏我这边篇笔记就好。如果你舍得花钱,有充足的时间,推荐去购买一下他的知识星球。

基本知识点

分词必知

当字段类型为text的时候会进行分词,默认分词器是standard

两个地方会出现分词,一个是indexing,一个是search。文档索引的时候肯定会分词,search时候针对search查询语句内容分析。默认的话是两者保持一致。某些场景下可以在search中设置分词

分词器分为三个部分:Tokenizers (分词)、Token filters(修改分词例如小写,删除分词,增加分词)、Character filters(用在分词前去除字符)

Test分词器

1
2
3
4
5
POST _analyze
{
"analyzer":"standard",
"text": "The quick brown fox. 1"
}

排查当前index分词的结果

1
2
3
4
5
GET kibana_sample_data_logs/_analyze
{
"field": "my_text",
"text": "Is this déjà vu?"
}

配置一个分析器,去掉英文修饰词

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
PUT my-index-000001
{
"settings": {
"analysis": {
"analyzer": {
"std_english": {
"type": "standard",
"stopwords": "_english_"
}
}
}
},
"mappings": {
"properties": {
"my_text": {
"type": "text",
"analyzer": "standard",
"fields": {
"english": {
"type": "text",
"analyzer": "std_english"
}
}
}
}
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
POST my-index-000001/_analyze
{
"field": "my_text",
"text": "The old brown cow"
}
// [ the, old, brown, cow ]
POST my-index-000001/_analyze
{
"field": "my_text.english",
"text": "The old brown cow"
}
// [ old, brown, cow ]
阅读全文 »
0%