"커서"는 사용자가 실행하는 SQL 문에 할당되는 라이브러리 캐시의 메모리 영역입니다. 이 메모리 영역은 SQL 텍스트, SQL 실행 계획, 통계 등과 같은 SQL 문에 대한 주요 정보를 저장합니다.
각 SQL 문에는 하나의 상위 커서와 하나 이상의 하위 커서가 있습니다. 상위 및 하위 커서가 무엇인지 설명합니다. 커서 = 메모리 영역을 염두에 두십시오.
왜 커서가 두 종류인가?
두 종류의 커서(부모 및 자식)가 있는 것은 Oracle 데이터베이스 설계에 따른 것입니다.
실행하는 각 SQL 문에 대해 Oracle 엔진은 상위 및 하위 커서라는 두 개의 커서를 생성합니다. 동일한 SQL 문에 대해 다른 바인드 값이나 두 개의 다른 스키마 또는 다른 리터럴 값 등이 있을 수 있는 것과 같은 다른 차이점이 있을 수 있기 때문에 두 개의 커서가 생성됩니다.
상위 커서는 SQL 문을 보유하고 하위 커서는 정보를 보유합니다. 차이점과 관련이 있습니다. 이것은 본질적으로 SQL 문이 하드 또는 소프트 구문 분석을 수행할 것인지 여부를 결정하는 요소로 자식 커서를 만듭니다.
PARENT CURSOR
커서의 SQL 텍스트를 저장합니다. 두 문장이 동일한 경우 동일한 상위 커서를 공유합니다.
모든 상위 커서는 그에 대해 생성된 하나 이상의 하위 커서와 함께 실행됩니다.
상위 커서는 V$SQLAREA 뷰에 표시됩니다. v$sqlarea의 VERSION_COUNT 열은 이 부모 커서에 몇 개의 자식 커서가 있는지 알려줍니다.
CHILD CURSOR
부모 커서는 적어도 하나의 자식 커서를 가진다.
상위 커서는 SQL 텍스트를 저장하지만, 하위 커서는 환경 정보, 통계 정보, 바인드 변수 정보, 실행 세부 정보와 같은 SQL 문과 관련된 중요한 정보를 저장합니다.
SQL 텍스트가 자식 커서에 저장되지 않으므로 자식 커서는 메모리 공간을 덜 차지합니다.
모든 자식 커서는 부모에 속해야 합니다.
쿼리에 대해 자식 커서는 하드 파싱을 할지 또는 소프트 파싱을 할지를 결정합니다. SQL 쿼리가 동일해서 부모 커서는 동일하지만 자식 커서가 공유되지 않고 하드 파싱(재컴파일)을 하는 상황이 있을 수 있습니다.
상위 커서는 V$SQL 보기에 표시됩니다.
V$SQL_SHARED_CURSOR는 옵티마이저가 커서를 비공유로 표시하기로 결정한 이유를 제공하므로 매우 유용한 보기입니다. 따라서 SQL 문이 동일하지만 하드파싱이 발생 때 이 뷰를 참조합니다.
V$SQL_SHARED_CURSOR
동일한 상위 커서에 대해 둘 이상의 하위 커서가 생성되되어었을 때 기존 하위 커서와 공유되지 않는 이유를 설명합니다. 뷰의 각 열은 커서를 공유할 수 없는 이유를 식별합니다. 공유되지 않은 사유의 열 값은 "Y" 로 표시됩니다.
특정 자식은 여러 가지 이유로 공유에 실패했을 수 있습니다. 이 이유는 다른 기존 자식 커서를 사용하려는 이유가 됩니다.
cursor_sharing 파라미터
CURSOR_SHARING은 어떤 SQL이 동일한 커서를 공유할 수 있는지를 결정합니다. 세 가지 값이 있습니다.
EXACT
동일한 텍스트가 있는 SQL 구문만 동일한 커서를 공유할 수 있습니다.
FORCE
일부 문자가 다를 경우 그 문자가 SQL문의 의미에 영향을 미치지 않는 한 강제로 커서를 공유합니다.
SIMILAR
문자가 SQL문의 의미나 실행계획 최적화에 영향을 미치지 않는 한 일부 문자가 달라도 동일한 커서로 공유하도록 합니다. cursor_sharing의 default는 EXACT입니다.
예를 들어 아래 두 개의 서로 다른 SQL 문이 있습니다.
select * from EMP WHERE EMPNO=7369;
select * from EMP where EMPNO=7369;
둘 다 동일한 결과를 생성하지만 이들은 서로 다른 SQL입니다. "where"를 보면 첫 번째 문장에서는 대문자로, 두 번째 문장에서는 소문자로 작성되어 있는데 Oracle optimizer는 두 개를 상이한 SQL로 판단합니다.
V$SQLAREA 뷰를 조회합니다. 부모 커서에 대한 정보를 보여줍니다.
V$SQLAREA 에서는 SQL문에 대한 Parsing 정보 (sql text, sql_id, parse calls, executions 등)와 메모리 사용량, CPU 사용량, 수행시간, 모듈정보 등 외에도 많을 정보를 확인할 수 있습니다.
Oracle DB 에서 실행한 SQL 내역을 조회하고자 할때 v$sql 딕셔너리 뷰를 이용할 수 있습니다.
V$SQL을 조회해 봅니다. 아래와 같이 2개의 SQL 문이 조회됩니다.
v$sql 에는 실행한 SQL 문과 실행 시작시간, 종료시간, 경과시간 등의 다양한 정보가 들어있습니다.
select sql_text, sql_id, sharable_mem, loaded_versions, open_versions, executions,
loads, parse_calls, buffer_gets, rows_processed, elapsed_time,
is_obsolete, is_bind_sensitive, is_bind_aware
from v$sql
where upper(sql_text) like upper('%select * from EMP%7369%')
and upper(sql_text) not like upper('%v$sql%');
-- SQL 수행결과
SQL_TEXT SQL_ID SHARABLE_MEM LOADED_VERSIONS OPEN_VERSIONS EXECUTIONS LOADS PARSE_CALLS BUFFER_GETS ROWS_PROCESSED ELAPSED_TIME IS_OBSOLETE IS_BIND_SENSITIVE IS_BIND_AWARE
select * from EMP WHERE EMPNO=7369 2zp7d0gmunwfj 23539 1 0 1 1 1 7 1 1118 N N N
select * from EMP where EMPNO=7369 fah6htfu5fdjg 23539 1 1 1 1 1 7 1 1280 N N N
V$SQL_SHARED_CURSOR
로드된 각 자식 커서에 대한 정보를 보여줍니다. 커서를 공유할 수 없는 이유를 설명하는 컬럼을 가지고 있습니다.
select * from v$sql_shared_cursor
where sql_id in('2zp7d0gmunwfj','fah6htfu5fdjg');
-- SQL 수행 결과
SQL_ID ADDRESS CHILD_ADDRESS CHILD_NUMBER UNBOUND_CURSOR SQL_TYPE_MISMATCH OPTIMIZER_MISMATCH OUTLINE_MISMATCH STATS_ROW_MISMATCH LITERAL_MISMATCH FORCE_HARD_PARSE EXPLAIN_PLAN_CURSOR BUFFERED_DML_MISMATCH PDML_ENV_MISMATCH INST_DRTLD_MISMATCH SLAVE_QC_MISMATCH TYPECHECK_MISMATCH AUTH_CHECK_MISMATCH BIND_MISMATCH DESCRIBE_MISMATCH LANGUAGE_MISMATCH TRANSLATION_MISMATCH BIND_EQUIV_FAILURE INSUFF_PRIVS INSUFF_PRIVS_REM REMOTE_TRANS_MISMATCH LOGMINER_SESSION_MISMATCH INCOMP_LTRL_MISMATCH OVERLAP_TIME_MISMATCH EDITION_MISMATCH MV_QUERY_GEN_MISMATCH USER_BIND_PEEK_MISMATCH TYPCHK_DEP_MISMATCH NO_TRIGGER_MISMATCH FLASHBACK_CURSOR ANYDATA_TRANSFORMATION PDDL_ENV_MISMATCH TOP_LEVEL_RPI_CURSOR DIFFERENT_LONG_LENGTH LOGICAL_STANDBY_APPLY DIFF_CALL_DURN BIND_UACS_DIFF PLSQL_CMP_SWITCHS_DIFF CURSOR_PARTS_MISMATCH STB_OBJECT_MISMATCH CROSSEDITION_TRIGGER_MISMATCH PQ_SLAVE_MISMATCH TOP_LEVEL_DDL_MISMATCH MULTI_PX_MISMATCH BIND_PEEKED_PQ_MISMATCH MV_REWRITE_MISMATCH ROLL_INVALID_MISMATCH OPTIMIZER_MODE_MISMATCH PX_MISMATCH MV_STALEOBJ_MISMATCH FLASHBACK_TABLE_MISMATCH LITREP_COMP_MISMATCH PLSQL_DEBUG LOAD_OPTIMIZER_STATS ACL_MISMATCH FLASHBACK_ARCHIVE_MISMATCH LOCK_USER_SCHEMA_FAILED REMOTE_MAPPING_MISMATCH LOAD_RUNTIME_HEAP_FAILED HASH_MATCH_FAILED PURGED_CURSOR BIND_LENGTH_UPGRADEABLE USE_FEEDBACK_STATS CON_ID
2zp7d0gmunwfj 000000008CA91018 000000008CA908C0 0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0
fah6htfu5fdjg 000000008C9AD6E0 000000008A6EEB18 0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0
V$SQLAREA 는 부모 커서에 대한 정보를 담고 있고, V$SQL 은 자식 커서에 대한 정보를 담고 있습니다.
V$SQL_SHARED_CURSOR 은 커서를 공유하지 못한 사유에 대한 정보를 담고 있습니다.
foreground로 실행되니 최종 "Creating new log file" 보이면 다음 단계를 진행합니다.
[2022-01-01 00:34:06,106] INFO ______ _ (org.apache.zookeeper.server.ZooKeeperServer)
[2022-01-01 00:34:06,107] INFO |___ / | | (org.apache.zookeeper.server.ZooKeeperServer)
[2022-01-01 00:34:06,107] INFO / / ___ ___ | | __ ___ ___ _ __ ___ _ __ (org.apache.zookeeper.server.ZooKeeperServer)
[2022-01-01 00:34:06,108] INFO / / / _ \ / _ \ | |/ / / _ \ / _ \ | '_ \ / _ \ | '__| (org.apache.zookeeper.server.ZooKeeperServer)
[2022-01-01 00:34:06,108] INFO / /__ | (_) | | (_) | | < | __/ | __/ | |_) | | __/ | | (org.apache.zookeeper.server.ZooKeeperServer)
[2022-01-01 00:34:06,109] INFO /_____| \___/ \___/ |_|\_\ \___| \___| | .__/ \___| |_| (org.apache.zookeeper.server.ZooKeeperServer)
[2022-01-01 00:34:06,109] INFO | | (org.apache.zookeeper.server.ZooKeeperServer)
[2022-01-01 00:34:06,110] INFO |_| (org.apache.zoo
..... .....
[2022-01-01 00:34:10,369] INFO Using checkIntervalMs=60000 maxPerMinute=10000 maxNeverUsedIntervalMs=0 (org.apache.zookeeper.server.ContainerManager)
[2022-01-01 00:34:10,373] INFO ZooKeeper audit is disabled. (org.apache.zookeeper.audit.ZKAuditProvider)
[2022-01-01 01:08:12,522] INFO Creating new log file: log.1 (org.apache.zookeeper.server.persistence.FileTxnLog)
[2022-01-01 01:08:14,923] WARN fsync-ing the write ahead log in SyncThread:0 took 2389ms which will adversely effect operation latency.File size is 67108880 bytes. See the ZooKeeper troubleshooting guide (org.apache.zookeeper.server.persistence.FileTxnLog)
config/zookeeper.properties 파일을 보면 clientPort 속성이 2181로 설정된 것을 볼 수 있습니다. 이 속성은 Zookeeper 서버가 현재 수신 대기 중인 포트입니다.
# File: kafka_2.13-3.0.0/config/zookeeper.properties
# the port at which the clients will connect
clientPort=2181
Kafka Broker 실행하기
Kafka 브로커는 클러스터의 핵심이며 데이터가 저장되고 배포되는 파이프라인 역할을 합니다. Zookeeper를 시작한 방법과 유사하게,
브로커 서버를 시작하고(bin/kafka-server-start.sh) 구성(config/server.properties)하기 위한 두 개의 파일이 있습니다. kafka의 분산환경 구성을 해야하기 때문에 다이어그램과 같이 3개의 브로커를 시작하겠습니다. config/server.properties 파일을 열면 여러 구성 옵션이 표시됩니다(지금은 대부분 무시할 수 있음). 그러나 각 브로커 인스턴스에 대해 고유해야 하는 세 가지 속성이 있습니다.
File: kafka_2.13-3.0.0/config/server.properties
# The id of the broker. This must be set to a unique integer for each broker.
broker.id=0
# The address the socket server listens on. It will get the value returned from
listeners=PLAINTEXT://:9092
# A comma separated list of directories under which to store log files
log.dirs=/tmp/kafka-logs
zookeeper.connect=localhost:2181
* 주키퍼 서버들 멀티로 구성한 경우에는 zookeeper.connect 에 나열해주면 됩니다.
주제의 파티션 및 복제본에 대한 세부 정보를 출력합니다. Partition, Leader/follower, Replicas, Isr(In Sync Replica) 정보를 보여줍니다. 여기서 ISR은 kafka 리더 파티션과 팔로워 파티션이 모두 싱크가 된 상태를 나타냅니다. 만일, 브로커 중 1대의 서버가 중지된 상태라면 Isr 은 2개 만 표시됩니다. 3번 브로커 서버가 중지되었다면 Leader는 1 또는 2가 되고 Isr 은 1,2 가 됩니다.
KIP-226(Kafka Improvement Proposal)은 브로커 구성의 동적 업데이트에 대한 지원을 추가했습니다. 브로커를 다시 시작하지 않고 클러스터에서 주제를 동적으로 삭제할 수 있도록 허용합니다.(동적 허용을 하지 않으려면 server.properties 구성에서 "delete.topic.enable" 구성을 "false"로 설정하면 됩니다.)
Caused by: org.apache.kafka.common.errors.InvalidRequestException: Invalid config value for resource ConfigResource(type=BROKER, name=''): Cannot update these configs dynamically: Set(delete.topic.enable)
2.
Exception in thread "main" joptsimple.UnrecognizedOptionException: zookeeper is not a recognized option at joptsimple.OptionException.unrecognizedOption(OptionException.java:108)
3.
Invalid config(s): delete.topic.enable
아직 동적 config 설정이 정상작동 하지 않는 것 같다. 패치버전이나 더 상위 버전이 나오는 다시 확인해 본다.
Zookeeper 쉘을 이용한 방법
* 주키퍼로 삭제할지 말고 kafka-topics.sh 로 삭제하는 것을 권장합니다. 주키퍼는 znode 관리용입니다.
zookeeper-shell.sh 를 이용하여서 znode를 삭제할 수 있습니다.
rmr명령은 더이상 사용되진 않는다. delete나 deleteall로 삭제합니다. delete 를 사용할 경우 message가 남아있는 경우 삭제가 되지 않습니다. 이럴 경우, deleteall로 삭제할 수 있습니다.
$ bin/zookeeper-shell.sh localhost:2181
ls /brokers/topics
## 실행결과
[__consumer_offsets, movie, music, my-kafka-topic]
rmr /brokers/topics/my-kafka-topic
## 실행결과. rmr은 사용할 수 없다.
Command not found: Command not found rmr
## The zkCli provides the rmr (deprecated) or deleteall command for this purpose
delete /brokers/topics/my-kafka-topic
## 실행결과
Node not empty: /brokers/topics/my-kafka-topic
deleteall /brokers/topics/my-kafka-topic
ls /brokers/topics
[__consumer_offsets, movie, music]
quit
## 삭제된 topic을 다시 생성해본다.
$ bin/kafka-topics.sh --create --topic my-kafka-topic --bootstrap-server localhost:9093 --partitions 3 --replication-factor 2
## 오류가 발생한다. topic을 kafka-topics.sh 로 조회하면 목록이 보인다.
## zookeeper와 kafka broker 간이 연동이 잘 안되는 것 같다.
Error while executing topic command : Topic 'my-kafka-topic' already exists
* 주키퍼로 삭제할지 말고 kafka-topics.sh 로 삭제하는 것을 권장합니다. 주키퍼는 znode 관리용입니다.
Producers: Topic에 메시지 보내기
"생산자(Producer)"는 데이터를 Kafka 클러스터에 넣는 프로세스입니다.
bin 디렉토리의 명령어는 콘솔에 텍스트를 입력할 때마다 클러스터에 데이터를 입력하는 콘솔 생성자(Producer)를 제공합니다.
이제 데이터를 입력하고 Enter 키를 치면, Kafka 클러스터에 텍스트를 입력할 수 있는 명령 프롬프트가 표시됩니다.
컨슈머가 데이터를 가져가도 Topic 데이터는 삭제되지 않습니다.
>first insert
>두번째 입력
프로듀서가 데이터를 보낼 때 '파티션키'를 지정해서 보낼 수 있습니다.
파티션키를 지정하지 않으면, 라운드로빈 방식으로 파티션에 저장하고,
파티션키를 지정하면, 파티셔너가 파티션키의 HASH 값을 구해서 특정 파티션에 할당합니다.
카프카에서 kafka-console-producer.sh로 Consumer에게 메세지를 보낼 때 기본적으로 key값이 null로 설정되어 있습니다. 이럴 때 설정에서 parse.key 및 key.separator 속성을 설정하면 key와 value가 포함된 메시지를 보낼 수 있습니다.
Kafka consumers 를 사용하여 클러스터에서 데이터를 읽을 수 있습니다. 이 경우 이전 섹션에서 생성한 데이터를 읽습니다. consumer를 시작하려면 다음 명령을 실행합니다. 아래와 같이 위에서 pruducer가 입력한 데이터가 출력됩니다.
bin/kafka-console-consumer.sh --bootstrap-server localhost:9093 --topic my-kafka-topic --from-beginning
first insert
두번째 입력
bootstrap-server는 클러스터의 브로커 중 하나일 수 있습니다.
Topic은 생산자가 클러스터에 데이터를 입력한 Topic(주제)과 동일해야 합니다.
from-beginning은 클러스터에 현재 가지고 있는 모든 메시지를 원한다고 클러스터에 알립니다.
컨슈머 그룹이 다른 새로운 컨슈머가 auto.offset.reset=earliest 설정으로 데이터를 0번부터 가져갈 수 있습니다. 설정하지 않으면 새롭게 토픽에 생성된 메세지만 읽어옵니다.
위의 명령을 실행하면 콘솔에 로그온한 생산자가 입력한 모든 메시지가 즉시 표시됩니다. 소비자가 실행되는 동안 생산자가 메시지를 입력하면 실시간으로 콘솔에 출력되는 것을 볼 수 있습니다.
이런 식으로 Kafka는 지속적인 메시지 대기열처럼 작동하여 소비자가 아직 읽지 않은 메시지를 저장하고 소비자가 실행되는 동안 새 메시지가 오는 대로 전달합니다.
카프카에서는 consumer 그룹이라는 개념이 있는데 --consumer-property group.id=group-01 형식으로 consumer 그룹을 지정할 수 있습니다. 카프카 브로커는 컨슈머 그룹 중 하나의 컨슈머에게만 이벤트를 전달합니다. 동일한 이벤트 처리를 하는 컨슈머를 clustering 한 경우에 컨슈머 그룹으로 지정하면 클러스터링된 컨슈머 중 하나의 서버가 데이터를 수신합니다.
key와 value를 콘솔창에 표시하기 위해서는 --property print.key=true --property key.separator=: 를 설정합니다.
기존의 Message Queue 솔루션에서는 컨슈머가 메시지를 가져가면, 해당 메세지를 큐에서 삭제된다. 즉, 하나의 큐에 대하여 여러 컨슈머가 붙어서 같은 메세지를 컨슈밍할 수 없다. 하지만 Kafka는, 컨슈머가 메세지를 가져가도 큐에서 즉시 삭제되지 않으며, 하나의 토픽에 여러 컨슈머 그룹이 붙어 메세지를 가져갈 수 있다.
또한 각 consumer group마다 해당 topic의 partition에 대한 별도의 offset을 관리하고, group에 컨슈머가 추가/제거 될 때마다 rebalancing을 하여 group 내의 consumer에 partition을 할당하게 된다. 이는 컨슈머의 확장/축소를 용이하게 하고, 하나의 MQ(Message Queue)를 컨슈머 별로 다른 용도로 사용할 수 있는 확장성을 제공한다.
reset-offsets의 옵션으로 --to-earlist , --to-datetime, --from-file, --to-current, --shift-by 등이 있다 - --shift-by -2 를 하면 오프셋이 2칸 전으로 이동한다
execute의 옵션으로 --all-topics 와 --topic [그룹 이름] 이 있다
복제 테스트 : 브로커가 Offline 되면 어떤 일이?
이제 시스템에 Kafka 클러스터가 설정되었으므로 데이터 복제를 테스트해 보겠습니다.
실행한 3개의 브로커 중 첫 번째 브로커를 Control + C 키로 종료합니다.
# 첫번째 브로커 중지
[2022-01-01 02:09:13,095] INFO Metrics reporters closed (org.apache.kafka.common.metrics.Metrics)
[2022-01-01 02:09:13,097] INFO Broker and topic stats closed (kafka.server.BrokerTopicStats)
[2022-01-01 02:09:13,098] INFO App info kafka.server for 1 unregistered (org.apache.kafka.common.utils.AppInfoParser)
[2022-01-01 02:09:13,099] INFO [KafkaServer id=1] shut down completed (kafka.server.KafkaServer)
실행한 3개의 브로커 중 하나를 종료해도 클러스터가 클러스터가 제대로 실행되는지 아래 명령어를 실행합니다. 다른 터미널 창에서 다른 소비자를 시작해 보겠습니다.
bin/kafka-console-consumer.sh --bootstrap-server localhost:9094 --topic my-kafka-topic --from-beginning --group group2
real-time data
두번째 입력
awesome!!!
first insert
여기에 추가한 것은 이 소비자를 다른 소비자와 구별하는 그룹 옵션입니다. 명령을 실행하면 처음부터 입력된 모든 메시지가 표시됩니다. 동일한 소비자인 경우에는 이미 데이터를 읽었기 때문에 데이터가 보지이 않습니다.
중개인 중 하나가 중지되었지만 데이터는 손실되지 않았습니다. 이는 이전에 설정한 복제 계수(replication-factor)를 2로 설정하여 데이터 사본이 여러 브로커에 존재하도록 했기 때문입니다.
? 의문점 : 위에서 보는 것처럼 입력한 순서대로 출력되지 않았습니다. 한글때문인지 아니면 원래 순서가 없는 것인지 정확한 이유는 파악하지 못했습니다. 추후 확인이 필요한 사안입니다.
다른 브로커를 중단하면 어떻게 될까요?
본 문서에서는 두번 째 브로커도 중지하고 테스트 해보겠습니다.
이 경우에는 데이터 조회가 되지 않네요? 브로커를 3개로 구성한 경우 2개의 브로커가 장애가 발생한 경우 정상 작동하지 않습니다. 즉, 브로커의 과반수 이상에 장애가 발생하면 정상 작동하지 않습니다.
Kafka 생산자 및 소비자 구현
클러스터를 실행하고 나면 애플리케이션 코드에서 생산자와 소비자를 구현할 수 있습니다. Golang 또는 Node.js에서 Kafka 생산자 및 소비자를 구현하는 방법은 링크된 문서를 참고하시면 됩니다.
로컬 환경에 Java 8 이상이 설치되어 있어야 하고, zookeeper 가 설치 및 실행되고 있어야 합니다. zookeeper가 설치되어 있을 경우, zookeeper 를 시작합니다.
# Start the ZooKeeper service
# Note: Soon, ZooKeeper will no longer be required by Apache Kafka.
$ bin/zookeeper-server-start.sh config/zookeeper.properties
Kafka는 여러 시스템에서 이벤트(문서에서 레코드 또는 메시지라고도 함)를 읽고, 쓰고, 저장하고, 처리할 수 있는 분산 이벤트 스트리밍 플랫폼입니다. 이벤트의 예로는 결제 거래, 휴대폰의 지리적 위치 업데이트, 배송 주문, IoT 장치 또는 의료 장비의 센서 측정 등이 있습니다. 이러한 이벤트는 주제별로 구성 및 저장됩니다. 매우 단순화된 주제는 파일 시스템의 폴더와 유사하고 이벤트는 해당 폴더의 파일로 생각하면 이해가 쉽습니다. 이벤트를 작성하기 전에 topic을 작성해야 합니다. 다른 터미널 세션을 열고 다음을 실행하여 topic을 생성합니다.
Kafka 클라이언트는 이벤트 쓰기(또는 읽기)를 위해 네트워크를 통해 Kafka 브로커와 통신합니다. 일단 수신되면 브로커는 필요한 기간 동안(또는영원히) 내구성 및 내결함성 방식으로 이벤트를 저장합니다. 콘솔 생산자 클라이언트를 실행하여 주제에 이벤트를 작성합니다. 입력하는 각 행은 topic에 이벤트로 작성됩니다.
$ bin/kafka-console-producer.sh --topic quickstart-events --bootstrap-server localhost:9092
>This is my first event
>This is my second event
다른 터미널 세션을 열고 콘솔 소비자 클라이언트를 실행하여 방금 생성한 이벤트를 읽습니다. 최초 수행 시 "internal topic __consumer_offsets" 이 자동 생성됩니다.
$ bin/kafka-console-consumer.sh --topic quickstart-events --from-beginning --bootstrap-server localhost:9092
This is my first event
This is my second event
Ctrl-C를 사용하여 언제든지 소비자 클라이언트를 중지할 수 있습니다. 이벤트는 Kafka에 영구적으로 저장되기 때문에 원하는 만큼 많은 소비자가 이벤트를 읽을 수 있습니다. 또 다른 터미널 세션을 열고 이전 명령을 다시 실행하여 이를 쉽게 확인할 수 있습니다.
Topics 삭제
이전버전 :
이전 버전에서는 kafka server.properties파일에 설정을 하고 kafka broker를 재기동해야 topic을 삭제할 수 있습니다. 단, 이벤트를 읽고 있는 consumber는 에러(Error while fetching metadata with correlation)가 발생합니다.
KIP-226(Kafka Improvement Proposal)은 브로커 구성의 동적 업데이트에 대한 지원을 추가했습니다. 브로커를 다시 시작하지 않고 클러스터에서 주제를 동적으로 삭제할 수 있도록 허용합니다.(동적 허용을 하지 않으려면 server.properties 구성에서 "delete.topic.enable" 구성을 "false"로 설정하면 됩니다.)
관계형 데이터베이스 또는 기존 메시징 시스템과 같은 기존 시스템과 이미 이러한 시스템을 사용하는 많은 애플리케이션에 많은 데이터가 있을 수 있습니다. Kafka Connect를 사용하면 외부 시스템에서 Kafka로 또는 그 반대로 데이터를 지속적으로 수집할 수 있습니다. 이 프로세스를 더욱 쉽게 만들기 위해 수백 개의 커넥터를 사용할 수 있습니다. Kafka에서 데이터를 지속적으로 가져오거나 내보내는 방법에 대해 자세히 알아보려면 Kafka Connect section 섹션을 살펴보세요.
데이터가 Kafka에 이벤트로 저장되면 Java/Scala용 Kafka Streams 클라이언트 라이브러리를 사용하여 데이터를 처리할 수 있습니다. 이를 통해 입력 및/또는 출력 데이터가 Kafka 주제에 저장되는 실시간 애플리케이션 및 마이크로서비스를 구현할 수 있습니다. Kafka Streams는 클라이언트 측에서 표준 Java 및 Scala 애플리케이션을 작성하고 배포하는 단순성과 Kafka의 서버 측 클러스터 기술의 이점을 결합하여 이러한 애플리케이션을 확장성, 탄력성, 내결함성 및 분산성을 높입니다. 라이브러리는 정확히 한 번 처리, 상태 저장 작업 및 집계, 윈도우, 조인, 이벤트 시간 기반 처리 등을 지원합니다.
이벤트 스트리밍은 인체의 디지털 중추 신경계라고 할 수 있으며 '상시 가동' 세상을 위한 기반 기술입니다. 기술적으로 말하면 이벤트 스트리밍은 데이터베이스, 센서, 모바일 장치, 클라우드 서비스 및 소프트웨어 애플리케이션과 같은 이벤트 소스에서 이벤트 스트림의 형태로 실시간으로 데이터를 캡처하는 방식입니다.
나중에 검색할 수 있도록 이러한 이벤트 스트림을 영구적으로 저장합니다. 소급적으로나 실시간으로 이벤트 스트림을 조작, 처리 및 반응합니다. 필요에 따라 이벤트 스트림을 다른 목적지 기술로 라우팅하는 단계를 포함합니다. 이벤트 스트리밍은 올바른 정보가 적시에 적절한 위치에 있도록 데이터의 지속적인 흐름과 해석을 보장합니다.
이벤트 스트리밍은 무엇에 사용할 수 있습니까?
이벤트 스트리밍은 수많은 산업 및 조직의 다양한 사용 사례에 적용됩니다.
증권 거래소, 은행 및 보험과 같은 실시간으로 지불 및 금융 거래를 처리합니다.
물류 및 자동차 산업과 같이 자동차, 트럭, 차량 및 선적을 실시간으로 추적하고 모니터링합니다.
공장 및 풍력 발전 단지와 같은 IoT 장치 또는 기타 장비의 센서 데이터를 지속적으로 캡처하고 분석합니다.
소매, 호텔 및 여행 산업, 모바일 애플리케이션과 같은 고객 상호 작용 및 주문을 수집하고 즉시 대응합니다.
병원에서 치료 중인 환자를 모니터링하고 상태 변화를 예측하여 응급 상황에서 시기 적절한 치료를 보장합니다.
문서에서는 기록 또는 메시지라고도 합니다. Kafka에서 데이터를 읽거나 쓸 때 이벤트 형식으로 이 작업을 수행합니다.
개념적으로 이벤트에는 키, 값, 타임스탬프 및 선택적 메타데이터 헤더가 있습니다.
다음은 이벤트의 예입니다.
Event key: "Alice"
Event value: "Made a payment of $200 to Bob"
Event timestamp: "Jun. 25, 2020 at 2:06 p.m."
생산자(Producers)는
Kafka에 이벤트를 게시(쓰기)하는 클라이언트 응용 프로그램이고
소비자(consumers)는
이러한 이벤트를 구독(읽기 및 처리)하는 응용 프로그램입니다.
Kafka에서 생산자와 소비자는 완전히 분리되고 서로 알 수 없으며, 이는 Kafka가 높은 확장성을 달성하기 위한 핵심 설계 요소입니다. 예를 들어 생산자는 소비자를 기다릴 필요가 없습니다. Kafka는 이벤트를 정확히 한 번 처리하는 기능과 같은 다양한 보장성을 제공합니다.
이벤트는 주제(topics)로 구성되고 영구적으로 저장됩니다. 간단하게 주제는 파일 시스템의 폴더와 유사하고 이벤트는 해당 폴더의 파일입니다. 예로써 주제 이름은 "지불"일 수 있습니다.
Kafka의 토픽은 항상 다중 생성자 및 다중 구독자입니다. 주제에는 이벤트를 작성하는 0개, 1개 또는 많은 생성자와 이러한 이벤트를 구독하는 0개, 1개 또는 많은 소비자가 있을 수 있습니다. 주제의 이벤트는 필요한 만큼 자주 읽을 수 있습니다. 기존 메시징 시스템과 달리 이벤트는 소비 후 삭제되지 않습니다. 대신 주제별 구성 설정을 통해 Kafka가 이벤트를 유지해야 하는 기간을 정의할 수 있고, 이보다 오래된 이벤트가 삭제됩니다.
Kafka의 성능은 데이터 크기와 관련하여 사실상 일정하므로 데이터를 장기간 저장하는 것이 좋습니다.
주제는 분할(partitioned)되어 있으며, 이는 다른 Kafka 브로커에 있는 여러 "버킷(buckets)"에 분산되어 있음을 의미합니다.
데이터의 분산 배치는 클라이언트 애플리케이션이 동시에 많은 브로커에서 데이터를 읽고 쓸 수 있도록 하기 때문에 확장성에 매우 중요합니다. 새 이벤트가 주제에 게시되면 실제로 해당 주제의 파티션 중 하나에 추가됩니다.
동일한 이벤트 키(예: 고객 또는 차량 ID)가 있는 이벤트는 동일한 파티션에 기록되고 Kafka는 지정된 파티션의 모든 소비자가 항상 기록된 것과 정확히 동일한 순서로 해당 파티션의 이벤트를 읽도록 보장합니다.
Figure:
이 예제 주제에는 4개의 파티션 P1~P4가 있습니다. 두 개의 서로 다른 생산자가 네트워크를 통해 서로 독립적으로 새 이벤트를 주제에 게시하고 있습니다. 동일한 키를 사용하는 이벤트(그림에서 색상으로 표시)는 동일한 파티션에 기록됩니다. 두 생산자 모두 동일한 파티션에 쓸 수도 있습니다.
데이터 내결함성 및 고가용성을 만들기 위해 모든 주제를 여러 지리적 지역이나 데이터 센터에 걸쳐 복제할 수 있습니다. 일이 잘못될 경우에 대비하여 데이터 복사본이 있는 여러 브로커가 있도록 합니다. 일반적인 프로덕션 설정은 복제 3팩터입니다. 즉, 항상 3개의 데이터 복사본이 있습니다. 이 복제는 주제 파티션 수준에서 수행됩니다.
We build for multiple versions of Scala
: 여러 버전의 Scala로 빌드되었다. 즉 Kafka는 Scala로 만들었다.
What is Scala?
스칼라는 함수형 객체지향 프로그래밍 언어 입니다. 스칼라는 자바의 복잡한 단점을 해결하기 위해 만들어 졌습니다. 스칼라는 자바 바이트 코드를 사용하기 때문에 JVM위에서 실행 시킬 수 있습니다. 또한 자바의 클래스들을 바로 사용할 수도 있고, 자바에서도 스칼라 코드들을 호출할 수 있습니다.
설치한 프로그램을 실행하거나 압축해제한 DB Browser for SQLite 실행파일을 수행하면 아래와 같은 화면이 나타난다.
우측 하단에 UTF-8 문자셋이 보인다. 기본적으로 문자를 UTF-8로 처리한다.
DB Browser
3. DB를 생성거나 기존 DB 열기
DB 생성 :
[새 데이터베이스(N)] 메뉴를 클릭하고 저장하고자 하는 폴더 위치와 파일명을 입력한다.
신규 DB 생성화면
그 다음에 테이블명을 입력하고, 필드명을 추가하여 신규 DB와 테이블을 생성한다.
table 생성 화면
[데이터 보기] 탭을 클릭한 후, 데이터를 입력해 본다.
기존 DB 열기
기존에 생성된 데이터베이스를 선택하여 DB를 오픈한다.
4. Table과 Field 생성
[편집] - [테이블생성] 메뉴를 클릭한 후 '테이블 정의 변경' 화면이 나오면 테이블명에 emp 를 입력하고, id(integer, PK, AI), name(text, NN), birth(text, NN), pic(blob) 필드를 추가하고 id는 primary key와 auto increment(AI)로 지정한다.
data 타입은 integer, text, blob, real, numeric이 지원된다.
Not null, Primary key. Auto Increment, Unique 제약 조건 및 default, check, collcation, FK 등도 지원된다.
5. 새 레코드 추가/삭제
[데이터 보기] 탭을 클릭한 후 새 레코드를 입력히거나 기준 레코드를 삭제할 수 있다.Oracle DB와는 다르게 Not Null 컬럼으로 지정한 컬럼에 아무 데이터도 입력하지 않았는데, 오류가 발생하지 않고 데이터가 저장되었다. 오라클을 제외한 일반 DB(mysql, mariaDB, MS Sql, informix 등)에서 처리하는 empty string이나 zero-byte string으로 처리한다.
6. SQL 문은 일반 DBMS 사용법과 같다.
단, 데이터가 아무것도 없는 경우에는 empty string 으로 처리하고, 명시적으로 null을 입력할 경우에는 null로 처리한다.
*** 참고 ***
원격 DB 접속은 원천적으로 안된다. 서버리스 DB이므로 접속을 할 수 있는 데몬이나 리스너가 없다.
The easiest is probably to share the directory where the squeezecenter.db file is stored. I'm not sure if you'll get into trouble if you modify the squeezecenter.db while SqueezeCenter is connected to it, to be safe it's probably a good idea to shutdown SqueezeCenter before you do any modifications.
If you just want to be able to run a SQL statement from a remote machine, you can always try toe Database Query plugin. It's only available as a beta version for SQLite yet, see this thread for more information: http://forums.slimdevices.com/showthread.php?t=65439