oracle ogg kafka添加一张表_kafka读取数据

oracle ogg kafka添加一张表_kafka读取数据GoldenGate介绍GoldenGate软件是一种基于日志的结构化数据复制软件。GoldenGate能够实现大量交易数据的实时捕捉、变换和投递,实现源数据库与目标数据库的数据同步,保持亚秒级的数据延迟。GoldenGate能够支持多种拓扑结构,包括一对一,一对多,多对一,层叠和双向复制等等。GoldenGate基本架构OracleGoldenGate主要由如下组件组成Extra…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

GoldenGate介绍

GoldenGate软件是一种基于日志的结构化数据复制软件。GoldenGate 能够实现大量交易数据的实时捕捉、变换和投递,实现源数据库与目标数据库的数据同步,保持亚秒级的数据延迟。

GoldenGate能够支持多种拓扑结构,包括一对一,一对多,多对一,层叠和双向复制等等。

GoldenGate基本架构

Oracle GoldenGate主要由如下组件组成

  • Extract
  • Data pump
  • Trails
  • Collector
  • Replicat
  • Manager

Oracle GoldenGate 数据复制过程如下:

利用抽取进程(Extract Process)在源端数据库中读取Online Redo Log或者Archive Log,然后进行解析,只提取其中数据的变化信息,比如DML操作——增、删、改操作,将抽取的信息转换为GoldenGate自定义的中间格式存放在队列文件(trail file)中。再利用传输进程将队列文件(trail file)通过TCP/IP传送到目标系统。

目标端有一个进程叫Server Collector,这个进程接受了从源端传输过来的数据变化信息,把信息缓存到GoldenGate 队列文件(trail file)当中,等待目标端的复制进程读取数据。

GoldenGate 复制进程(replicat process)从队列文件(trail file)中读取数据变化信息,并创建对应的SQL语句,通过数据库的本地接口执行,提交到目标端数据库,提交成功后更新自己的检查点,记录已经完成复制的位置,数据的复制过程最终完成。

① Manager

  • 顾名思义、Manager进程是Golden Gate中进程的控制进程,用于管理 Extract,Data Pump,Replicat等进程

  • 在 Extract、Data Pump、Replicat 进程启动之前,Manager 进程必须先要在源端和目标端启动

  • 在整个 Golden Gate 运行期间,它必须保持运行状态

⒈ 监控与启动 GoldenGate 的其它进程

⒉ 管理 trail 文件及 Reporting
在 Windows 系统上,Manager 进程是作为一个服务来启动的,在 Unix 系统下是一个进程

② Extract

Extract 进程运行在数据库源端上,它是Golden Gate的捕获机制,可以配置Extract 进程来做如下工作:

⒈ 初始数据装载:对于初始数据装载,Extract 进程直接从源对象中提取数据

⒉ 同步变化捕获:保持源数据与其它数据集的同步。初始数据同步完成后,Extract 进程捕获源数据的变化;如DML变化、 DDL变化等

③ Replicat

Replicat 进程是运行在目标端系统的一个进程,负责读取 Extract 进程提取到的数据(变更的事务或 DDL 变化)并应用到目标数据库

就像 Extract 进程一样,也可以配置 Replicat 进程来完成如下工作:

  1. 初始化数据装载:对于初始化数据装载,Replicat 进程应用数据到目标对象或者路由它们到一个高速的 Bulk-load 工具上
  2. 数据同步,将 Extract 进程捕获到的提交了的事务应用到目标数据库中

④ Collector

Collector 是运行在目标端的一个后台进程
接收从 TCP/IP网络传输过来的数据库变化,并写到 Trail 文件里动态

collector:由管理进程自动启动的

collector 叫做动态

collector,用户不能与动态 collector 交互

静态 collector:可以配置成手工运行 collector,这个 collector 就称之为静态 collector

⑤ Trails

为了持续地提取与复制数据库变化,GoldenGate 将捕获到的数据变化临时存放在磁盘上的一系列文件中,这些文件就叫做 Trail 文件

这些文件可以在 source DB 上也可以在目标 DB 上,也可以在中间系统上,这依赖于选择哪种配置情况

在数据库源端上的叫做 Local Trail 或者 Extract Trail;在目标端的叫做 Remote Trail

⑥ Data Pumps

Data Pump 是一个配置在源端的辅助的 Extract 机制

Data Pump 是一个可选组件,如果不配置 Data Pump,那么由 Extract 主进程将数据发送到目标端的 Remote Trail 文件中

如果配置了 Data Pump,会由 Data Pump将Extract 主进程写好的本地 Trail 文件通过网络发送到目标端的 Remote Trail 文件中

使用 Data Pump 的好处是:

⒈ 如果目标端或者网络失败,源端的 Extract 进程不会意外终止

⒉ 需要在不同的阶段实现数据的过滤或者转换

⒊ 多个源数据库复制到数据中心

⒋ 数据需要复制到多个目标数据库

⑦ Data source

当处理事务的变更数据时,Extract 进程可以从数据库(Oracle, DB2, SQL Server, MySQL等)的事务日志中直接获取

或从 GoldenGate VAM中获取。通过 VAM,数据库厂商将提供所需的组件,用于 Extract 进程抽取数据的变更

⑧ Groups

为了区分一个系统上的多个 Extract 和 Replicat 进程,我们可以定义进程组

例如:要并行复制不同的数据集,我们可以创建两个 Replicat 组

一个进程组由一个进程组成(Extract 进程或者 Replicat 进程),一个相应的参数文件,一个 Checkpoint 文件,以及其它与之相关的文件

如果处理组中的进程是 Replicat 进程,那么处理组还要包含一个 Checkpoint 表

安装与基本配置

环境说明

软件配置 下载地址

角色 数据存储服务及版本 OGG版本 IP
源服务器 OracleRelease11.2.0.4.0 Oracle GoldenGate 12.2.0.2 for Oracle on Linux x86-64 xxx.xxx.xxx.xx1
目标服务器 cdh6.0.0 Oracle GoldenGate for Big Data 12.3.2.1.1 on Linux x86-64 xxx.xxx.xxx.xx2

以上源服务器上OGG安装在Oracle用户下,目标服务器上OGG安装在root用户下。

2、源端(Oracle)配置

注意:源端是安装了oracle的机器,oracle环境变量之前都配置好了

2.1 解压

先建立ogg目录

mkdir -p /opt/ogg

Jetbrains全家桶1年46,售后保障稳定

解压后得到一个tar包,再解压这个tar

tar xf fbo_ggs_Linux_x64_ora11g_64bit.tar -C /opt/ogg
chown -R oracle:oinstall /opt/ogg

(使oracle用户有ogg的权限,后面有些需要在oracle用户下执行才能成功

2.2 配置ogg环境变量

vim /etc/profile
export OGG_HOME=/opt/ogg
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/usr/lib
export PATH=$OGG_HOME:$PATH
source /etc/profile
Oracle打开归档模式

使用如下命令查看当前是否为归档模式(archive)

SQL> archive log list 
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            /u01/arch_log
Oldest online log sequence     6
Next log sequence to archive   8
Current log sequence           8

如非以上状态,手动调整即可

SQL> conn / as sysdba(以DBA身份连接数据库) 
SQL> shutdown immediate(立即关闭数据库)
SQL> startup mount(启动实例并加载数据库,但不打开)
SQL> alter database archivelog(更改数据库为归档模式)
SQL> alter database open(打开数据库)
SQL> alter system archive log start(启用自动归档)
Oracle打开日志相关

OGG基于辅助日志等进行实时传输,故需要打开相关日志确保可获取事务内容。通过一下命令查看当前状态:

SQL> select force_logging, supplemental_log_data_min from v$database;
FOR SUPPLEME--- --------
YES YES

如果以上查询结果非YES,可通过以下命令修改状态:

SQL> alter database force logging;
SQL> alter database add supplemental log data;
Oracle创建复制用户

为了使Oracle里用户的复制权限更加单纯,故专门创建复制用户,并赋予dba权限

SQL> create tablespaceoggtbsdatafile '/u01/app/oracle/oradata/orcl/oggtbs01.dbf' size 1000M autoextend on;
SQL> create user ggs identified by ggs default tablespaceoggtbs;
User created.
SQL> grant dba to ggs;
Grant succeeded.

最终这个ggs帐号的权限如下所示:

SQL> select * from dba_sys_privs where GRANTEE='GGS';
GRANTEE                        PRIVILEGE                                ADM
GGS                            DROP ANY DIRECTORY                       NO
GGS                            ALTER ANY TABLE                          NO
GGS                            ALTER SESSION                            NO
GGS                            SELECT ANY DICTIONARY                    NO
GGS                            CREATE ANY DIRECTORY                     NO
GGS                            RESTRICTED SESSION                       NO
GGS                            FLASHBACK ANY TABLE                      NO
GGS                            UPDATE ANY TABLE                         NO
GGS                            DELETE ANY TABLE                         NO
GGS                            CREATE TABLE                             NO
GGS                            INSERT ANY TABLE                         NO
GRANTEE                        PRIVILEGE                                ADM
GGS                            UNLIMITED TABLESPACE                     NO
GGS                            CREATE SESSION                           NO
GGS                            SELECT ANY TABLE                         NO
OGG初始化

进入OGG的主目录执行./ggsci,进入OGG命令行

[oracle@VM_0_25_centos gg]$ ./ggsci 
Oracle GoldenGate Command Interpreter for Oracle
Version 11.2.1.0.3 14400833 OGGCORE_11.2.1.0.3_PLATFORMS_120823.1258_FBO
Linux, x64, 64bit (optimized), Oracle 11g on Aug 23 2012 20:20:21
Copyright (C) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
GGSCI (VM_0_25_centos) 1>
执行create subdirs进行目录创建
GGSCI (VM_0_25_centos) 4> create subdirs
Creating subdirectories under current directory /u01/gg
Parameter files                /opt/ogg/dirprm: already exists
Report files                   /opt/ogg/dirrpt: already exists
Checkpoint files               /opt/ogg/dirchk: already exists
Process status files           /opt/ogg/dirpcs: already exists
SQL script files               /opt/ogg/dirsql: already exists
Database definitions files     /opt/ogg/dirdef: already exists
Extract data files             /opt/ogg/dirdat: already exists
Temporary files                /opt/ogg/dirtmp: already exists
Stdout files                   /opt/ogg/dirout: already exists
Oracle创建模拟复制库表

模拟建一个用户叫tcloud,密码tcloud,同时基于这个用户建一张表,叫t_ogg。

SQL> create user tcloud  identified by tcloud default tablespace users;
User created.
SQL> grant dba to tcloud;
Grant succeeded.
SQL> conn tcloud/tcloud;
Connected.
SQL> create table t_ogg(id int ,text_name varchar(20),primary key(id));
Table created.

配置全局变量

在源端服务器OGG主目录下,执行./ggsci到OGG命令行下,执行如下命令:

GGSCI (VM_0_25_centos) 1> dblogin userid ggs password ggs
Successfully logged into database.
GGSCI (VM_0_25_centos) 3> view params ./globals
ggschema ggs

其中./globals变量没有的话可以用edit params ./globals来编辑添加即可(编辑器默认使用的vim)

配置管理器mgr

在OGG命令行下执行如下命令:

GGSCI (VM_0_25_centos) 4> edit param mgr
PORT 7809
DYNAMICPORTLIST 7810-7909
AUTORESTART EXTRACT *,RETRIES 5,WAITMINUTES 3
PURGEOLDEXTRACTS ./dirdat/*,usecheckpoints, minkeepdays 3

说明:PORT即mgr的默认监听端口;DYNAMICPORTLIST动态端口列表,当指定的mgr端口不可用时,会在这个端口列表中选择一个,最大指定范围为256个;AUTORESTART重启参数设置表示重启所有EXTRACT进程,最多5次,每次间隔3分钟;PURGEOLDEXTRACTS即TRAIL文件的定期清理
在命令行下执行start mgr即可启动管理进程,通过info mgr可查看mgr状态

GGSCI (VM_0_25_centos) 5> info mgr
Manager is running (IP port VM_0_25_centos.7809).
添加复制表

在OGG命令行下执行添加需要复制的表的操作,如下:

GGSCI (VM_0_25_centos) 7> add trandata tcloud.t_ogg
Logging of supplemental redo data enabled for table TCLOUD.T_OGG.
GGSCI (VM_0_25_centos) 8> info trandata tcloud.t_ogg
Logging of supplemental redo log data is enabled for table TCLOUD.T_OGG.
Columns supplementally logged for table TCLOUD.T_OGG: ID.

配置extract进程

配置extract进程OGG命令行下执行如下命令:

GGSCI (VM_0_25_centos) 10> edit params ext2hd
extract ext2hd
dynamicresolution
SETENV (ORACLE_SID = "orcl")
SETENV (NLS_LANG = "american_america.AL32UTF8")
userid ggs,password ggs
exttrail /u01/gg/dirdat/tc
table tcloud.t_ogg;

说明:第一行指定extract进程名称;dynamicresolution动态解析;SETENV设置环境变量,这里分别设置了Oracle数据库以及字符集;userid ggs,password ggs即OGG连接Oracle数据库的帐号密码,这里使用2.3.4中特意创建的复制帐号;exttrail定义trail文件的保存位置以及文件名,注意这里文件名只能是2个字母,其余部分OGG会补齐;table即复制表的表明,支持*通配,必须以;结尾
接下来在OGG命令行执行如下命令添加extract进程:

GGSCI (VM_0_25_centos) 11> add extract ext2hd,tranlog,begin now
EXTRACT added.

最后添加trail文件的定义与extract进程绑定:

GGSCI (VM_0_25_centos) 12> add exttrail /u01/gg/dirdat/tc,extract ext2hd
EXTTRAIL added

可在OGG命令行下通过info命令查看状态:

GGSCI (VM_0_25_centos) 14> info ext2hd
EXTRACT    EXT2HD    Initialized   2016-11-09 15:37   Status STOPPED
Checkpoint Lag       00:00:00 (updated 00:02:32 ago)
Log Read Checkpoint  Oracle Redo Logs
                     2016-11-09 15:37:14  Seqno 0, RBA 0
                     SCN 0.0 (0)

配置pump进程

pump进程本质上来说也是一个extract,只不过他的作用仅仅是把trail文件传递到目标端,配置过程和extract进程类似,只是逻辑上称之为pump进程
在OGG命令行下执行:

GGSCI (VM_0_25_centos) 16> edit params push2hd
extract push2hd
passthru
dynamicresolution
userid ggs,password ggs
rmthost 10.0.0.2 mgrport 7809
rmttrail /data/gg/dirdat/tc
table tcloud.t_ogg;

说明:第一行指定extract进程名称;passthru即禁止OGG与Oracle交互,我们这里使用pump逻辑传输,故禁止即可;dynamicresolution动态解析;userid ggs,password ggs即OGG连接Oracle数据库的帐号密码,这里使用2.3.4中特意创建的复制帐号;rmthost和mgrhost即目标端OGG的mgr服务的地址以及监听端口;rmttrail即目标端trail文件存储位置以及名称

分别将本地trail文件和目标端的trail文件绑定到extract进程:

GGSCI (VM_0_25_centos) 17> add extract push2hd,exttrailsource /u01/gg/dirdat/tc
EXTRACT added.
GGSCI (VM_0_25_centos) 18> add rmttrail /data/gg/dirdat/tc,extract push2hd
RMTTRAIL added.

同样可以在OGG命令行下使用info查看进程状态:

GGSCI (VM_0_25_centos) 19> info push2hd

EXTRACT    PUSH2HD   Initialized   2016-11-09 15:52   Status STOPPED
Checkpoint Lag       00:00:00 (updated 00:01:04 ago)
Log Read Checkpoint  File /u01/gg/dirdat/tc000000
                     First Record  RBA 0

配置define文件

Oracle与MySQL,Hadoop集群(HDFS,Hive,kafka等)等之间数据传输可以定义为异构数据类型的传输,故需要定义表之间的关系映射,在OGG命令行执行:

GGSCI (VM_0_25_centos) 20> edit params tcloud
defsfile /u01/gg/dirdef/tcloud.t_ogg
userid ggs,password ggs
table tcloud.t_ogg;

在OGG主目录下执行:

./defgen paramfile dirprm/tcloud.prm

完成之后会生成这样的文件/opt/ogg/dirdef/tcloud.t_ogg,将这个文件拷贝到目标端的OGG主目录下的dirdef目录即可。

目标端的配置

环境变量配置
vim /etc/profile

#for ogg
export OGG_HOME=/opt/ogg
export LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/amd64:$JAVA_HOME/jre/lib/amd64/server:$JAVA_HOME/jre/lib/amd64/libjsig.so:$JAVA_HOME/jre/lib/amd64/server/libjvm.so:$OGG_HOME/lib
export PATH=$OGG_HOME:$PATH

OGG初始化

# ggsci
GGSCI (dev-cdh-002v) 1> create subdirs

配置管理器manager

GGSCI (dev-cdh-002v) 2> edit params mgr
PORT 7809
DYNAMICPORTLIST 7810-7909
AUTORESTART EXTRACT *,RETRIES 5,WAITMINUTES 3
PURGEOLDEXTRACTS ./dirdat/*,usecheckpoints, minkeepdays 3

配置checkpoint

checkpoint即复制可追溯的一个偏移量记录,在全局配置里添加checkpoint表即可

GGSCI (dev-cdh-002v) 5> edit  params  ./GLOBALS
CHECKPOINTTABLE tcloud.checkpoint

保存即可

配置replicate进程

本步骤接收端为hdfs文件
在OGG的命令行下执行:

GGSCI (dev-cdh-002v) 8> edit params r2hdfs
REPLICAT r2hdfs
sourcedefs /data/gg/dirdef/tcloud.t_ogg
TARGETDB LIBFILE libggjava.so SET property=dirprm/hdfs.props
REPORTCOUNT EVERY 1 MINUTES, RATE 
GROUPTRANSOPS 10000
MAP tcloud.t_ogg, TARGET tcloud.t_ogg;

tcloud.t_ogg 文件由源端自动生成,放入主目录下dirdef 目录下即可

其中上述中
管理器manager的配置文件 mgr.prm
replicate的配置文件 r2hdfs.prm
以及下面的hdfs接收配置文件 hdfs.props
均可在 /opt/ogg/dirprm/目录下编辑

hdfs.pops

gg.handlerlist=hdfs

gg.handler.hdfs.type=hdfs
gg.handler.hdfs.pathMappingTemplate=/ogg/replication/hive
gg.handler.hdfs.mode=op
gg.handler.hdfs.format=delimitedtext

goldengate.userexit.writers=javawriter
javawriter.stats.display=TRUE
javawriter.stats.full=TRUE

gg.log=log4j
gg.log.level=INFO

gg.report.time=30sec

#Sample gg.classpath for Apache Hadoop
#gg.classpath=/var/lib/hadoop/share/hadoop/common/*:/var/lib/hadoop/share/hadoop/common/lib/*:/var/lib/hadoop/share/hadoop/hdfs/*:/var/lib/hadoop/share/hadoop/hdfs/lib/*:/var/lib/hadoop/etc/hadoop/:
#Sample gg.classpath for CDH
gg.classpath=/opt/cloudera/parcels/CDH/lib/hadoop/client/*:/etc/hadoop/conf
#Sample gg.classpath for HDP
#gg.classpath=/usr/hdp/current/hadoop-client/client/*:/etc/hadoop/conf

可参照 /opt/ogg/AdapterExamples/big-data/hdfs 目录下的样例文件进行编辑
具体的OGG for Big Data支持参数以及定义可参考地址
https://docs.oracle.com/goldengate/bd1221/gg-bd/GADBD/GUID-85A82B2E-CD51-463A-8674-3D686C3C0EC0.htm#GADBD376

kafka接收数据配置

新定义一个replicate 进程为rekafka.prm

REPLICAT rekafka
sourcedefs /opt/ogg/dirdef/tcloud.t_ogg
TARGETDB LIBFILE libggjava.so SET property=dirprm/kafka.props
REPORTCOUNT EVERY 1 MINUTES, RATE 
GROUPTRANSOPS 10000
MAP tcloud.t_ogg, TARGET tcloud.t_ogg;

另新建一个kafka接收配置文件
kafka.props

gg.handlerlist=kafkahandler
gg.handler.kafkahandler.type=kafka
gg.handler.kafkahandler.KafkaProducerConfigFile=custom_kafka_producer.properties
gg.handler.kafkahandler.topicMappingTemplate=test_ogg
gg.handler.kafkahandler.format=json
gg.handler.kafkahandler.mode=op

goldengate.userexit.writers=javawriter
javawriter.stats.display=TRUE
javawriter.stats.full=TRUE

gg.log=log4j
gg.log.level=INFO

gg.report.time=30sec

gg.classpath=dirprm/:/opt/cloudera/parcels/CDH/lib/kafka/libs/*:/opt/cloudera/parcels/CDH/etc/kafka/conf.dist/*:/opt/ogg/:/opt/ogg/lib/*
javawriter.bootoptions=-Xmx512m -Xms32m -Djava.class.path=ggjava/ggjava.jar

同时新建一个kafka信息配置文件custom_kafka_producer.properties

bootstrap.servers=172.17.194.18:9092,172.17.194.19:9092,172.17.194.20:9092
acks=1
compression.type=gzip
reconnect.backoff.ms=1000
value.serializer=org.apache.kafka.common.serialization.ByteArraySerializer
key.serializer=org.apache.kafka.common.serialization.ByteArraySerializer
batch.size=102400
linger.ms=10000

以上文件同样可参考
/opt/ogg/AdapterExamples/big-data/kafka/目录下的样例文件或者
https://docs.oracle.com/goldengate/bd1221/gg-bd/GADBD/GUID-2561CA12-9BAC-454B-A2E3-2D36C5C60EE5.htm#GADBD449

测试

6.1 启动所有进程

在源端和目标端的OGG命令行下使用start [进程名]的形式启动所有进程。
启动顺序按照源mgr——目标mgr——源extract——源pump——目标replicate来完成。
全部需要在ogg目录下执行ggsci目录进入ogg命令行。

源端依次是

start mgr
start extkafka
start pukafka

目标端

start mgr
start rekafka

可以通过info all 或者info [进程名] 查看状态,所有的进程都为RUNNING才算成功
源端

GGSCI (ambari.master.com) 5> info all

Program     Status      Group       Lag at Chkpt  Time Since Chkpt

MANAGER     RUNNING                                           
EXTRACT     RUNNING     EXTKAFKA    04:50:21      00:00:03    
EXTRACT     RUNNING     PUKAFKA     00:00:00      00:00:03

目标端

GGSCI (ambari.slave1.com) 3> info all

Program     Status      Group       Lag at Chkpt  Time Since Chkpt

MANAGER     RUNNING                                           
REPLICAT    RUNNING     REKAFKA     00:00:00      00:00:01

6.2 异常解决

如果有不是RUNNING可通过查看日志的方法检查解决问题,具体通过下面两种方法

vim ggser.log
1
或者ogg命令行,以rekafka进程为例

GGSCI (ambari.slave1.com) 2> view report rekafka

kafka查看过来的数据

kafka-topics --describe --zookeeper l172.17.194.18:2181,172.17.194.19:2181,172.17.194.20:2181 --topic test_ogg

添加主键

在kafka.props添加

gg.handler.kafkahandler.format.includePrimaryKeys=true

参考资料:

https://www.cnblogs.com/purpleraintear/p/6071038.html

https://blog.csdn.net/dkl12/article/details/80447154

https://docs.oracle.com/goldengate/bd1221/gg-bd/GADBD/GUID-2561CA12-9BAC-454B-A2E3-2D36C5C60EE5.htm#GADBD449

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/226927.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号