'2016/08'에 해당되는 글 15건

  1. 2016.08.12 OSPF 쉽게 이해하기 (2편: External Network 라우팅 정보 가져오기)
  2. 2016.08.12 OSPF 쉽게 이해하기 (1편: Shortest Path Tree 토폴로지 생성 절차)
  3. 2016.08.12 스위칭과 라우팅... 참 쉽죠잉~ (2편: IP 라우팅)
  4. 2016.08.12 스위칭과 라우팅... 참 쉽죠잉~ (1편: Ethernet 스위칭)
  5. 2016.08.05 자바 JVM 정리(Java Virtual Machine)
  6. 2016.08.05 GC
  7. 2016.08.04 MySQL Cluster
  8. 2016.08.04 스케일 아웃 측면에서 살펴본 MySQL의 특성
  9. 2016.08.04 In Memory Data Grid
  10. 2016.08.04 Do You Really Get Classloaders?

OSPF 쉽게 이해하기 (2편: External Network 라우팅 정보 가져오기)

Network/Network 2016. 8. 12. 12:47

지난 시간에는 OSPF 망에서 Router-LSA를 통해 각 라우터가 Network Topology Map을 만들고 Link Cost 기반으로 Shortest Path Tree를 구성하는 절차에 대해 설명을 드렸습니다.

오늘은 위의 과정을 통해 생성된 OSPF Topology에 External Network이 연결되는 경우, 어떻게 OSPF 라우터들은 External Network의 라우팅 정보를 배우고, 그 Network으로 가는 Shortest Path를 알게 되는지 그 과정을 살펴 보도록 하겠습니다.

 

OSPF External Network

 


 

■ OSPF 관점에서 External Network이란?

External Network이란 OSPF로 구성된 하나의 네트워크(AS 혹은 Routing Domain이라 부름)과 연결된 "외부 네트워크"를 말합니다. 즉, OSPF가 enable된 라우터간에는 Router-LSA(지난 시간에 설명), Network-LSA등으로 서로간에 라우팅 정보를 주고 받게 되고, OSPF가 enable되지 않은 망의 라우팅 정보는 External Network으로 분류되어 AS-External-LSA를 통해 External Network의 라우팅 정보를 OSPF 망에서 알 수 있게 됩니다. External Network의 예는 아래와 같습니다.

  • BGP 망의 라우팅 정보
  • IS-IS 망의 라우팅 정보
  • Static route로 생성된 라우팅 엔트리 정보
  • 라우터와 바로 직결된 Connected Network이지만 이 링크는 OSPF가 enable되지 않은 경우
이와 같이 External Network과 연결된 OSPF 라우터를 ASBR(Autonomous System Border Router)이라 부릅니다.

 

■ AS와 Routing Domain

보통 통신사업자는 망 내부 전체의 Intra-domain Routing 프로토콜로 OSPF나 IS-IS를 선택하여 운영하게 되는데, 이와 같이 동일 IGP 프로토콜로 운영되는 하나의 망을 AS 혹은 Routing Domain이라 부릅니다.

아래 내용에 따르면 AS 보다는 Routing Domain이란 표현이 더 일반적인 듯 합니다.

 

The IETF concept of autonomous system (AS) is, in ISO terms, a routing domain. I much prefer the second term. These days, an AS has a specific meaning in BGP networks, to differentiate one area of autonomous administrative control from another, and as entries interconnected by EBGP. Whthin a single AS, multiple IGPs can be running. In contrast, a routing domain is always the scope of a single set of routers speaking the same routing protocol to each other, unbroken by any other routing protocol

출처: Jeff Doyle, OSPF and IS-IS: Choosing an IGP for Large-Scale Networks, 2005, Addison-Wesley

 

 

OSPF Network Topology

 


 

그림 상에 5개의 OSPF 라우터(R1 ~ R5)가 존재하고, 라우터간 연결 링크에 대한 IP 주소와 OSPF Link Cost 및 각 라우터의 OSPF Router ID(RID)인 Loopback 주소(예. R1의 경우 10.1.0.1/32)가 표시되어 있습니다.

  • 각 라우터간 파란색 링크가 OSPF가 enable되어 있음을 표시하고 있고,
  • 회색 링크는 OSPF가 enable되어 있지 않음을 표시하고 있습니다.

즉, R1에 직결된(connected) 100.1.1.0/24는 External Network이고, R2에서 라우터(회색 라우터)를 거쳐 연결된(static route) 200.1.1.0/24도 External Network이 됩니다.

 

앞서 설명 드린바와 같이 External Network과 연결되는 OSPF 라우터를 "OSPF 망의 가장자리(Border)에 위치한 라우터"의 의미로 ASBR(Autonomous System Border Router)이라 부릅니다.

 

 

ASBR: External 라우팅 정보를 OSPF 내부 라우터들로 전파

 

1. R1이 External Network (Connected Network) 정보를 전파

 


 

R1의 설정(redistribute connected subnets)에 의해서 External Network 100.1.1.0/24 정보가 AS-External-LSA를 통해 R2, R3로 전파됩니다[t=1]. 그리고 이를 수신한 R2, R3는 본 AS-External-LSA가 수신된 핑크를 제외한 링크로 AS-External-LSA를 flooding 합니다. 그래서 R4, R5는 동일한 AS-External-LSA를 2개씩 수신하는데[t=2], 이 경우 LSA 식별자인 {LS Type, Link State ID, Advertising Router}가 동일한 경우 두번째 수신한 LSA를 폐기합니다.

  • LS Type: Router-LSA(1), Network-LSA(2), AS-External-LSA(5) 등의 LSA 타입을 구분
  • Link State ID: AS-External-LSA인 경우 External Network 주소의 Prefix (address prefix of the external route)
  • Advertising Router: AS-External-LSA를 생성한 라우터의 ID (R1 OSPF RID, 즉, R1의 Loopback 주소인 10.1.0.1)

 

R1이 보낸 AS-External-LSA에 포함된 정보는 다음과 같습니다.

  • Network Mask: External Network의 subnet mask (255.255.255.0)
  • Metric: External Network과 OSPF Network 사이의 Link Cost (35)

 

이와 같이 R1이 보낸 AS-External-LSA를 R2 ~ R5가 수신하게 되면 각 라우터는 그 정보를 OSPF LSDB(Link State DataBase)에 저장하고 OSPF Network Topology 상에 해당 External Network으로 가기 위한 Shortest Path Tree를 구성하게 됩니다 (맨 밑에 그림 참조).

 

2. R2가 External Network (Static Route) 정보를 전파

 


 

R2의 설정(200.1.1.0/24로 가기 위한 static route 및 redistribute static subnets)에 의해서 External Network 200.1.1.0/24 정보가 AS-External-LSA를 통해 R1, R4, R5로 전파됩니다[t=1]. 그리고 이를 수신한 R1, R4, R5는 본 AS-External-LSA가 수신된 링크를 제외한 링크로 AS-External-LSA를 flooding 합니다. 

 

R1, R3, R4, R5는 이 정보(AS-External-LSA)를 LSDB에 저장하고, OSPF Network Topology 상에 해당 External Network으로 가기 위한 Shortest Path Tree를 구성하게 됩니다 (맨 밑에 그림 참조).

 

역자 주: External Route를 OSPF 망으로 전파할때 2가지 옵션(External Type 1 & External Type 2) 중에 하나를 선택할 수 있습니다. 위 그림의 설정은 External Type 1(CLI 상에 metric-type 1)으로 예를 든 것입니다. 이 2가지 옵션에 대해서는 다음 기회에 설명을 드리도록 하겠습니다.

 

 

R1 ~ R5: Shortest Path Tree 구성하기

 


 

위에서 설명한 2개의 External Network(100.1.1.0/24, 200.1.1.0/24)에 대해 각 라우터는 최단 경로 즉, Shortest Path Tree를 구성하고, 이렇게 만들어진 Shortest Path 정보 즉, External Network Prefix와 최단경로로 가기 위한 Next Hop 정보가 라우터의 RIB(Routing Information Base)와 FIB(Forwarding Information Base)에 인스톨 됩니다. (예. R5는 External Network 200.1.1.0/24로 가기 위한 최단경로상의 Next Hop은 R2(1.1.5.1)이고, 100.1.1.0/24로 가기 위한 최단경로상의 Next Hop도 R2(1.1.5.1)임) 

 

* 아래 Comments에 추가 설명(박형규님/넷매니아즈 글) 참고하세요~


출처 - http://www.netmanias.com/ko/?m=view&id=blog&no=5478

:

OSPF 쉽게 이해하기 (1편: Shortest Path Tree 토폴로지 생성 절차)

Network/Network 2016. 8. 12. 12:46

지난 시간에 LTE over MPLS L3VPN 망을 위한 IP/MPLS 프로토콜을 설명 드리면서 "모든 IP 라우터는 OSPF나 IS-IS와 같은 IGP 프로토콜을 이용하여 IP 망 토폴로지 정보를 서로간에 주고 받고, Shotest Path Tree 토폴로지를 구성한다"라고 말씀을 드렸었는데요.

오늘은 OSPF 프로토콜을 통해 어떻게 라우터들이 OSPF 망(IP 망)의 전체 토폴로지를 알아내고, Shortest Path Tree를 구성하는지 살펴보도록 보겠습니다.

사실 OSPF와 같은 라우팅 프로토콜은 라우팅 비전문가들에게는 그 원리를 이해하기가 쉽지 않은 기술 분야입니다. Cisco나 Juniper 장비의 라우팅 설정(CLI)을 잘 하시는 분들은 많이 보았는데, 프로토콜 원리를 이해하고 계시는 분들은 그리 많지 않은 듯 합니다.

 

오늘 설명은 "라우팅 비전문가"도 쉽게 그 기술을 이해할 수 있도록 "그림"을 많이 넣어 보았습니다.

 

OSPF 네트워크 토폴로지

 


 

그림 상에 5개의 OSPF 라우터(R1 ~ R5)가 존재하고, 라우터간 연결 링크에 대한 IP 주소와 OSPF Cost 및 각 라우터의 Loopback 주소(예. R1의 경우 10.1.0.1)가 표시되어 있습니다. 그리고 파란색 줄(링크)가 OSPF가 enable되어 있음을 표시하고 있습니다.

  • OSPF에서 얘기하는 Cost란 각 링크로 패킷을 전달하는데 드는 "소요 비용"으로 OSPF는 Cost가 작은 경로를 최적의 경로(Shortest Path)로 인식합니다. 통상적으로 Link Cost는 링크 속도(bandwidth of a link)에 따라 그 값을 정의합니다. 그래서 예로 100Mbps 링크보다는 1GE 링크 Cost가 작을 것이고, 1GE 링크 보다는 10GE 링크가 Cost가 작을 것입니다. (Link Cost는 라우터의 각 Interface별로 운영자가 CLI를 통해 설정함)
  • 라우터간에 OSPF 프로토콜 메시지를 주고 받기 위해서는 각 라우터를 식별할 수 있는 IP 주소(OSPF RID(Router ID))가 필요한데 이를 위해 보통 Loopback 주소를 사용합니다. Physical Link의 IP 주소를 사용해도 상관은 없지만 다음과 같은 차이로 인해 Loopback 주소를 선호하지요.
    • Physical Link IP 주소 사용의 경우: 해당 Physical Link가 down 되는 경우 그 IP 주소가 사라짐. 즉, 이 주소를 OSPF RID로 사용한 OSPF 라우터는 더 이상 OSPF neighbor(나와 연결되어 있는 라우터)와 통신이 불가함
    • Loopback IP 주소 사용의 경우: Loopback 주소는 어떤 특정 Physical Link와 바인딩되어 있지 않은 Logical한 주소이기 때문에, Physical Link가 down되더라도 Loopback 주소는 계속 살아 있음
 

각 라우터는 자신의 링크 IP 주소를 다른 라우터들로 전파

 

1. R1이 자신의 링크 정보를 다른 OSPF 라우터들로 전파

 


 

R1은 자신의 Link(Interface) 주소와 Loopback 주소를 Router-LSA에 실어 R2, R3로 전달합니다[t = 1]. 그리고 이를 수신한 R2, R3는 Router-LSA가 수신된 링크를 제외한 나머지 링크로 Router-LSA를 flooding 합니다. 그래서 R4와 R5는 동일한 Router-LSA를 2개씩 수신합니다[t = 2]. 이 경우, LSA 식별자에 해당하는 {LS Type, Link State ID, Advertising Router}가 동일한 경우 두번째 수신한 LSA를 폐기합니다.

  • LS Type: Router-LSA (1), Network-LSA (2), External-LSA (5) 등의 타입을 구분
  • Link State ID: Router-LSA인 경우 Advertising Router와 동일 값 (10.1.0.1)
  • Advertising Router: Router-LSA를 생성한 라우터의 ID (OSPF RID 즉, Loopback 주소 = 10.1.0.1) 
R1이 보낸 Router-LSA에 포함되는 정보는 다음과 같습니다. (위 그림의 우측 상단을 보세요)
  • Link Type: 링크 타입을 가리키는 값으로 그 타입에 따라 Link ID와 Link Data에 들어가는 값이 달라짐
    • Link Type = 1: Point-to-point connection(그림상에서 라우터간 연결은 모두 여기에 해당)
    • Link Type = 3: Stub network(라우터의 loopback 주소)
  • Link ID: R1과 연결된 OSPF Neighbor의 Router ID(Link Type=1,  OSPF Neighbor간에 Hello 메시지를 주고 받는 과정에서 Neighbor의 RID를 알게 됨) 혹은 R1의 Loopback 주소(Link Type=3)
  • Link Data: R1의 Link IP 주소(Link Type=1) 혹은 R1의 Loopback 주소에 대한 subnet mask (/32 = 255.255.255.255)
  • Metric: 해당 Link의 cost(CLI로 각 링크의 cost는 설정함). Loopback 주소(stub network)인 경우 cost는 0
이와 같이 R1이 보낸 Router-LSA를 R2 ~ R5가 수신 하게 되면 각 라우터는 그 정보를 OSPF LSDB(Link State DataBase)에 저장하고 그 정보를 바탕으로 OSPF Topology를 그리게 됩니다. 현재까지의 정보로 R1 ~ R5 라우터가 알 수 있는 Topology는 다음과 같습니다.
  • R1의 Loopback 주소 (10.1.0.1/32)
  • R1의 Link 주소 1.1.1.1은 R2(10.1.0.2)와 연결되어 있음
  • R1의 Link 주소 1.1.2.1은 R3(10.1.0.3)과 연결되어 있음
 
2. R2가 자신의 링크 정보를 다른 OSPF 라우터들로 전파
 


 

R2는 자신의 Link(Interface) 주소와 Loopback 주소를 Router-LSA에 실어 R1, R4, R5로 전달하고[t = 1], 이를 수신한 R1, R4, R5는 Router-LSA가 수신된 링크를 제외한 나머지 링크로 Router-LSA를 flooding 합니다[t = 2]. 
 
R1, R3, R4, R5는 이 정보(Router-LSA)를 LSDB에 저장하고, 이제 위 그림과 같은 "OSPF Network Topology"를 알게 됩니다.
 
3. R3가 자신의 링크 정보를 다른 OSPF 라우터들로 전파
 


 

R3는 자신의 Link(Interface) 주소와 Loopback 주소를 Router-LSA에 실어 R1, R4, R5로 전달하고[t = 1], 이를 수신한 R1, R4, R5는 Router-LSA가 수신된 링크를 제외한 나머지 링크로 Router-LSA를 flooding 합니다[t = 2]. 
 
R1, R2, R4, R5는 이 정보(Router-LSA)를 LSDB에 저장하고, 이제 위 그림과 같은 "OSPF Network Topology"를 알게 됩니다.

 

4. R4가 자신의 링크 정보를 다른 OSPF 라우터들로 전파

 


 

R4는 자신의 Link(Interface) 주소와 Loopback 주소를 Router-LSA에 실어 R2, R3로 전달하고[t = 1], 이를 수신한 R2, R3는  Router-LSA가 수신된 링크를 제외한 나머지 링크로 Router-LSA를 flooding 합니다[t = 2]. 
 
R1, R2, R3, R5는 이 정보(Router-LSA)를 LSDB에 저장하고, 이제 위 그림과 같은 "OSPF Network Topology"를 알게 됩니다.
 

5. R5가 자신의 링크 정보를 다른 OSPF 라우터들로 전파

 


 

R5는 자신의 Link(Interface) 주소와 Loopback 주소를 Router-LSA에 실어 R2, R3로 전달하고[t = 1], 이를 수신한 R2, R3는  Router-LSA가 수신된 링크를 제외한 나머지 링크로 Router-LSA를 flooding 합니다[t = 2]. 
 
R1 ~ R4는 이 정보(Router-LSA)를 LSDB에 저장하고, 이제 위 그림과 같은 "OSPF Network Topology"를 알게 됩니다.

 

역자 주 1: 실제로는 모든 라우터가 동시 다발적으로 자신의 Router-LSA를 OSPF neighbor들로 flooding 하지만, 본 설명에서는 이해를 돕고자 각 라우터가 순차적으로 Router-LSA를 보낸다고 하였습니다.
역자 주 2: 라우터의 링크 타입을 point-to-point로 설정(CLI)해야 Router-LSA가 나가게 되고, 그렇지 않은 경우(예. broadcast 타입) Network-LSA가 나가게 됩니다. 라우터간 링크 연결은 point-to-point가 일반적이므로 초보자님들께서는 Router-LSA만 생각하세요~*

 

각 라우터에서 OSPF Topology 그림 그리기

 


 

5개의 라우터들간에 Router-LSA를 주고 받게 되면, 모든 OSPF 라우터는 동일한 LSDB를 가지게 됩니다.

그리고 이 LSDB를 통해 위 그림과 같이 각 라우터는 모두 동일한 그림의 OSPF Topology Map을 완성합니다.

 

Shortest Path Tree 구성하기

 


 

위에서 생성한 OSPF Topology를 기반으로 각 라우터는 목적지(Destination Network)로 가는 최단 경로 즉, Shortest Path Tree를 구성합니다.

그리고 이렇게 만들어진 Shortest Path 정보가 라우터의 RIB(Routing Information Base)와 FIB(Forwarding Information Base)에 인스톨 됩니다. (참고: RIB는 OSPF와 같은 라우팅 프로토콜이 돌고 있는 Control Plane에서 관리하는 라우팅 테이블이고, FIB는 패킷을  포워딩(wire-speed packet forwarding by packet processor)하는 Data Plane에 위치한 라우팅 테이블입니다.)

 

OSPF에 대해 좀 더 자세히 알고 싶으신 분들을 위해 2권의 책을 추천드립니다.

  • John T. Moy, "OSPF: Anatomy of an Internet Routing Protocol", 1998, Addison-Wesley
    • OSPF 창시자의 저서이고, 프로토콜 규격에 충실
  • Jeff Doyle, "OSPF and IS-IS: Choosing an IGP for Large-Scale Networks", 2005, Addison-Wesley
    • OSPF와 IS-IS를 비교하였고, 또한 프로토콜 규격의 설명과 Cisco/Juniper 장비 설정도 함께 다루고 있음 (추천!)

출처 - http://www.netmanias.com/ko/post/blog/5476/ip-routing-network-protocol-ospf-shortest-path-tree/ospf-basic-part-1-build-of-shortest-path-tree-topology

:

스위칭과 라우팅... 참 쉽죠잉~ (2편: IP 라우팅)

Network/Network 2016. 8. 12. 12:45

지난 시간에 이어 오늘 설명 드릴 내용은 아래 그림 우측 IP Routing입니다.

예전에 IP 분야 경력자 면접을 볼 때 우측 그림상에서 패킷 흐름/테이블 변화(아래 설명할 내용)를 화이트보드에 한번 그려 보라 한 적이 있는데요. 웃는 얼굴로 설명을 시작했지만 끝은 별로 좋지 않았다는...

 


 

지난 시간과 마찬가지로 망 구성도를 잘 봐 주시기 바랍니다. MAC/IP 값은 아래 테이블과 같습니다. 

 

 Server/Router Port  MAC 주소 IP 주소
 SVR1 lan1 m1 1.1.1.10
 SVR3 lan1 m3 2.1.1.30

 R1 

 

 ge1/1 a1 1.1.1.1
 ge2/1 a2 2.1.1.1

 

 

IP Routing

 


 

1. SVR1 sends ARP Request

  • IP 주소 1.1.1.10인 SVR1이 목적지 주소 2.1.1.30인 SVR3로 패킷을 전송하려 합니다.
  • SVR1은 목적지 주소 2.1.1.30에 대해 자신의 Routing Table을 참조(lookup)하고, 그 결과 default route(0.0.0.0/0)에 매칭되어 "목적지로 가기 위해서는 Gateway는 1.1.1.1이고 출력 포트(OIF: Outgoing Interface)는 lan1"임을 알게 되었습니다. 보통 일반 PC의 경우 DHCP를 통해 IP 주소를 할당(임대) 받으면서 DHCP Option 3을 통해 Gateway 주소를 받아오고, 서버의 경우 운영자가 직접 Gateway 주소를 설정 합니다. 그러면 그 주소가 Routing Table에 인스톨 됩니다.
  • Gateway(Default Gateway라고도 함)란 SVR1과 연결된(중간에 L2 스위치가 여러개 있던 없던 간에) 첫번째 라우터를 의미하며 이 Gateway는 나(SVR1)와 동일 네트워크에 존재합니다. (그림상에서 SVR1(1.1.1.10)과 연결된 첫번째 라우터 R1의 인터페이스 주소 1.1.1.1이 Gateway가 됨)
  • SVR1은 Gateway 주소 1.1.1.1에 대한 MAC 주소가 ARP Table에 없어(ARP Miss) ARP Request 패킷을 lan1 포트로 내보내며 패킷 구성은 아래와 같습니다.
  Header     Fields         
 

 Ethernet Header  

 

 

 * Destination MAC = FF:FF:FF:FF:FF:FF(브로드캐스팅, 동일 LAN에 있는 모든 노드로 전달)
 * Source MAC = Sender(SVR1)의 MAC 주소 m1
 

 ARP Header   

 

 

 

 * Sender MAC = ARP Request 패킷 송신자(sender), 즉 SVR1의 MAC 주소 m1
 * Sender IP = ARP Request 패킷 송신자(sender), 즉 SVR1의 IP 주소 1.1.1.10
 * Target MAC = 00:00:00:00:00:00임 (SVR1은 이 값을 알고 싶어 하는 것임)
 * Target IP = ARP Request 패킷 수신자(target), 즉 R1의 IP 주소 1.1.1.1
  • 이제 이 패킷을 수신한 S1(스위치 1)은 Source MAC Learning을 수행(MAC 주소 m1은 fe1 포트에 연결되어 있음을 MAC Table에 저장)하고,
  • 수신 패킷의 Destination MAC 주소를 참조하여 출력 포트를 정하게 되는데 이 경우는 브로드캐스팅 주소(FF:FF:FF:FF:FF:FF)입니다. 따라서 S1은 수신 포트를 제외한 나머지 포트로 Flooding 합니다. 따라서 이 패킷은 SVR2와 R1(라우터 1)이 수신합니다.
  • SVR2는 수신된 ARP Request 패킷의 Target IP 주소가 자신의 것이 아님을 확인 후 버립니다.

 

2. R1 responds with ARP Reply

  • ARP Request를 수신한 R1(라우터 1)은 Target IP 주소를 보고 자신의 MAC 주소를 물어 본 것임을 압니다. 따라서 R1은 1.1.1.1에 대한 MAC 주소를 Sender MAC 필드에 담아 ARP Reply 패킷을 ge1/1 포트로 내보내며, 그 패킷의 구성은 아래와 같습니다.
  Header     Fields         
 

 Ethernet Header   

 

 * Destination MAC = ARP Reply를 수신할 SVR1의 MAC 주소 m1
 *
 Source MAC = Sender(R1)의 MAC 주소 a1
 

 ARP Header   

 

 

 

 * Sender MAC = ARP Reply 패킷 송신자(sender), 즉 R1의 MAC 주소 a1
 * Sender IP = ARP Reply 패킷 송신자(sender), 즉 R1의 IP 주소 1.1.1.1
 * Target MAC = ARP Reply 패킷 수신자(target), 즉 SVR1의 MAC 주소 m1
 * Target IP = ARP Reply 패킷 수신자(target), 즉 SVR1의 IP 주소 1.1.1.10
  • 이 패킷을 수신한 S1은 Source MAC Learning을 수행(MAC 주소 a1은 fe3 포트에 연결되어 있음을 MAC Table에 저장)하고,
  • 수신 패킷의 Destination MAC 주소 m1에 대한 MAC Table을 참조하여 해당 패킷을 fe1 포트로 패킷을 전달(유니캐스팅)합니다.
  • 그리고 이 패킷을 수신한 SVR1은 자신의 ARP Table에 그 값(1.1.1.1의 MAC 주소 a1)을 저장합니다.

 

3. SVR1 sends IP Packet to R1

  • 이제 SVR1은 SVR3로 IP 패킷을 보낼 준비가 되었습니다. SVR1은 아래와 같이 패킷을 구성하여 lan1 포트로 내보냅니다.
  Header     Fields         
 

 Ethernet Header

  

 * Destination MAC = Receiver(R1)의 MAC 주소 a1
 * Source MAC = Sender(SVR1)의 MAC 주소 m1
 

 IP Header   

 

 * Destination IP = Receiver(SVR3)의 IP 주소 2.1.1.30
 * Source IP = Sender(SVR1)의 IP 주소 1.1.1.10
  • 이 패킷을 수신한 S1은 이미 Learning된 Source MAC 주소이므로 Source MAC Learning 과정은 생략하고, Destination MAC 주소 a1에 대한 MAC Table 참조를 통해 fe3 포트로 패킷을 보냅니다.

 

4. R1 sends ARP Request

  • 패킷을 수신한 R1(라우터 1)은 자신의 FIB(Routing Table)를 참조하여 "목적지 주소 2.1.1.30은 나와 바로 붙어 있는 네트워크이고(Next Hop이 없으므로) 출력 포트는 ge2/1"라는 사실을 알게 되고,
  • 이제 R1은 2.1.1.30에 대한 MAC 주소를 알기 위해 ARP Table을 참조합니다. 하지만 해당 엔트리가 없습니다(ARP Miss). 따라서 R1은 아래와 같이 ARP Request 패킷을 ge2/1 포트로 내보냅니다.
  Header     Fields         
 

 Ethernet Header   

 

 

 * Destination MAC = FF:FF:FF:FF:FF:FF(브로드캐스팅, 동일 LAN에 있는 모든 노드로 전달)
 * Source MAC = Sender(R1)의 MAC 주소 a2
 

 ARP Header   

 

 

 

 * Sender MAC = ARP Request 패킷 송신자(sender), 즉 R1의 MAC 주소 a2
 * Sender IP = ARP Request 패킷 송신자(sender), 즉 R1의 IP 주소 2.1.1.1
 * Target MAC = 00:00:00:00:00:00임 (R1은 이 값을 알고 싶어 하는 것임)
 * Target IP = ARP Request 패킷 수신자(target), 즉 SVR3의 IP 주소 2.1.1.30
  • 이 패킷을 수신한 S2(스위치 2)는 Source MAC Learning을 수행(MAC 주소 a2는 fe3 포트에 연결되어 있음을 MAC Table에 저장)하고,
  • 수신 패킷의 Destination MAC 주소를 참조하여 출력 포트를 결정하는데 이 경우는 브로드캐스팅 주소(FF:FF:FF:FF:FF:FF)입니다. 따라서 S2는 수신 포트를 제외한 나머지 포트로 Flooding 합니다. 따라서 이 패킷은 SVR3과 SVR4가 수신합니다.
  • SVR4는 수신된 ARP Request 패킷의 Target IP 주소가 자신의 것이 아니므로 버립니다.

 

5. SVR3 responds with ARP Reply

  • ARP Request를 수신한 SVR3은 Target IP 주소를 보고 자신의 것임을 압니다. 따라서 SVR3은 2.1.1.30에 대한 MAC 주소를 Sender MAC 필드에 담아 ARP Reply 패킷을 lan1 포트로 내보내며, 그 패킷의 구성은 아래와 같습니다.
  Header     Fields         
 

 Ethernet Header

  

 * Destination MAC = ARP Reply를 수신할 R1의 MAC 주소 a2
 * Source MAC = Sender(SVR3)의 MAC 주소 m3
 

 ARP Header   

 

 

 

 * Sender MAC = ARP Reply 패킷 송신자(sender), 즉 SVR3의 MAC 주소 m3
 * Sender IP = ARP Reply 패킷 송신자(sender), 즉 SVR3의 IP 주소 2.1.1.30
 * Target MAC = ARP Reply 패킷 수신자(target), 즉 R1의 MAC 주소 a2
 * Target IP = ARP Reply 패킷 수신자(target), 즉 R1의 IP 주소 2.1.1.1
  • 이 패킷을 수신한 S2는 Source MAC Learning을 수행(MAC 주소 m3는 fe1 포트에 연결되어 있음을 MAC Table에 저장)하고,
  • 수신 패킷의 Destination MAC 주소 a2에 대한 MAC Table을 참조하여 해당 패킷을 fe3 포트로 패킷을 전달(유니캐스팅)합니다.
  • 그리고 이 패킷을 수신한 R1은 자신의 ARP Table에 그 값(2.1.1.30의 MAC 주소 m3)을 저장합니다.

 

6. R1 sends IP Packet to SVR3

  • SVR3의 MAC 주소를 알았으므로, 이제 R1(라우터 1)은 SVR1에서 SVR3로 향하는 패킷을 IP 라우팅 할 수 있습니다. R1은 아래와 같은 구성으로 SVR1이 보낸 패킷을 SVR3로 라우팅 시켜 줍니다.
  Header     Fields         
 

 Ethernet Header   

 

 * Destination MAC = Receiver(SVR3)의 MAC 주소 m3
 * Source MAC = Sender(R1)의 MAC 주소 a2
 

 IP Header   

 

 * Destination IP = Receiver(SVR3)의 IP 주소 2.1.1.30
 * Source IP = Sender(SVR1)의 IP 주소 1.1.1.10
  • 이 패킷을 수신한 S2(스위치 2)는 이미 Learning된 Source MAC 주소이므로 Source MAC Learning 과정은 건너뛰고, Destination MAC 주소 m3에 대한 MAC Table 참조를 통해 fe1 포트로 패킷을 전송하여 SVR3가 패킷을 수신합니다.
 

정리

 

모든 단말/서버(이하 서버로 부름)는 스위치와 라우터를 통해 다른 서버와 연결되어 있습니다.
 
서버에서 보낸 패킷이 Ethernet Switching 될 것이냐 IP Routing 될 것이냐는 결정은 패킷을 송신하는 서버에서 이미 결정이 됩니다.
 
지난 시간에 설명드린 바와 같이 패킷 송신 서버는 목적지 주소(1.1.1.20)가 나(1.1.1.10)와 동일 네트워크에 존재하면 해당 목적지 단말의 MAC 주소를 Destination MAC으로 하여 패킷을 전달하고 이 패킷은 스위치를 통해 Ethernet Switching 되어 수신 서버로 전달됩니다.
 
반면 오늘 설명과 같이 목적지 주소(2.1.1.30)가 나(1.1.1.10)와 다른 네트워크에 존재하는 경우 해당 목적지가 아닌 Gateway (1.1.1.1)의 MAC 주소를 Destination MAC으로 하여 패킷을 전달하는데, 이 때의 Gateway는 서버와 연결된 첫번째 L3 Hop, 즉 라우터(R1) 입니다. 따라서 이 패킷은 목적지 주소가 라우터 MAC 이므로 중간에 스위치가 있어도 Ethernet Switching 되어 라우터로 도착할 것이고, 라우터는 수신 패킷의 Destination MAC이 자신의 것임을 확인 한 후에 FIB lookup을 하여 IP Routing(혹은 Forwarding이라 부름) 하게 됩니다. 
 
방금 중요한 포인트를 말씀드렸습니다.
"라우터는 수신 패킷의 Destination MAC 주소가 내 MAC이면 라우팅, 아니면 폐기합니다." 
단, Destination MAC 주소가 FF:FF:FF:FF:FF:FF인 경우는 일단 라우터의 Control Plane이 받아 봅니다. 위에서 R1이 ARP Request 패킷을 수신하여 처리한 것과 같이요.


출처 - http://www.netmanias.com/ko/post/blog/5502/arp-bridging-ip-routing-network-protocol/switching-and-routing-part-2-ip-routing

:

스위칭과 라우팅... 참 쉽죠잉~ (1편: Ethernet 스위칭)

Network/Network 2016. 8. 12. 12:42

제목이 좀 유치하죠? ^^* 말랑 말랑한 블로그 공간에서의 표현이므로 너그럽게 봐 주시기 바랍니다.

 

오늘과 내일에 걸쳐 L2(Ethernet) 스위칭과 L3(IP) 라우팅 과정에서 살펴 보도록 하겠습니다. 본 글을 통해 다음과 같은 내용을 설명 드리도록 하겠습니다.

  • ARP와 IP 패킷
  • 스위칭/라우팅 과정에서 Ethernet Header의 변화
  • 스위칭/라우팅 과정 전후로 단말과 스위치, 라우터의 테이블(Routing, ARP, MAC Table) 엔트리 변화

 

Switching과 Routing

 


 

위 그림은 앞으로(오늘과 내일) 설명드릴 망 구성도이므로 잘 봐 주시기 바랍니다. (특히 서버/라우터의 MAC, IP 주소, 스위치/라우터의 포트(인터페이스) 번호)

 

좌측 그림과 같이 Sender(SVR1)와 Receiver(SVR2)가 동일 네트워크(LAN)에 위치해 있는 경우 라우터 R1을 거치지 않고 스위치 S1을 통해 바로 통신이 되며 이 때의 패킷 구성은 다음과 같습니다. (동일 네트워크인지 아닌지 어떻게 구분하는지 궁금하시면 여기를 클릭)

 Header Fields     

 Ethernet Header

 

 * Destination MAC = Receiver(SVR2)의 MAC 주소 m2
 * Source MAC = Sender(SVR1)의 MAC 주소 m1

 IP Header

 

 * Destination IP = Receiver(SVR2)의 IP 주소 1.1.1.20
 * Source IP = Sender(SVR1)의 IP 주소 1.1.1.10

 

반면 우측 그림과 같이 Sender(SVR1)와 Receiver(SVR3)가 동일 네트워크(LAN)에 위치하지 않은 경우 라우터 R1을 거치게 되는데 이 때의 Ethernet Header 필드는 라우터를 사이에 두고 서로 값을 가지게 됩니다.

 

SVR1에서 R1으로 패킷 전송시

 Header Fields     

 Ethernet Header

 

 * Destination MAC = Router(R1의 ge1/1)의 MAC 주소 a1
 * Source MAC = Sender(SVR1)의 MAC 주소 m1

 IP Header

 

 * Destination IP = Receiver(SVR3)의 IP 주소 2.1.1.30
 * Source IP = Sender(SVR1)의 IP 주소 1.1.1.10

 

R1에서 SVR3로 패킷 전송시

 Header Fields     

 Ethernet Header

 

 * Destination MAC = Receiver(SVR3)의 MAC 주소 m3
 * Source MAC = Router(R1의 ge2/1)의 MAC 주소 a2

 IP Header

 

 * Destination IP = Receiver(SVR3)의 IP 주소 2.1.1.30
 * Source IP = Sender(SVR1)의 IP 주소 1.1.1.10

 

 

Ethernet Switching

 


 

그림을 그리다 보니 너무 길쭉해 졌습니다. (다음 시간 그림은 더 길어요~)

 

1. SVR1 sends ARP Request

  • IP 주소 1.1.1.10을 가진 SVR1이 목적지 주소 1.1.1.20인 SVR2로 패킷을 전송하려 합니다.
  • 서버든 라우터든 패킷을 보내기 위해서는 일단 Routing Table을 참조합니다. Routing Table Lookup 결과 목적지 주소는 나(SVR1)와 동일 네트워크에 존재하고(라우팅 엔트리 1.1.1.0/24에 Gateway가 없음이 나와 동일 네트워크임을 나타냄), 출력 포트(OIF: Outgoing Interface)는 lan1입니다(그림에서 서버의 포트는 하나만 그렸으므로 다 lan1이죠).
  • 이제 SVR1은 목적지 주소 1.1.1.20에 대한 MAC 주소를 알기 위해 자신의 ARP Table을 참조합니다. 그런데 테이블이 비어 있습니다. (해당 엔트리가 없으면 ARP Miss라 부름)
  • 따라서 SVR1은 SVR2(1.1.1.20)의 MAC 주소를 알아내기 위해 lan1 포트로 ARP Request를 보냅니다. ARP Request 패킷은 아래와 같이 구성됩니다. 
  Header     Fields         
 

 Ethernet Header  

 

 

 * Destination MAC = FF:FF:FF:FF:FF:FF(브로드캐스팅, 동일 LAN에 있는 모든 단말로 전달)
 * Source MAC = Sender(SVR1)의 MAC 주소 m1
 

 ARP Header  

 

 

 

 * Sender MAC = ARP Request 패킷 송신자(sender), 즉 SVR1의 MAC 주소 m1
 * Sender IP = ARP Request 패킷 송신자(sender), 즉 SVR1의 IP 주소 1.1.1.10
 * Target MAC = 00:00:00:00:00:00임 (SVR1은 이 값을 알고 싶어 하는 것임)
 * Target IP = ARP Request 패킷 수신자(target), 즉 SVR2의 IP 주소 1.1.1.20
  • 이제 이 패킷은 S1(스위치 1)이 수신하고, 수신 패킷(스위치는 수신 패킷이 IP 패킷인지 ARP 패킷인지 관심 없음)의 Source MAC 주소를 배웁니다. 따라서 S1의 MAC Table에는 {MAC 주소 m1은 fe1 포트에 연결되어 있음}이 기록됩니다.
  • Source MAC Learning 직후 S1은 수신 패킷의 Destination MAC 주소를 봅니다. 브로드캐스팅 주소네요. 따라서 S1은 수신 포트를 제외한 나머지 모든 포트로(VLAN 설정이 있다면 동일 VLAN에 속한 모든 포트로) Flooding 합니다. 그래서 이 ARP Request 패킷은 SVR2와 라우터 R1이 수신을 합니다.
  • R1은 수신된 ARP Request 패킷의 Target IP 주소를 보고 이 주소가 내 것이 아님을 알고(R1이 소유한 주소는 1.1.1.1과 2.1.1.1) 버립니다.

 

2. SVR2 responds with ARP Reply

  • ARP Request를 수신한 SVR2도 Target IP 주소를 봅니다. 내 주소네요. 따라서 SVR2는 1.1.1.20에 대한 MAC 주소를 Sender MAC 필드에 담아 ARP Reply 패킷을  lan1 포트로 내보냅니다. ARP Reply 패킷은 아래와 같이 구성됩니다.
  Header     Fields         
 

 Ethernet Header  

 

 * Destination MAC = ARP Reply를 수신할 SVR1의 MAC 주소 m1
 * Source MAC = Sender(SVR2)의 MAC 주소 m2
 

 ARP Header   

 

 

 

 * Sender MAC = ARP Reply 패킷 송신자(sender), 즉 SVR2의 MAC 주소 m2
 * Sender IP = ARP Reply 패킷 송신자(sender), 즉 SVR2의 IP 주소 1.1.1.20
 * Target MAC = ARP Reply 패킷 수신자(target), 즉 SVR1의 MAC 주소 m1
 * Target IP = ARP Reply 패킷 수신자(target), 즉 SVR1의 IP 주소 1.1.1.10
  • 이 패킷을 수신한 S1은 Source MAC Learning을 하여 MAC Table에 {MAC 주소 m2는 fe2 포트에 연결되어 있음}를 기록하고,
  • 수신 패킷의 Destination MAC 주소 m1에 대해 MAC Table을 참조하여 fe1 포트로 패킷을 전달(유니캐스팅)합니다.
  • 그리고 이를 수신한 SVR1은 자신의 ARP Table에 그 값(1.1.1.20의 MAC 주소 m2)을 기록합니다.

 

3. SVR1 sends IP Packet to SVR2

  • 이제 SVR1은 SVR2로 IP 패킷을 보낼 준비가 되었습니다. 따라서 SVR1은 아래와 같은 구성의 IP 패킷을 lan1 포트로 내보냅니다.
  Header     Fields         
 

 Ethernet Header  

 

 * Destination MAC = Receiver(SVR2)의 MAC 주소 m2
 * Source MAC = Sender(SVR1)의 MAC 주소 m1
 

 IP Header   

 

 * Destination IP = Receiver(SVR2)의 IP 주소 1.1.1.20
 * Source IP = Sender(SVR1)의 IP 주소 1.1.1.10
  • 이 패킷을 수신한 S1(스위치 1)은 Source MAC Learning을 하려 봤더니 Source MAC 주소 m1은 이미 배운 MAC 입니다. 따라서 MAC Learning은 필요 없구요. Destination MAC 주소 m2를 MAC Table에서 찾아 보았더니 fe2 포트로 내보내면 된다고 적혀 있습니다.
  • 따라서 이 패킷은 fe2 포트를 통해 나가고, SVR2가 수신 합니다.

출처 - http://www.netmanias.com/ko/post/blog/5501/arp-bridging-ip-routing-network-protocol/switching-and-routing-part-1-ethernet-switching

:

자바 JVM 정리(Java Virtual Machine)

Language/JAVA 2016. 8. 5. 14:50

자바 JVM 정리(Java Virtual Machine)

Java2015-08-09 

Java 언어는 기본적으로 JVM(Java Virtual Machine) 위에서 실행되도록 고안된 언어입니다. 이번엔 JVM의 구조를 살펴보고 하나씩 점검해 보는 포스팅입니다.

1. Java Virtual Machine

A Java virtual machine (JVM) is an abstract computing machine. There are three notions of the JVM: specification, implementation, and instance. The specification is a book that formally describes what is required of a JVM implementation. Having a single specification ensures all implementations are interoperable. A JVM implementation is a computer program that meets the requirements of the JVM specification in a compliant and preferably performant manner. An instance of the JVM is a process that executes a computer program compiled into Java bytecode.

Wikipedia - Java virtual machine

위키피디아에서 소개된 JVM에 대한 설명중 일부입니다. 간략하게 풀어보자면,

JVM이란 추상적인 컴퓨팅 머신입니다. 그리고 JVM에는 3가지 개념이 있습니다. 이것은 명세(스펙), 구현, 그리고 인스턴스입니다. 명세는 책입니다. JVM 구현에 무엇이 요구되는지 공식적으로 설명 되어 있습니다. 하나의 명세를 가지는 것은 모든 구현의 상호 운영을 보장합니다. JVM 구현은 JVM 명세의 요구에 맞춘 컴퓨터 프로그램입니다. JVM의 인스턴스는 자바 바이트코드로 컴파일된 컴퓨터 프로그램을 실행하는 프로세스입니다.

2. JVM Diagram

실제로 JVM의 구조는 어떻게 되었는지 다이어그램으로 확인해 봅시다.

                    ╋━━━━━━╋
class files ------▶┃Class Loader┃
                    ╋━━━━━━╋
                           ↕
╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋
┃JVM Memory(Runtime Data Areas)                                                              ┃
┃╋━━━━━━╋ ╋━━╋ ╋━━━━━━━━━━╋ ╋━━━━━━╋ ╋━━━━━━━━━━╋┃
┃┃Method Area ┃ ┃Heap┃ ┃JVM Language Stacks ┃ ┃PC Registers┃ ┃Native Method Stacks┃┃
┃╋━━━━━━╋ ╋━━╋ ╋━━━━━━━━━━╋ ╋━━━━━━╋ ╋━━━━━━━━━━╋┃
╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋
         ↕                            ↕
╋━━━━━━━━╋    ╋━━━━━━━━━━━━╋    ╋━━━━━━━━━━━━╋
┃Execution Engine┃ ↔ ┃Native Method Interface ┃ ↔ ┃Native Method Libraries ┃
╋━━━━━━━━╋    ╋━━━━━━━━━━━━╋    ╋━━━━━━━━━━━━╋

다이어그램상으로 위에서 아래로 내려가는 과정을 수행한다고 보면 됩니다. class 파일의 정보를 Class Loader를 사용해 JVM Memory 공간으로 옮기고 이것을 Execution Engine으로 실행하는 구조입니다.

그리고 새로운 단어들이 많이 등장합니다. 하나씩 살펴봅시다.

3. Class Loader

Class Loader(이하 "클래스 로더")는 클래스 파일 포맷(.class)을 준수하는 어떠한 것이라도 인지하고 적재할 수 있도록 구현해야 합니다. 그리고 런타임(Runtime)시에 클래스를 적재하고 바른 바이트코드로 작성되었는지 검사합니다.

또한 일반적으로 클래스 로더는 두 종류로 나뉩니다. 하나는 bootstrap class loader이고 다른 하나는 user define class loader입니다. 모든 JVM 구현은 반드시 bootstrap class loader가 있어야 합니다. 그리고 JVM 명세에서 클래스 로더가 클래스를 찾는 방법을 지정하지 않습니다.

4. JVM Memory(Runtime Data Areas)

JVM Memory는 Runtime Data Areas라고도 불립니다. 해당 공간에는 Method Area, Heap, JVM Language Stacks, PC Registers, Native Method Stacks 등으로 구성 되어 있습니다.

이 공간은 클래스 로더에 의해 데이터가 적재되는 공간입니다.

4.1. Method Area

Method Area(이하 "메소드 지역")은 Type(class, inteface) 데이터들을 가지고 있습니다. 다이어그램으로 보면 아래와 같습니다.

╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋
┃Method Area                                               ┃
┃╋━━━━━━━━━━━━━━━━━━━━━━━━━━╋  ┃
┃┃class data(Field, Method, Runtime Constant Pool...) ┃…┃
┃╋━━━━━━━━━━━━━━━━━━━━━━━━━━╋  ┃
╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋

인스턴스 생성을 위한 필요 정보(필드, 메소드, 생성자...)를 적재한 공간입니다.

또한 각 Type 데이터에는 Runtime Constant Pool이라는 것을 가집니다. 이 곳은 심볼 테이블(symbol table)과 유사한 구조로 되어 있습니다. 상수 풀에는 해당 Type의 메소드, 필드, 문자열 상수등의 레퍼런스를 가지고 있습니다. 실제 물리적 메모리 위치를 참조할 때 사용합니다. 그리고 종종 바이트 코드를 메모리에 전부 올리기엔 크기 때문에 바이트 코드를 참조할 레퍼런스만 상수 풀에 저장하고 추후에 해당 값을 참조해서 실행할 바이트 코드를 찾아 메모리에 적재하게 하는 경우도 있습니다. 또한, 상수 풀을 사용함으로 동적 로딩(dynamic loading)이 가능합니다.

4.2. Heap

╋━━━━━━━━━━━━━━━━━╋
┃Heap                              ┃
┃╋━━━╋ ╋━━━╋ ╋━━━╋  ┃
┃┃object┃ ┃object┃ ┃object┃…┃
┃╋━━━╋ ╋━━━╋ ╋━━━╋  ┃
╋━━━━━━━━━━━━━━━━━╋

Heap(이하 "힙")은 객체들이 적재되는 공간입니다. 메소드 지역에서 참조한 값을 바탕으로 새로운 객체를 생성하면 이곳에 적재됩니다.

4.3. JVM Language Stacks

JVM Language Stacks(이하 "JVM 스택")은 아래의 다이어그램을 참조하면 됩니다. 추후에 기술할 PC Registers, Native Method Stacks도 이 다이어그램을 참조합니다.

╋━━━━━━━━━━╋ ╋━━━━━━━━━━╋ ╋━━━━━━━━━━╋
┃Thread              ┃ ┃Thread              ┃ ┃Thread              ┃
╋━━━━━━━━━━╋ ╋━━━━━━━━━━╋ ╋━━━━━━━━━━╋
┃JVM Language Stacks ┃ ┃JVM Language Stacks ┃ ┃JVM Language Stacks ┃
┃PC Registers        ┃ ┃PC Registers        ┃ ┃PC Registers        ┃
┃Native Method Stacks┃ ┃Native Method Stacks┃ ┃Native Method Stacks┃
╋━━━━━━━━━━╋ ╋━━━━━━━━━━╋ ╋━━━━━━━━━━╋
           ↕                       ↕                       ↕
╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋
┃Heap                                                                  ┃
╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋

메소드 프레임(method frame)들이 JVM 스택에 하나씩 쌓이게 됩니다. 메소드 프레임은 간단하게 메소드라고 생각해도 됩니다. 스택 자료구조 형식이기 때문에 스택의 맨위에서부터 차례대로 메소드를 실행합니다. 또한 하나의 힙을 모든 스레드가 공유합니다. 하지만 각 스레드는 자신들만의 고유 JVM 스택을 가지고 있습니다.

4.4. PC Registers

PC는 Program Counter의 축약어입니다. 따라서 원래는 Program Counter Registers가 됩니다. 해당 영역은 현재 실행하고 있는 부분의 주소(adress)를 가지고 있습니다. 일반적으로 PC의 값은 현재 명령이 끝난 뒤에 값을 증가시킵니다. 그리고 해당하는 값의 명령을 실행하게 됩니다. 즉, 실행될 명령의 주소를 가지고 있습니다.

4.5. Native Method Stacks

일반적으로 JVM은 네이티브 방식을 지원합니다. 따라서 스레드에서 네이티브 방식의 메소드가 실행되는 경우 Native Method Stacks(이하 "네이티브 스택")에 쌓입니다. 일반적인 메소드를 실행하는 경우 JVM 스택에 쌓이다가 해당 메소드 내부에 네이티브 방식을 사용하는 메소드(예를 들면 C언어로 작성된 메소드)가 있다면 해당 메소드는 네이티브 스택에 쌓입니다.

5. Execution Engine

클래스 로더에 의해 JVM 메모리 공간에 적재된 바이트 코드를 Execution Engine(이하 "실행 엔진")을 이용해 실행합니다. 하지만 바이트 코드를 그대로 쓰는 것은 아니고 기계어로 변경한 뒤에 사용하게 됩니다. 해당 작업을 실행 엔진이 합니다. 그리고 바이트 코드를 기계어로 변경할 때엔 두 종류의 방식을 사용합니다. 각각 Interpreter와 JIT (Just-In-Time) compiler입니다.

Interpreter(이하 "인터프리터")는 우리가 알고 있는대로 방식대로 바이트 코드를 실행합니다. 하나의 명령어를 그때그때 해석해서 실행하게 되어 있습니다. JIT (Just-In-Time) compiler(이하 "JIT 컴파일러")는 인터프리터의 단점(성능,속도 등)을 보완하기 위해 도입되었습니다. 실행 엔진이 인터프리터를 이용해 명령어를 하나씩 실행하지만 JIT 컴파일러는 적정한 시간에 전체 바이트 코드를 네이티브 코드로 변경합니다. 이후에는 실행 엔진이 인터프리터 대신 네이티브로 컴파일된 코드를 실행합니다.

다만 JIT 컴파일러와 Java 컴파일러는 다른 것입니다. 다이어그램을 보면 이해가 빠를 것 같습니다.

               Java Compiler     JIT Compiler
                    ↓               ↓
Java Source Code ------- Bytecode ------- Native Code

6. Native Method Interface(JNI)

Native Method Interface는 줄여서 JNI라고도 합니다. JNI는 JVM에 의해 실행되는 코드 중 네이티브로 실행하는 것이 있다면 해당 네이티브 코드를 호출하거나 호출 될 수 있도록 만든 일종의 프레임워크입니다.

7. Native Method Libraries

네이티브 메소드 실행에 필요한 라이브러리들을 뜻합니다.

8. Closing Remarks

간단하게 JVM에 대해 알아봤습니다. 혹시라도 잘못된 점이 있다면 말씀 부탁드립니다. :D

Go Top(문서 처음으로)



출처 - http://jdm.kr/blog/188

'Language > JAVA' 카테고리의 다른 글

Generic 메서드  (0) 2017.10.20
자바 람다식(Lambda Expressions in Java)  (0) 2016.09.09
GC  (0) 2016.08.05
Do You Really Get Classloaders?  (0) 2016.08.04
JVM ClassLoader의 작동원리  (0) 2016.08.04
:

GC

Language/JAVA 2016. 8. 5. 10:33

1. 자바 VM은 힙을 세개의 영역으로 나누어 사용한다.
  1) New/Young 영역 : 새로 생성된 객체를 저장
  2) Old 영역 : 만들어진지 오래된 객체를 저장
  3) Permanent 영역 : JVM클래스와 메서드 객체를 저장


자바가 사용하는 메모리 구조


여기서 New 영역은 다시  
 a) Eden : 모든 새로 만들어진 객체를 저장
 b) Survivor Space 1, Survivor Space 2 : Old 영역으로 넘어가기 전 객체들이 저장되는 공간
으로 구분된다.

2. Garbage Collector
자바 언어의 중요한 특징중 하나.
전통적인 언어의 경우 메모리를 사용한 뒤에는 일일이 메모리를 수거해 주어야 했다. 
그러나, 자바 언어 에서는 GC기술을 사용하여 개발자로 하여금 메모리 관리에서 자유롭게 했다.

자바의 GC는 New/Young 영역과 Old 영역에 대해서만 GC를 수행한다.  
(Permanent 영역은 code가 올라가는 부분이기 때문에 GC가 필요없다.)

1) Minor GC
New 영역의 GC를 Minor GC라고 부른다. New 영역은 Eden과 Survivor라는 두 영역으로 구분된다.
Eden 영역은 자바 객체가 생성 되자 마자 저장이 되는 곳이다. 
이곳의 객체가 Minor GC가 발생할 때 Survivor 영역으로 이동된다.

Survivor 영역은 Survivor1 과 Survivor2로 나뉘어 지는데, Minor GC가 발생하면 Eden과 Survivor1에 살아있는 객체가 Survivor2로 이동되고, Eden 영역과 Survivor1 영역에 남아있는(죽어있는) 객체는 clear된다.
결과적으로, 현재 살아있는 객체들만 Survivor2에 남아있게 된다.
다음번 Minor GC가 발생되면 같은 원리로, Eden과 Survivor2의 살아있는 객체가 Survivor1으로 이동되고, 두 영역은 Clear 된다.
이와 같은 방법으로 반복되면서 메모리를 수거한다. 이런 방식의 GC알고리즘을 Copy & Scavenge라고 한다. 속도가 빠르며 작은 크기의 메모리를 collecting 하는데 효과적이다.
Minor GC 과정중 오래된 객체는 Old 영역으로 복사된다.  
(Kein:그런데 얼마나 지나야 '오래된' 객체인 것인지는 명확히 모르겠네요)


새로 생성된 객체가 Eden 영역에 있다가 Minor GC가 일어난다. 살아있는 객체(파란색)가 SS1으로 옮겨지고 죽은객체(빨간색)는 그대로 남겨진다. 이후 Eden과 SS2를 clear 한다.



Eden에 새로 생성된 객체와 SS1에 있는 살아있는 객체를 SS2로 옮기고, Eden과 SS1 을 clear 한다.


생성된지 오래된 객체를 Old 영역으로 이동한다.



2) Full GC
Old 영역의 GC를 Full GC라 한다. Mark & Compact 알고리즘을 이용하는데, 전체 객체들의 reference를 따라가면서 연결이 끊긴 객체를 marking 한다. 이 작업이 끝나면 사용되지 않는 객체가 모두 mark 되고, 이 객체들을 삭제한다. 
실제로는 삭제가 아니라, mark 된 객체로 생기는 부분을 unmark된, 즉 사용중인 객체로 메꾸는 방법이다.

Full GC는 속도가 매우 느리며, Full GC가 일어나는 도중에 순간적으로 java application이 멈춰버리기 때문에 Full GC가 일어나는 정도와 Full GC에 소요되는 시간은 application의 성능과 안정성에 매우 큰 영향을 미치게 된다.


Full GC 동작 순서


3. Garbage Collection이 중요한 이유
Minor GC는 보통 0.5초 이내에 끝나기 때문에 큰 문제가 되지 않는다. 하지만, Full GC의 경우 보통 수 초가 소요되고, GC동안 Application이 멈추기 때문에 문제가 될 수 있다. 5초 동안 서버가 멈춘다면, 멈춰있는 동안 사용자의 request는 쇄도하게 되고, queue에 저장되었다가 요청이 한꺼번에 들어오게되면 여러 장애를 발생할 수 있게 된다.
원할한 서비스를 위해서 GC를 어떻게 일어나게 하느냐가 시스템의 안정성과 성능에 변수로 작용하게 된다.


4. Garbage Collection 알고리즘들
1) Default Collector
위에 설명한 전통적인 GC방법으로 Minor GC에 Scavenge를, Full GC에 Mark & Compact를 사용하는 방법이다.

2) Parallel GC
JDK 1.3까지는 하나의 thread 에서만 GC가 수행되었다. JDK 1.4 부터 지원되는 parallel gc 는 minor gc를 동시에 여러개의 thread 를 이용해서 수행하는 방법으로 하나의 thread 에서 gc를 수행하는 것보다 빠른 gc를 수행한다.



하지만, parallel gc가 언제나 유익한 것은 아니다. 1 CPU에서는 오히려 parallel gc 가 느리다. multi thread에 대한 지원이나 계산등을 위해서 4CPU의 256M 정도의 메모리를 보유한 시스템에서 유용하게 사용된다.
parallel gc 는 두가지 옵션을 제공하는데, Low-Pause 방식과 Throughput 방식이다. 
solaris 기준으로 Low-pause 방식은 ?XX:+UseParNewGC 옵션을 사용한다. Old GC를 수행할 때 Application 이 멈추는 현상을 최소화 하는데 역점을 두었다. 
Throughput 방식은 ?XX:+UseParallelGC 옵션을 사용하며, Old 영역을 GC할때는 기본 옵션을 사용하며 Minor GC가 발생했을 때 최대한 빨리 수행되도록 throughput에 역점을 둔 방식이다.

3) Concurrent GC
Full GC를 하는 동안 시간이 길고, Application이 순간적으로 멈추는 현상이 발생하는 단점을 보완하기 위해서, Full GC에 의해 Application이 멈추는 현상을 최소화 하기 위한 방법이다.
Full GC에 소요되는 작업을 Application을 멈추고 하는것이 아니라, 일부는 Application을 수행하고, Application이 멈추었을때 최소한의 작업만을 GC에 할당하는 방법으로 Application이 멈추는 시간을 최소화 한다.


Application이 수행중 일 때 (붉은라인) Full GC를 위한 작업을 수행한다. Application이 멈춘 시간동안에는 일부분의 작업을 수행하기 때문에 기존 Default 방법보다 멈추는 시간이 현저하게 줄어든다.
solaris JVM 에서는 -XX:+UseConcMarkSweepGC 옵션을 사용한다.

4) Incremental GC (Train GC)
Incremental GC 또는 Train GC 라고 불리우는 방법은 JDK 1.3 부터 지원된 방법이다. 의도 자체는 Full GC 동안 Application이 멈추는 시간을 최소화 하는데 목적이 있다.
Minor GC가 일어날 때 마다 Old 영역을 조금씩 GC를 해서, Full GC가 발생하는 횟수나 시간을 줄이는 방법이다.


그림에서 보듯, 왼쪽의 Default GC Full GC가 일어난 후에나 Old 영역이 Clear된다그러나오른쪽의 Incremental GC를 보면 Minor GC가 일어난후에, Old 영역이 일부 Collect된것을 알 수 있다.
Incremental GC
를 사용하는 방법은 JVM 옵션에 ?Xinc 옵션을 사용하면 된다
.
Incremental GC
는 많은 자원을 소모하고, Minor GC를 자주일으키며Incremental GC를 사용한다고 Full GC가 없어지거나 그 횟수가 획기적으로 줄어드는 것은 아니다오히려 느려지는 경우가 많다.

5. GC 로그 수집 및 분석 방법
이제 적군에 대해 알았으니 나 자신을 파악할 차례다. 
내 Application의 gc 동태를 파악하기 위해 java 실행 옵션에 -verbose:gc 옵션을 주면 gc 로그를 출력할 수 있다. 


garbage collection 로그

로그중 GC 는 Minor GC 이고, Full GC는 Full GC를 나타낸다. 
그 뒤의 숫자는 GC수행 전 heap 메모리 사용량 이다. (New + Old + Perm 영역)
그뒤 -> 이후의 숫자는 GC 수행 후 heap 메모리 사용량을 나타낸다. 
Minor GC 가 수행된 뒤에는 Eden 과 Survivor 영역의 GC가 수행된 것이며, GC이후 heap 사용량은 Old영역의 용량과 유사하다. 괄호 안의 Total Heap Size 는 현재 jvm 이 사용하는 Heap memory의 양이다. 이 크기는 java 실행 옵션의 -Xms -Xmx 옵션으로 설정이 가능한데, 예를 들어 -Xms512 -Xmx1024로 해 놓으면 jvm는 메모리 사용량에 따라서 512~1024m 사이에서 적절하게 메모리 사용량을 늘였다 줄였다 하며 동작한다.
그 다음값은 gc에 소요된 시간이다. 

위의 로그를 보면, Minor GC가 일어날 때 마다 약 20,000Kbytes 정도의 collection이 일어난다. Minor GC는 Eden과 survivor 영역 하나를 gc 하는 것이기 때문에  New 영역을 20,000Kbyte 정도로 생각할 수 있다. 
Full GC 때를 보면 약 44,000Kbytes 에서 1,749Kbytes 로 줄어든 것을 볼 수 있다. Old 영역에 큰 데이터가 많지 않은 경우이다. 
Data를 많이 사용하는 Application의 경우 전체 Heap 이 512M 라 할 때, Full GC 후에도 480M 정도로 유지되는 경우가 있다. 이런 경우에는 실제로 Application이 메모리를 많이 사용하는 경우라고 판단할 수 있기 때문에, 전체 Heap 메모리를 늘려주면 효과적이다. 




출처 - http://drkein.tistory.com/95

:

MySQL Cluster

DB/MySQL 2016. 8. 4. 18:08

Introduction 

MySQL 클러스터는 분산 컴퓨팅 환경에서 high-availability와 high-redundancy를 채택하였다. MySQL 클러스터는 NDB 클러스터 스토리지 엔진을 사용하여, 클러스터에서 여러 개의 서버가 함께 돌아가도록 한다. MySQL 클러스터가 지원하는 운영 체제는 Linux, Mac OS X, Solaris 등 이다. 더 자세한 정보는 다음 사이트를 참고 하길 바란다. http://www.mysql.com/products/cluster

MySQL Cluster Overview 


MySQL 클러스터는 share-nothing 시스템에서 in-memory 데이터 베이스의 클러스터링을 가능하게 한다. 이러한 아키텍쳐는 특정한 하드웨어 및 소프트웨어를 요구하지 않으므로 비용을 절감할 수 있도록 하며, 각 콤포넌트가 고유 메모리와 디스크를 보유함으로 단일 취약점(single point of failure)을 가지지 않는다.

MySQL 클러스터는 일반 MySQL 서버에 NDB라는 스토리지 엔진을 통합하여, 다음 그림과 같이 MySQL서버, NDB 클러스터의 데이터 노드, MGM 서버가 포함된 컴퓨터와 데이터에 접근하기 위한 어플리케이션 프로그램으로 구성된다.

데이터가 NDB 클러스터 스토리지 엔진에 저장될 때, 테이블은 데이터 노드에 저장된다. 각 테이블은 클러스터의 MySQL 서버에서 직접 접근이 가능하다. 그래서 클러스터의 어떤 정보를 업데이트 하면, 다른 모든 MySQL서버에서 곧바로 확인할 수 있다.

MySQL 클러스터의 데이터 노드에 저장된 데이터는 미러링이 가능하며, 클러스터는 트랜잭션 중단 등 각 노드들의 상태에 대한 핸들링이 가능하다.

http://dev.mysql.com/doc/refman/5.0/en/images/cluster-components-1.png
MySQL 클러스터의 구성

Basic MySQL Cluster Concepts 


NDB는 높은 가용성과 데이터 지속성을 갖는 인 메모리 스토리지 엔진이다. DB 스토리지 는 failover와 로드 밸런싱 옵션을 설정할 수 있다. MySQL클러스터는 NDB 스토리지 엔진과 MySQL 서버로 구성되어 있으며, MySQL 클러스터의 클러스터 부분은 MySQL 서버에 독립적이다. MySQL 클러스터의 각 부분은 노드로 간주한다.

"노드"는 일반적으로 컴퓨터를 지칭하지만 MySQL 클러스터에서는 "프로세스"를 말한다.


클러스터 노드에는 세 가지 타입이 있으며, MySQL Cluster를 구성하기 위해 최소한 노드 세 개가 있어야 한다.

  • MGM node : 이 노드는 설정을 포함, 다른 노드를 관리하는 매니저 노드이다. 다른 노드보다 가장 먼저 실행되며 ndb_mgmd 명령으로 실행시킨다.
  • data node : 클러스터의 데이터를 저장하는 노드이다. ndbd 명령으로 실행시킨다.
  • SQL node : 클러스터 데이터에 접근하는 노드이다. MySQL 클러스터에서는 NDB 클러스터 스토리지 엔진을 사용하는 MySQL 서버가 클라이언트 노드이다. mysqld --ndbcluster나 mysqld 명령으로 실행시키는데, 이 때는 my.cnf 에 ndbcluster를 추가한다. 

MGM 노드는 클러스터 컨피그레이션 파일과 로그를 관리한다. 데이터 노드에 이벤트가 발생하면, 데이터 노드는 그에 대한 정보를 매니저 서버로 보내고, 매니저 서버는 클러스터 로그를 기록한다.


Simple Multi-Computer How-To 


다음과 같이 4대의 컴퓨터로 클러스터를 구성하는 것을 가정하고 있다. (4개의 노드로 구성되고, 각각의 노드는 편이성을 위해 IP로 지칭한다.)

아래에서 필요한 컴퓨터는 리눅스가 설치된 인텔 기반 데스크탑 PC이며, 4대 모두 동일한 이더넷 카드(100Mbps나 1기가 비트)가 필요하다.

Node IP Address

Management (MGM) node 192.168.0.10

MySQL server (SQL) node 192.168.0.20

Data (NDBD) node "A" 192.168.0.30

Data (NDBD) node "B" 192.168.0.40
http://dev.mysql.com/doc/mysql/en/images/multi-comp-1.png


설치 및 사용 시 주의할 점은 MySQL 클러스터는 클러스터 노드 간 커뮤니케이션에 암호화 및 보호 장치가 전혀 없으므로, 웹 상에서 사용하려면 방화벽을 사용하는 등의 보안상의 대책이 필요하다는 것이다.

MySQL Cluster를 사용하기 위해서는 -max 버전을 설치해야 한다. 모든 설치는 root권한으로 진행하며 작업에 필요한 파일은 /usr/local/ 에 저장한다.

1. /etc/passwd 와 /etc/group 파일에서 mysql 그룹과 유저가 있는지 확인한 후 없으면 다 음과 같이 생성한다.
# cd /usr/local
# groupadd mysql
# useradd -g mysql mysql

2. 유저와 그룹 생성 후 압축을 풀고, 심볼릭 링크를 걸어준다.
# tar -xzvf mysql-max-4.1.13-pc-linux-gnu-i686.tar.gz
# ln -s /usr/local/ mysql-max-4.1.13-pc-linux-gnu-i686 mysql

3. mysql 디렉토리로 이동하여 시스템 데이터베이스 생성을 위한 스크립트를 실행시킨다.
# cd mysql
# scripts/mysql_install_db --user=mysql

4. MySQL 서버와 데이터 디렉토리의 퍼미션을 설정한다.
# chown -R root .
# chown -R mysql data
# chgrp -R mysql .

5. 시스템 부팅 시 자동적으로 Mysql을 실행할 수 있도록 설정한다.
# cp support-files/mysql.server /etc/rc.d/init.d/
# chmod +x /etc/rc.d/init.d/mysql.server
# chkconfig --add mysql.server

6. MGM (management) 노드를 별도의 PC에 설치할 경우 mysql 데몬은 설치하지 않아도 무방하다. 위와 같이 설치한 후 MGM 서버는 다음과 같이 설치를 계속한다.
# cd /usr/local/mysql/bin/
# cp ndb_mgm* /usr/local/bin/
# chmod +x ndb_mgm*

7. 각 데이터 노드와 SQL 노드는 MySQL서버 옵션과 connectstring에 대한 정보가 포함된 my.cnf파일이 필요하고, MGM노드는 config.ini 파일이 필요하다. 에디터를 열어 다음과 같이 편집한 후 파일을 저장한다.
# vi /etc/my.cnf 
[MYSQLD]			      # Options for mysqld process:
Ndbcluster			# run NDB engine
ndb-connectstring=192.168.0.10	# location of MGM node

[MYSQL_CLUSTER]		      # Options for ndbd process:
ndb-connectstring=192.168.0.10	# location of MGM node

8. MGM 노드의 설정 파일을 만들기 위해 적당한 디렉토리를 만든 후 에디터를 열어 다음과 같이 편집한다.
 # mkdir /var/lib/mysql-cluster
# cd /var/lib/mysql-cluster
# vi config.ini

[NDBD DEFAULT]		# Options affecting ndbd processes on all data nodes:
NoOfReplicas=2		# Number of replicas
DataMemory=80M	         # How much memory to allocate for data storage
IndexMemory=18M	         # How much memory to allocate for index storage
                  		# For DataMemory and IndexMemory, we have used the
                  		# default values. Since the "world" database takes up
                  		# only about 500KB, this should be more than enough
                  		# for this example Cluster setup.

[TCP DEFAULT]		# TCP/IP options:
portnumber=2202	         # This the default; however, you can use any
                  		# port that is free for all the hosts in cluster
                  		# Note: In MySQL 5.0, this parameter is deprecated;
                  		# it is recommended that you do not specify the 
                  		# portnumber at all and simply allow the port to be
                  		# allocated automatically

[NDB_MGMD]			# Management process options:
hostname=192.168.0.10		# Hostname or IP address of MGM node
datadir=/var/lib/mysql-cluster	# Directory for MGM node logfiles

[NDBD]				# Options for data node "A":
				# (one [NDBD] section per data node)
hostname=192.168.0.30		# Hostname or IP address
datadir=/usr/local/mysql/data	# Directory for this data node's 
				# datafiles

[NDBD]				# Options for data node "B":
hostname=192.168.0.40		# Hostname or IP address
datadir=/usr/local/mysql/data	# Directory for this data node's 
				# datafiles

[MYSQLD]			         # SQL node options:
hostname=192.168.0.20	         # Hostname or IP address
datadir=/usr/local/mysql/data	# Directory for SQL node's datafiles
				# (additional mysqld connections can be
				# specified for this node for various
				# purposes such as running ndb_restore)

설치와 설정 과정이 끝났다. 이제 실행을 해 보자.

클러스터 노드들은 각각 실행되어야 한다. 실행 순서는 매니지먼트 노드를 가장 먼저 실행할 것을 권한다. 그 다음은 스토리지 노드와 SQL노드 순이다.
1. 매니지먼트 호스트에서 MGM 노드 프로세스를 실행시켜 보자. 컨피그레이션 파일을 찾을 수 있도록 -f 옵션을 주도록 한다.
# ndb_mgmd -f /var/lib/mysql-cluster/config.ini
MGM 노드를 다운시킬 때에는 다음과 같이 하면 된다.
# ndb_mgm -e shutdown

2. 다음으로 데이터 노드 호스트에서 NDBD프로세스를 실행시킨다. --initial 이란 인수는 ndbd를 처음 실행할 때와 컨피그레이션이 바뀐 후 재시작 할 때만 사용한다.
# ndbd --initial

3. SQL 노드는 다음과 같이 mysql.server를 실행시킨다.
# /etc/rc.d/init.d/mysql.server start

4. 이제 모든 노드가 실행되었으니 MGM 노드 클라이언트를 띄워 간단히 테스트를 해보자.

Ndb_mgm명령어를 입력하였을 때 정상적으로 동작하는 모습은 다음과 같이 프롬프트가 떨어지는 모습이다.
# ndb_mgm
-- NDB Cluster -- Management Client --
ndb_mgm> 

5. 이제 show명령어를 사용하여 클러스터의 모든 노드들이 정상적으로 연동되는지 확인을 해 보자. HELP 를 입력하면 다른 명령어들도 확인해 볼 수 있다. 다음과 같이 4개의 노드를 구성하는 것에 성공하였다.
ndb_mgm> show
Connected to Management Server at: 192.168.0.10:1186
Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=2    @192.168.0.30  (Version: 4.1.13, Nodegroup: 0, Master)
id=3    @192.168.0.40 (Version: 4.1.13, Nodegroup: 0)

[ndb_mgmd(MGM)] 1 node(s)
id=1    @192.168.0.10 (Version: 4.1.13)

[mysqld(API)]   1 node(s)
id=4   (Version: 4.1.13)

ndb_mgm>

MySQL 클러스터의 제한 


MySQL Cluster 4.1.x 버전은 다음과 같은 사용상의 제한점을 지닌다.

  • 트랙잭션 수행 중의 롤백을 지원하지 않으므로, 작업 수행 중에 문제가 발생하였다면, 전체 트랙잭션 이전으로 롤백하여야 한다.
  • 실제 논리적인 메모리의 한계는 없으므로 물리적으로 허용하는 만큼 메모리를 설정하는 것이 가능하다.
  • 컬럼 명의 길이는 31자, 데이터베이스와 테이블 명은 122자까지 길이가 제한된다. 데이터베이스 테이블, 시스템 테이블, BLOB인덱스를 포함한 메타 데이터(속성정보)는 1600개까지만 가능하다.
  • 클러스터에서 생성할 수 있는 테이블 수는 최대 128개이다.
  • 하나의 로우 전체 크기가 8KB가 최대이다(BLOB를 포함하지 않은 경우).
  • 테이블의 Key는 32개가 최대이다.
  • 모든 클러스터의 기종은 동일해야 한다. 기종에 따른 비트저장방식이 다른 경우에 문제가 발생하기 때문이다.
  • 운영 중 스키마 변경이 불가능하다.
  • 운영 중 노드를 추가하거나 삭제할 수 없다.
  • 최대 데이터 노드의 수는 48개이다.
  • 모든 노드는 63개가 최대이다. (SQL node, Data node, 매니저를 포함) 


MySQL Cluster FAQ 


Cluster 와 Replication의 차이

리플리케이션은 비동기화 방식이고, 클러스터는 동기화 방식이다. 따라서 리플리케이션은 일방적으로 데이타를 전달하여 복제를 하지만 클러스터는 동기방식이므로 데이타를 복제한 후 결과를 확인하기 때문에 데이타 누락이 발생하지 않는다. 다만 복제한 결과를 확인해야 하기 때문에 Cluster가 Replication보다는 속도가 느리다. 또한 Replication의 경우 복제된 데이터에 대한 신뢰를 할 수 없다.


Cluster가 사용하는 네트워크 (How do computers in a cluster communicate?)

MySQL 클러스터는 TCP/IP를 통해 서로 통신한다. 최소한 100Mbps의 이더넷을 사용해야 하며 원활한 통신을 위해 gigabit 이더넷을 권고한다. 실제 데이터가 메모리에 존재하여 사용되며 물리적인 측면에서 봤을 때 CPU, 메모리, 각 노드간의 통신을 위한 네트워킹이 주를 이룬다. 이중 가장 속도가 느린 네트워크의 속도를 높임으로써 전체적인 빠른 동작이 가능하도록 해야 한다. 또한, 더욱 빠른 SCI 프로토콜도 지원하며, 이는 특정 하드웨어를 필요로 한다.


클러스터를 구성하기 위해 컴퓨터가 얼마나 필요한가?

최소한 3대가 있어야 클러스터 구성이 가능하나, MGM 노드와 SQL 노드, 스토리지 노드 둘, 이렇게 4 대로 구성하길 권한다. 하나의 노드가 실패했을 때 지속적인 서비스를 하기 위해서 MGM노드는 분리된 컴퓨터에서 실행되어야 한다.


클러스터에서 각 컴퓨터들이 하는 일은?

MySQL 클러스터는 물리적, 논리적으로 구성된다. 컴퓨터는 물리적 요소이며 호스트라고 불리기도 한다. 논리적, 기능적 요소는 노드이다. 노드는 역할에 따라 MGM 노드, data 노드(ndbd), SQL 노드로 나뉜다.


어떤 OS에서 사용할 수 있는가?
MySQL 4.1.12 현재 MySQL 클러스터는 공식적으로 Linux, Mac OS X, Solaris를 지원한다.


MySQL 클러스터가 요구하는 하드웨어 사양은?

NDB가 설치되고 실행되는 모든 플랫폼이면 가능하나, 당연히 빠른 CPU, 높은 메모리에서 더 성능이 좋다(64-bit CPU에서 더 빠르다). 네트워크은 일반 TCP/IP를 지원하면 되고, SCI 를 지원하려면 특정 하드웨어가 요구된다.


MySQL 클러스터가 TCP/IP를 이용한다면 하나 이상의 노드를 인터넷을 통해 다른 곳에서 실행시킬 수 있는가?

가능하다. 하지만 MySQL 클러스터는 어떠한 보안도 제공되지 않으므로, 외부에서 클러스터 데이터 노드나 매니저 노드에 직접 접근하지 못하도록 해야 한다.


클러스터 사용을 위해 새로운 프로그래밍 언어나 쿼리를 배워야 하나?

표준 (My)SQL 쿼리나 명령을 사용하므로 그러지 않아도 된다.


클러스터 사용 시 에러나 경고 메시지는 어디서 찾나 ?
두 가지 방법이 있다. MySQL창에서 SHOW ERRORS나 SHOW WARNINGS로 확인하는 방법과 프롬프트 상태에서 perror --ndb error-code 를 사용하는 방법이 있다.


MySQL Cluster transaction-safe? 어떤 테이블 타입이 클러스터를 지원하나?
MySQL에서 NDB 스토리지 엔진과 생성된 테이블은 트랜잭션을 지원한다. NDB는 클러스터링만 지원하는 MySQL 스토리지 엔진이다.


"NDB" 의 의미는?
"Network Database".


클러스터를 지원하는 MySQL 버전은? 소스를 컴파일 해야 하나?

MySQL-max 4.1.3부터 지원한다. 바이너리 파일은 컴파일을 할 필요가 없다.


RAM은 얼마나 필요한가? 디스크는 사용하지 못하나?

클러스터는 오직 in-memory이며, 모든 테이블 데이터(인덱스 포함)가 RAM에 저장된다. 클러스터에서 필요한 RAM용량은 다음 공식으로 계산한다. (SizeofDatabase * NumberOfReplicas * 1.1 ) / NumberOfDataNodes


ERROR 1114: The table 'my_cluster_table' is full

위와 같은 에러가 발생했을 때는 할당된 메모리가 부족한 경우이다.


FULL TEXT 인덱스를 지원하는가?

현재 지원하지 않는다.


하나의 컴퓨터에서 여러 개의 노드가 돌아가는가?

가능하긴 하지만 권하진 않는다. 각 노드들이 다른 컴퓨터에서 실행되는 것이 더 안정적이다.


클러스터를 재시작하지 않고 노드를 추가할 수 있는가?

할 수 없다. MGM 이나 SQL 노드를 추가하려면 새로 시작해야 한다.


어떻게 기존의 MySQL 데이터베이스를 클러스터로 임포트 하는가?

ENGINE=NDB 나 ENGINE=NDBCLUSTER 옵션을 가진 테이블은 임포트할 수 있다. 또는 ALTER 기능으로 기존의 테이블을 클러스터로 변환 사용할 수 있다.

- ALTER TABLE OLD_TABLE ENGINE=NDBCLUSTER;


Arbitrator란 ?

클러스터에서 한 개 혹은 그 이상의 노드가 실패할 경우, MGM 서버나 다른 노드가 그 노드의 역할을 대신하여 다른 노드들로 하여금 실패한 노드와 같은 노드로 인식하게 하는 기능을 한다. 이런한 역할을 하는 노드를 중재인이라고 한다.


클러스터 shut down시에 어떤 일이 일어나는가?

클러스터 데이터 노드의 메모리에 있던 데이터가 디스크에 쓰여지고, 그 다음에 클러스터가 시작될 때 다시 메모리에 로드된다.


클러스터에서 다른 매니저 노드를 구성하는 것은?

fail-safe에 있어서 도움이 된다. 단지 하나의 MGM 노드 만이 클러스터를 컨트롤 할 수 있지만 MGM 노드 하나를 primary로, 추가의 매니저 노드를 primary MGM 노드가 실패했을 때 인계받도록 하면 된다.


5. MySQL Cluster Glossary 


Cluster

일반적으로 Cluster는 하나의 업무를 수행하기 위해 함께 동작하는 컴퓨터 세트이다. NDB Cluster는 자료저장, 복구, 컴퓨터 간의 분배 관리 등을 시행하기 위해 MySQL을 사용하는 Storge Engine 이다. MySQL Cluster는 in-memory storage를 사용한 shared-noting 아키텍쳐에서 분산된MySQL DB를 지원하기 위해 NDB엔진을 사용하여 함께 돌아가는 컴퓨터 그룹이다.


Configuration Files

클러스터, 호스트, 노드에 관계된 직접적인 정보를 포함하는 파일이다. 클러스터 시작 시 Cluster의 MGM 노드가 읽어들인다.


Backup

디스크나 다른 Long-term Storage에 저장되는 모든 클러스터 데이타, 트랜젝션, 로그의 완전한 카피를 말한다.


Restore

백업에 저장되는 것과 같이 클러스터에 그 전 상태로 되돌리는 것을 말한다.


CheckPoint

일반적으로 데이타가 디스크에 저장될 때 체크포인트에 도달한다고 말한다. 클러스터에서는 Committed된 트랜잭션을 디스크에 저장하는 시간을 말한다. NDB Storage Engine에는 일관되게 클러스터의 데이타를 보존하기 위해 두 종류의 CheckPoint가 있다. LocalCheckPoint(LCP) : 싱글 노드의 체크포인트. 그러나 클러스터의 모든 노드에서 LCP를 사용한다. LCP는 디스크에 노드의 모든 데이타를 저장하도록 한다(보통 매 몇 분마다). 클러스터 Activity의 노드와 레벨, 다른 요인에 의해 저장되는 데이타의 양은 의존적이다. GlobalCheckPoint(GCP) : GCP는 모든 노드의 트랜잭션이 동기화되고, redo-log가 Disk에 저장될 때 몇 분마다 발생한다.


Cluster Host

MySQL Cluster의 구성 컴퓨터. 클러스터는 물리적 구조와 논리적 구조를 가진다. 물리적으로 클러스터는 Cluster Host라는 컴퓨터의 수로 구성된다.


Node

MySQL Cluster의 논리적, 기능적 요소를 말하며 Cluster Node라고도 한다. MySQL Cluster에서는 node란 용어를 Cluster의 물리적 Component인 Process를 지칭한다. MySQL Cluster가 동작하기 위해 3가지 타입의 노드가 있다.


MGM node - MySQL Cluster에서 다른 노드들의 설정 정보, 노드의 시작과 정지, 네트워크 파티셔닝, 백업과 저장 등을 포함하여 다른 노드들을 관리한다.


SQL node (MySQL Server) - 클러스터의 데이터 노드안에 저장된 데이터를 Serve 하는 MySQL Server 인스턴스. 데이타를 저장, 분배, 업데이트하는 클라이언트는 MySQL Server를 통해 접근 가능하다.


Data node - 이 노드는 실제 데이타를 저장한다. 현재 싱글 클러스터는 총 48개의 데이타 노드를 지원한다.

싱글 머신에 한 개 이상의 노드가 공존할 수도 있고, 한 머신에 완전한 클러스터를 구성하는 것도 가능하다. MySQL 클러스터에서 호스트는 클러스터의 물리적 컴퍼넌트이며, 노드는 논리적 혹은 기능적인 컴퍼넌트, 즉 프로세스라는 것을 잊지 말자.


Node group

데이터 노드의 집합. 노드 그룹 안의 모든 데이터 노드는 같은 데이터(fragment)를 포함한다. 그리고 싱글 그룹의 모든 노드는 다른 호스트에 존재해야 한다.


Node failure

MySQL 클러스터는 클러스터를 구성하는 어느 한 노드의 기능에만 의존적이지 않다. 클러스터는 하나 혹은 몇 개의 노드가 실패해도 계속될 수 있다.


Node restart

실패한 클러스터 노드의 리스타팅 과정.


Initial node restart

노드의 이전의 파일 시스템을 지우고 시작하는 클러스터 노드의 과정. 소프트웨어 향상과 그 밖의 특별한 상황 등에 사용된다.


System crash(or System fail)

클러스터의 상태가 확인되지 않는 등 많은 클러스터 노드가 실패했을 때 일어날 수 있다.


System restart

클러스터의 리스타팅과 디스크 로그 및 체크 포인트로부터 reinstall하는 프로세스를 말한다. 클러스터를 shutdown 한 이후에 일어나는 과정이다.


fragment

데이터베이스 테이블의 한 부분. NDB스토리지 엔진에서 테이블을 나누어 fragments의 수에 따라 저장한다. Fragment는 파티션이라 불리기도 한다. MySQL 클러스터에서 테이블은, 머신과 노드 간의 로드 밸런싱을 용이하게 할 수 있도록 fragment된다.


Replica

NBD 스토리지 엔진에서 각 테이블 프레그먼트는 여분을 포함하여 다른 데이터 노드에 저장된 많은 replica를 갖는다. 현재는 fragment 당 4개 이상의 replica가 가능하다.


Transpoter

노드들 간의 데이터 이동을 제공하는 프로토콜 TCP/IP(local), TCP/IP(remote), SCI, SHM(MySQL 4.1 버전에서 실험적임)


NDB(Network DataBase)

NDB는 MySQL클러스터에서 사용하는 스토리지 엔진을 말 함. NDB 스토리지 엔진은 모든 일반적인 MySQL 컬럼 타입과 SQL문을 지원하며, ACID(DB무결성 보장을 위한 트랜잭션)성질을 가진다.


Shared-nothing architecture

MySQL 클러스터의 이상적인 아키텍쳐. 진정한 Shared-nothing setup 에서 각 노드는 분리된 호스트에서 실행된다. 이러한 배열은 싱글 호스트나 싱글 노드가 아니면 SOF나 시스템 병목현상이 전체적으로 발생할 수 있다는 데 있다.


In-memory storage

각 데이터 노드에 저장된 모든 데이터는 그 노드의 호스트 컴퓨터의 메모리에 유지된다. 클러스터의 각 데이터 노드를 위해, (데이터 노드의 수로 나뉜 replica의 수 * 데이터베이스 사이즈)만큼의 가용 RAM의 양을 확보해 두어야 한다. 그러니까, 데이터베이스가 1기가의 메모리를 차지하고, 4개의 replica와 8개의 노드로 클러스터를 구성하고자 하면, 각 노드당 최소 500MB의 메모리가 필요하다. 그리고 OS와 다른 어플리케이션 프로그램이 쓰는 메모리가 추가로 필요하다.


Table

관계형 데이터베이스에서는 table은 일반적으로 동일하게 구조화된 레코드의 set을 가리킨다. MySQL 클러스터에서 데이터베이스 테이블은 fragment의 set으로써 데이터 노드에 저장되고, 각 fragment는 추가로 데이터 노드에 복제된다. 같은 fragment를 replicate한 데이터 노드의 set이나 fragment의 set을 노드 그룹이라 한다.


Cluster Programs : 명령어들

서버 데몬
  • ndbd : 데이터 노드 데몬
  • ndb_mgmd : MGM서버 데몬
클라이언트 프로그램
  • ndb_mgm : MGM 클라이언트
  • ndb_waiter : 클러스터의 모든 노드들의 상태를 확인할 때 사용
  • ndb_restore : 백업으로부터 클러스터의 데이터를 복구할 때 사용

Contributors 

처음 작성자 : 송은영,f405(ccotti22) f405@naver.com (2006.2.1 15:37)

작성일 : 2005년 8월 10일 수요일

이 문서는 MySQL Cluster 4.0대의 매뉴얼을 번역, 정리한 것으로 틀린 부분을 다소 포함할 수 있으며, 저는 그에 대한 책임을 지지 않겠습니다.

부족하지만 다른 분들도 공부하는데 도움이 되길 바랍니다.

그리고 이 문서를 작성하기 전 참고한 리눅스 및 MySQL 문서들을 작성하신 많은 선배님들에게 감사의 말씀을 드립니다. 그리고 이 경어는 생략하였습니다. 양해의 말씀을...

출처 - http://nuninaya.tistory.com/127

:

스케일 아웃 측면에서 살펴본 MySQL의 특성

DB/MySQL 2016. 8. 4. 18:07

스케일 아웃 측면에서 살펴본 MySQL의 특성

최근 인터넷 서비스들은 글로벌을 지향하고 소셜 네트워크 기능들을 추가하다 보니 데이터의 양과 트래픽의 양이 급속히 증가하고 있다. 또한 가용성 확보 목적으로 RDBMS도 이젠 스케일아웃(Scale-Out)에 자유롭지 못한 상황에 놓이게 되었다. RDBMS가 여러 측면에서 최상의 조합 기능을 제공하지만, 개별 영역의 장점을 추구하는 솔루션들보다 좋은 성능을 낼 수 없는 건 당연하다. 스케일아웃 관점에 맞는 솔루션을 찾을 필요가 있어 MySQL의 스케일아웃 측면에서 어떤 솔루션들이 있는지 살펴보고자 한다. 

[필자] 하호진 | KTH에서 포털 서비스 및 플랫폼(Identity/Payment) 개발 업무를 수행했으며, 현재 와이즈에코에서 이사로 일하고 있다. 개인 블로그 mimul.com/pebble/default를 운영한다.


1. MySQL Partitioning

1) 개요

파티셔닝은 대규모 테이블을 여러 개의 작은 파티션으로 분할해 성능을 높이는 기술이다. 각 행에 대해 각각의 파티션에 분할하며, MySQL에서는 5.1버전부터 지원한다. 파티셔닝은 주로 데이터 웨어하우스와 같은 거대한 테이블을 사용하는 경우에 위력을 발휘한다. 일반적으로 B 트리 인덱스가 커지면서 검색 및 삽입 속도가 저하된다(계산 순서는 O(log m N)). 하지만, 테이블을 파티션으로 나누는 것으로, B 트리 인덱스의 오버헤드를 줄일 수 있다.


 
그림 1 파티션된 테이블

파티션 테이블은 데이터의 분류 조건에 의해 여러 개의 작은 파티션으로 나뉘어 저장된다. 

+ 제약 사항
- 파티셔닝된 테이블은 스토리지 엔진이 같아야 한다. 
-외부키 제약은 사용할 수 없다.
-FULLTEXT 인덱스를 사용할 수 없다. 
-GIS 컬럼을 사용할 수 없다.
-임시 테이블, MERGE 스토리지 엔진, CSV 스토리지 엔진은 파티셔닝할 수 없다.


2) 방식

+ RANGE 
파티션마다 칼럼의 값이 취할 범위를 지정하는 방식이다.

 


 + LIST

파티션 마다 칼럼의 값을 직접 지정하는 방식이다.

 

+ HASH
HASH 값을 갖고 파티션을 할당하고, 할당이 사용자에 의해 정해지는 것이 아니라 MySQL에 맡기는 방식이다.

 

파티션 방식의 수식을 좀 더 이해하기 쉽게 설명하면, 내부적으로‘2012-05-15’라는 입력 값이 들어간다면 birthday가 아래와 같이 처리되어 파티션 1에 저장된다.


+ KEY

HASH와 비슷하나 분할 결정 값은 Primary Key(혹은 Unique Key)에 대해 서버 측의 결정 알고리즘(MySQL 클러스터:MD5, 다른 스토리지 엔진:PASSWORD())에 의해 결정되는 방식이다.
- PRIMARY/UNIQUE 키가 없으면 사용 불가
- UNIQUE 키가 NOT NULL이 아니면 불가(NULL 값은 MD5, PASSWORD 함수 적용 불가)

 

+ 서브 파티셔닝 RANGE와 LIST일 때 각 파티션을 더 분할할 수가 있다. 이것을 서브파티션이라고 한다.



  


3) 장단점

+ 장점
- 대량의 데이터 저장
- 테이블을 분할할 수 있기 때문에 많은 양의 데이터를 저장할 수 있다.

- 부하 경감
- 테이블의 데이터를 분할할 수 있어서 쿼리에 검색되는 데이터가 줄어든다.
- 해당 디스크에 남아있는 분할 데이터를 받을 확률이 높기 때문에 캐시 히트율도 높아진다.
- 집계 함수(SUM/COUNT)가 병렬 처리가 가능해 속도 향상을 가져 온다.

+ 단점
- 분할 방법의 정의, 관리, 그것을 취급하는 애플리케이션 측의 구현, 조사 비용 등이 증가한다.


4) 고려사항

+ 장점
 -테이블 설계 시 PK는 파티셔닝키와 연관돼야 하고 PK를 제외한 추가 제약 조건은 불가능하만, 테이블 특성에 맞는 것들만 파티셔닝 테이블로 설계해야 한다. 그리고 파티셔닝 키가 모든 조회 조건에 들어가야 한다는 점도 유의해야 한다. ? 
그 외는 1) 개요의 제약 사항을 참고하기 바란다.



2. MySQL Cluster

1) 개요

MySQL Cluster는 공유 디스크를 사용하지 않는 Active-Active 형태의 데이터베이스 클러스터에서 트랜잭션을 지원하고 MySQL의 SQL 문장을 사용할 수 있는 관계형 데이터베이스이다. 단일 장애 지점을 없애기 위하여 99.999%의 가용성(연간 5분 정도의 정지시간)을 달성하기 위한 설계가 반영돼 있다. 데이터를 여러 서버에 분산함으로써 동시 다발적으로 대량으로 발생하는 데이터 업데이트를 신속하게 처리하고, 확장성을 높인 접근이다. 온라인 백업뿐만 아니라 클러스터에 서버 추가와 업데이트도 온라인 상태에서 할 수 있기 때문에 클러스터를 중단 없이 운용할 수 있다. MySQL Cluster의 시발점은 통신장비 업체 에릭슨 휴대 통신망의 가입자 데이터베이스용으로 개발된 Ericsson Network DataBase(NDB)라고 한다. 2003년부터 MySQL 서버의 기능과 통합해 제품화하고, 현재 MySQL 서버와 별도의 제품으로 개발?판매가 진행되고 있다. 

+아키텍처
MySQL Cluster에서 공유 디스크를 사용하지 않는 대신 여러 서버에 데이터를 분산 배치하고, 항상 여러 서버가 동일한 데이터 사본을 갖고 있게 한 접근이다. 각 노드의 특성은 다음 <표 1>과 같다.



 

각 테이블의 기본 키 또는 고유 키의 해시를 계산해 파티션을 내부적으로 만들고, 해시 값과 데이터 노드의 수에 따라 각 파티션의 데이터를 데이터 노드에 분산한다. 분산된 데이터는 같은 그룹 데이터 노드의 복제본에 중복 저장된다. 파티션의 데이터가 변경되면 동일한 파티션을 가진 데이터 노드에 동기적으로 변경 사항이 반영되기 때문에 각 데이터 노드의 데이터는 항상 동일하게 유지된다.



 
그림 2 Cluster

클러스터에 있는 데이터 노드? 비트 패킷을 보내 모니터링하고 데이터 노드가 중지된 경우 클러스터에서 자동으로 분리된다. 또한 재해 복구 데이터 노드는 같은 그룹의 데이터 노드에서 최신 변경사항까지 차이를 취득해 데이터를 자동으로 반영하고 데이터를 동기화할 때 클러스터에 다시 참여한다.


+ 특징
- 자동 파티셔닝
- 분산 프라그먼트
- 동기화 방식
- 자동으로 이뤄지는 고속 데이터 노드

+ 페일오버
- 자동 재동기화
-트랜잭션 지원

+ 제약 사항
- 인메모리 인덱스
- 크로스 테이블 조인, 레인지 스캔 등을 지원 안 함
- 포린키 지원 안 함
- 롱 트랜젝션 지원 안 함
- 네트워크 지연 시 치명적
- 모든 클러스터의 기종은 동일해야 함. 기종에 따른 비트 저장방식이 다른 경우에 문제 발생



2) 방식

+ Shared-Nothing



 
그림 3 Shared-Nothing

각 데이터 노드별 독립적인 스토리지를 연결하고 스토리지 공유를 하지 않기 때문에 오라클 RAC와는 달라 스토리지 장애 발생 가능성을 차단하는 구조이다.


+Data Partitioning(데이터 분산 구조)

 
그림 4 Data Partitioning

테이블 Row 단위의 여러 노드에 분산해 쓰기 성능 확장이 가능하고 하나의 노드 그룹 시스템에 동일한 복제본으로 이중화 구성을 했다.


3) 장단점


+ 장점
  -고성능?고가용성
  - 어플리케이션에서 샤딩 기능이 필요 없어 개발 및 유지보수 비용 절감
  - Join 실행 가능
  - 샤드(Shard) 간 ACID 보장
  - 네트워크 홉이 크게 줄어 높은 처리 성능과 짧은 대기 시간 제공
  - 즉각적인 페일오버 및 복구 지원

+ 단점
  - MySQL Cluster 7.2에서 많은 개선이 있었지만 테이블 조인 성능이 떨어짐
  - 클러스터 격리 수준이 READ-COMMITTED



4) 고려사항

+ Distribution Awareness 고려한 설계 MySQL Cluster 내에서 데이터의 분산은 이른바 Sharding과 같은 원리로 이뤄지고 있다. 그래서 Distribution Awareness가 제대로 고려되지 않은, 데이터 노드 수가 증가하면 네트워크 병목현상이 일어나 성능 저하를 유발한다. 이를 위해서는 Sharding 방식으로 테이블을 정의하고 응용 프로그램에서 사용하는 쿼리도 조정한다면 효율을 높일 수 있다. 예를 들어 아래와 같이 Distribution Awareness를 이용하기 위해서는 테이블 정의와 쿼리를 조정해야 한다.


 

그리고 Distribution Awareness가 효과가 있는지 확인하려면 'EXPLAIN PARTITIONS SELECT ...'를 이용해 파티션이 하나만 선택됐는지 확인한다.

+ 키 설계도 중요하다.
MySQL Cluster는 Hash 인덱스 및 Ordered 인덱스라는 두 유형의 인덱스가 있다. Ordered 인덱스는 한 테이블에서 여러 개를 만들 수 있지만, 해시 인덱스는 테이블마다 하나만 만들 수 있다. 즉, 해시 인덱스로 구성되는 기본 키뿐이다. 한편, UNIQUE KEY 제약 조건을 이용하는 경우에는 해시 인덱스가 될 수 있다. 하지만 MySQL Cluster에서는 UNIQUE 키를 정의하면 내부적으로 지원 테이블이라는 다른 테이블이 생성된다. 지원 테이블만큼 테이블에 대한 참조가 증가하므로 UNIQUE KEY 제약 조건을 이용하는 키는 성능이 떨어짐을 알아야 한다.



3. MySQL Replication

1) 개요

MySQL은 마스터/슬레이브 복제 기능을 제공한다. MySQL에서 지원하는 것은 비동기식 복제로 마스터 서버에서 실행되는 SQL 문을 슬레이브 서버로 전송하고 슬레이브로 다시 실행해 데이터를 일관되게 유지하는 기법을 사용하고 있다. 이것은 스테이트먼트 기반 리플리케이션(SBR, Statement Based Replication)이라고 한다. SBR는 그 구조에 근본적인 문제가 있다. 예를 들어 UUID() 함수를 사용할 경우 마스터와 슬레이브에서 각각 UUID()를 실행하면, 각기 다른 결과로 나타난다. 그 결과, 마스터와 슬레이브는 데이터가 불일치하게 된다. 이 문제를 해결하려면 슬레이브로 전달되는 정보를 스테이트먼트 대신 실제로 테이블에 기록된 내용 또는 행 자체를 복제한다. 그것을 구현하는 것이 로우 기반 리플리케이션(RBR, Row Based Replication)이다. 

MySQL 5.1에서 UUID()을 복제하지 못할 스테이트먼트를 포함할 때만 자동으로 SBR에서 RBR로 전환 MIXED 모드가 기본값(binlog_format)으로 돼 있다. 

+아키텍처

 
그림 5 Replication

MySQL Replication은 READ 관련 스케일아웃만 가능할 뿐, WRITE 관련 스케일아웃은 불가하다. 만약 Replication 운영 시 마스터 트래픽이 과도하게 발생하면, 마스터와 슬레이브 간 데이터 동기화 지연 현상이 발생하기도 한다는 점을 염두에 둬야 한다. 동작의 흐름을 살펴본다면 아래와 같다.

① Slave I/O 스레드가 Master에 접속
② Master가 Slave를 인증하고 Slave와의 세션 개시
③ Slave I/O 스레드가 바이너리 로그파일(파일명, 위치)을 요구
④ Master(binlog dump 스레드)가 요구된 지점으로부터 이벤트를 바이너리 로그에서 읽어 들여 Slave에 전송
⑤ Slave I/O 스레드는 받아 낸 이벤트를 relay-log에 기록
⑥ Slave SQL 스레드가 relay-log 내용을 읽어 들여 SQL문을 실행
⑦ Master에 새로운 이벤트가 있으면 Master가 Slave에 송신



2) 방식

+ Linux Heartbeat + MySQL Replication

 
그림 6 Heartbeat + MySQL replication

Heartbeat 프로토콜을 사용해 노드 간 생존 확인 메시지를 송수신해 장애 여부를 인지한다. 두 서버 사이에는 가상(Virtual) IP가 위치해 장애 시 가상 IP는 살아있는 서버로 송수신해 장애를 피한다.


+ L/B + MySQL Replication

 
그림 7 L/B + MySQL Replication

여러 대의 슬레이브를 앞에 두고 부하 분산을 목표로 하며??서 마스터에서 장애가 발생하면 L/B는 자동 IP를 슬레이브로 향하게 해 서비스가 중단 없이 가능하게 된다.


+Linux Heartbeat + DRBD + MySQL Replication

 
그림 8 Heartbeat + DRBD + MySQL Replication

디스크 미러링 소프트웨어(DRBD; 단방향 복제, 동기 복제, 오픈소스)를 활용해 HA를 구성하는 방식이다. 이는 동기 방식으로 데이터 복제가 이뤄져 데이터 불일치가 없는 장점을 갖고 있다.

3) 장단점

+ 장점
  - MySQL 서버의 부하 분산 가능
  - 실시간 백업 가능


+ 단점
  - 장애가 발생시 슬레이브에 반영이 안 될 가능성 존재
  - Master와 Slave 간 데이터 동기화 지연 발생 가능성 존재
  - 장애 복구가 수동으로 이뤄짐



4) 고려 사항

+ MySQL 5.6.3에서는 slave multithread를 지원하지만, 이전 버전의 경우 Slave는 하나의 스레드로만 SQL을 실행하기 때문에 서버 간 동기화 지연 현상이 발생한다. 따라서 replicate_do_db 혹은 replicate_do_table 옵션을 사용해 실제로 적용할 객체들만 선별적으로 동기화하는 것이다. 이는 서비스 단위로 기능을 나눌 수도 있고, 역할별로 기능을 나눌 수 있게 할 수 있다. 그 외에 롱 트렌젝션을 제거하고, Slave 개수를 잘 조절하고, 작업 집합이 InnoDB 버퍼 풀보다 훨씬 큰 경우는 Slave pre-fetching 기술도 활용해 볼 만하다.

+ MySQL Replication에서 5.5버전부터 Semi-syncronous 기능이 추가됐다. 부하량이 적은 환경에서 마스터와 슬레이브 간의 데이터 정합성을 강화시키는 방법이므로 필요 시 활용하면 좋다.



4. MySQL Sharding

샤딩은 물리적으로 다른 데이터베이스에 데이터를 수평 분할 방식으로 분산 저장하고 조회하는 방법을 말한다. 여러 데이터베이스를 대상으로 작업해야 하기 때문에 경우에 따라서는 기능에 제약이 있을 수 있고(JOIN 연산 등) 일관성(consistency)과 복제(replication) 등에서 불리한 점이 많다. 과거의 샤딩은 애플리케이션 서버 레벨에서 구현하는 경우가 많았는데 최근에는 이를 플랫폼 차원에서 제공하려는 시도가 많다. 그중 미들티어에 샤딩 플랫폼을 둔 Gizzard, Spider, Spock Proxy에 대해 알아본다.


1) Gizzard


+ 개요
트위터(Twitter)에서 자체 개발한 데이터를 분산 환경에 쉽게 구성?관리하고, 장애 발생에 유연하게 대처할 수 있는 오픈소스이면서 미들웨어다. Gizzard 의 핵심이 되는 것은 샤딩(Sharding)이라는 기술이다. 트위터에 따르면, 샤딩은 파티션과 복제라는 두 기술로 구성됐다. 파티션은 하나의 데이터베이스를 해시 등을 사용해 여러 부분으로 나눔으로써 여러 데이터베이스에 분산하는 것을 말하고, 복제는 한 데이터 복제를 다른 서버에 만드는 것이다. 데이터를 복제해 전체 탄력성이 증가함과 동시에 대량의 액세스에 대해 복수의 서버가 동시에 응답할 수 있기 때문에 성능 향상을 기대할 수 있다. 

+ 아키텍처



 
그림 9 Replication

Gizzard는 데이터 저장소와 클라이언트 애플리케이션 사이에 위치해 모든 질의는 Gizzard를 통해 이뤄지고 있어 Gizzard가 분할?복제 키를 쥐고 있다.

 
그림 10 Gizzard Partition

① Gizzard 는 데이터 매핑 선행 테이블에서 데이터 조각을 관리한다. 키에 해당하는 값이 어디에 저장됐는지 샤드 정보를 갖고 있다. 특정 데이터에 관한 키 값을 해시 함수로 돌리고 결과값을 Gizzard에 전달하면, Gizzard는 해당 데이터가 어떤 구역에 속할지 숫자 정보를 생성한다. 이러한 함수는 프로그래밍 가능하기 때문에 사용자 성향에 맞춰 지역성 혹은 균형성 면에서 최적화할 수 있다.



 
그림 11 Gizzard Replication

② Gizzard는 'Replication Tree'로 복제 데이터를 관리한다. 매핑 테이블이 지칭하는 각 데이터 조각들은 물리적 또는 논리적인 형태로 구현될 수 있다. 즉, 물리적인 형태는 특정 데이터 저장소를 의미하고, 논리적인 형태는 데이터 조각에 관한 트리를 의미한다. 트리 안의 각 브랜치들은 데이터의 논리적인 변형을 나타내고, 각 노드들은 데이터 저장소를 의미한다.

③ Gizzard는 장애 상황에도 강한 시스템이다. 특정 파티션 내에 있는 복제 데이터가 유실됐을 지라도, Gizzard는 남은 다른 정상적인 복제 데이터 시스템에 읽기/쓰기를 전환 요청한다. 대응 시나리오는 데이터 조각 안의 특정 복제 데이터 불능이 발생하면 Gizzard는 최대한 빠르게 다른 정상적인 복제 데이터에 읽기/쓰기 작업을 시도해서 정상적인 응답을 주고, Gizzard 내부에서도 문제가 발생했던 복제 데이터가 정상으로 돌아오면, 변경 이력을 다시 적용해 동기화한다.



 
그림 12 Gizzard Migrations

④ Gizzard는 데이터 이전 방안을 제시할 수 있다. 데이터 노드가 A에서 B로 이전한다고 가정할 때 Replicate 샤드가 A와 B 사이에 위치하고 Writeonly는 B 앞에 위치해서 A의 데이터를 B로 복제하게 된다. Writeonly 샤드는 B가 사용 가능한 시점까지 유지되다가 B가 사용 가능한 시점이 되면 WriteOnly는 빠지고 Replicate가 동시에 A와 B에 데이터를 복제하며 동기화해 준다.

 + 고려사항 Gizzard는 동일 데이터를 동시에 변경하려면 데이터 충돌(Confliction)이 발생한다. 그래서 Gizzard는 데이터가 적용 순서를 보장하지 않기 때문에 모델링 시 반드시 이러한 점을 염두에 둬야 한다.



2) SPIDER for MySQL

+ 개요
SPIDER는 Kentoku SHIBA가 개발한 스토리지 엔진이다. MySQL의 파티셔닝 기능을 사용해 파티션마다 다른 서버로 데이터를 저장할 수 있게 한 구조이다. Sharding 기능이 가능한 스토리지 엔진이라고 할 수 있다. 물론 데이터가 저장된 서버가 다른 경우에도 조인할 수 있는 장점이 있다. 이러한 구조를 구현할 수 있었던 배경은 MySQL의 유연한 스토리지 엔진구조가 있었기 때문이다. 

+ 아키텍처

 
그림 13 Spider for MySQL

Spider 는 위 그림처럼 테이블 링크를 통해 로컬의 MySQL 서버처럼 활용할 수 있는 구조이다. 내부적으로는 클러스터의 약점인 애플리케이션에서 구현하던 분산 환경에서의 조인과 트렌잭션 문제를 Spider가 해결해 준다. 더불어 Spider는 XA 트렌잭션과 테이블 파티셔닝을 지원한다. GPL 라이선스 정책을 갖고 있다. 여기에 병BR>+ 고려사항
① SPIDER 테이블을 드롭해도 데이터 노드의 데이터는 사라지지 않는다. SPIDER은 FEDERATED 스토리지 엔진과 마찬가지를 생성하는 스토리지 엔진으로 테이블 DROP 때는 링크만 제거된다. 더불어 TRUNCATE 명령문은 원격 MySQL Server의 데이터를 모두 클리어해 버리므로 주의하자.
② MySQL Cluster처럼 Spider도 파티션을 전제로 한 스토리지 엔진이기 때문에 Distribution Awareness를 고려한 설계를 해줘야 한다.
③ 전체 텍스트 검색과 R-Tree 인덱스를 지원하지 못한다.



3) Spock Proxy

+ 개요
Spock Proxy는 MySQL Proxy를 바탕으로 제작된 샤딩 플랫폼이다. 데이터베이스들을 수평적 분할해 여러 샤드(shard)로 나눠줘 응용 프로그램들이 직면한 중요한 문제들을 해결해 줬고, 이로써 데이터베이스는 성능과 확장성을 쉽게 높일 수 있다. 주요 역할은 Proxy가 클라이언트로부터 전송되는 쿼리를 가로채 데이터가 분할된 기법에 따라 적절한 MySQL 서버에 쿼리를 전송한다. 이후 각 MySQL 서버로부터의 응답을 모아 일반 MySQL 결과인 것처럼 클라이언트로 다시 전송한다.

+ 아키텍처


 
그림 14 Spock Proxy

Spock proxy는 MySQL DB의 Table(universal_db)에 샤딩 규칙을 저장한다. 그래서 애플리케이션 서버로부터 전달받은 SQL을 파싱해, 이 SQL에 shard key가 있는지 파악한다. 만약 shard key가 있다면 universal_db에 기록된 기준에 따라 MySQL 인스턴스를 찾아 SQL을 전달한다. 이런 방식을 사용할 경우 SQL에 shard key와 관련한 정보를 기술할 필요가 없는 장점으로 인해 기존 애플리케이션을 그대로 이용할 수 있다. 

+ MySQL Proxy와 다른 점
Spock Proxy는 MySQL Proxy에서 갈라진 것이다. 코드의 많은 부분이 변경되지 않았지만 기반 아키텍처가 다르다.

① MySQL Proxy는 최적화를 위해 Lua 스크립트 언어를 지원하지만, Spock Proxy는 그렇지 않다. 성능상의 이유로 C/C++를 활용했다.
② MySQL Proxy는 각 클라이언트가 개별 데이터베이스에 직접 인증하는 것을 허용한다. 이는 클라이언트가 proxy 작업에 앞서 최소 연결을 해야 하기 때문에 문제가 있는 방법이다. Spock Proxy는 클라이언트로부터 독립된 서버 연결을 하도록 설계됐다.
③ Spock Proxy는 클라이언트와 서버 연결을 분리해, 관리할 최소/최대 연결 크기를 허용한다. 시작 시에 proxy는 최소 연결 개 수만큼을 미리 연결해 놓는다.
④ 다중 서버 Send/Recv가 가능하다. 그래서 다수의 서버에 요청을 보내고, 이 결과들을 합치는 것 또한 가능하다. 

+ 고려사항
Spock Proxy의 제약사항을 보면 쉽게 구현 단계에서 고려 사항들이 도출될 것이다 
① 데이터베이스들간의 조인이 불가능하다.
② 저장 프로시저와 트랜잭션 지원은 제한적이다.
③ 중첩 질의는 불가능하다.
④ SELECT에서 2개 테이블의 JOIN은 지원하지만, GROUP BY는 지원하지 않는다.
⑤ INSERT에서 칼럼명은 항상 표현돼야 한다.
⑥ MySQL 함수는 데이터들이 여러 파티션에 걸쳐 있는 경우 MAX, MIN, SUM, AVERAGE만 지원한다.
⑦ Spock Proxy는 read only (slave)와 read/write (master)를 구분하지 못한다.
⑧ auto_increment 값이 다르다.



5. 결론

MySQL은 다양한 방식의 스케일아웃을 지원하는 솔루션들이 있고, 지속적으로 개발?보완되고 있다. 중요한 건 우리가 용도에 적합한 솔루션들을 선택할 수 있는 혜안을 갖고 판단할 필요가 있다는 것이다. 비즈니스에 어느 정도 제약성도 있다는 점을 기획자들이 인지할 수 있게 지속적으로 커뮤니케이션 하는 활동도 필요하다. 거기에 DBA나 프로그래머들은 제약 사항 및 고려 사항들을 숙지하고 있어야 하며, 운용하면서 발생될 수 있는 문제점을 애플리케이션이든, 자체 미들웨어를 갖추든 보완하는 자세도 필요해 보인다. 트위터나 페이스북 등에서 행해지는 MySQL을 보완해 주는 미들웨어들을 유심히 살펴본다면 힌트를 얻을 수 있을 것이다.





출처 : 한국데이터베이스진흥원

제공 : DB포탈사이트 DBguide.net


'DB > MySQL' 카테고리의 다른 글

MySQL Cluster  (0) 2016.08.04
MySQL root 패스워드 분실  (0) 2015.05.21
MSSQL 문자열 구분자 분리 (테이블 반환 함수)  (0) 2012.12.11
MSSQL PROC ARRAY  (0) 2012.12.11
MySQL 프로세스 리스트 보기  (0) 2011.04.22
:

In Memory Data Grid

Network/Network 2016. 8. 4. 16:31

IMDG의 특징

저장소로 디스크 대신 메인 메모리를 사용하는 것은 전혀 새로운 시도가 아니다. 디스크보더 더 빨리 수행 결과를 얻기 위해 MMDB(Main Memory DBMS)를 사용하는 사례는 일상에서도 찾을 수 있다. 대표적인 예는 휴대 전화를 사용할 때이다. SMS나 통화를 시도할 때 상대방 정보를 빠른 시간 안에 찾기 위해 대부분의 통신사는 MMDB를 사용하고 있다.

IMDG(In Memory Data Grid)는 메인 메모리에 데이터를 저장한다는 점에서 MMDB와 같지만 아키텍처가 매우 다르다. IMDG의 특징을 간단히 정리하면 다음과 같다.

  • 데이터가 여러 서버에 분산돼서 저장된다.
  • 각 서버는 active 모드로 동작한다.
  • 데이터 모델은 보통 객체 지향형(serialize)이고 non-relational이다.
  • 필요에 따라 서버를 추가하거나 줄일 수 있는 경우가 많다.

즉, IMDG는 데이터를 MM(Main Memory)에 저장하고 확장성(Scalability)을 보장하며, 객체 자체를 저장할 수 있도록 구현됐다. 오픈 소스와 상용 제품을 구별하지 않으면 다음과 같은 IMDG 제품이 있다.

이 글에서는 제품의 기능과 성능을 비교하지는 않고, IMDG의 아키텍처를 살펴보고 어떻게 활용할 수 있을지 검토해 볼 것이다.

왜 메모리?

2012년 6월 현재 SATA(Serial ATA) 인터페이스를 사용하는 SSD(Solid State Drive)의 성능은 약 500MB/s 정도이고, 고가의 PCI Express를 사용하는 SSD는 약 3,000MB/s에 이른다. 10,000 RPM SATA HDD의 성능이 약 150MB/s 정도니까 SSD가 HDD보다 4~20배 정도 빠르다고 할 수 있다. 하지만 이에 반해 DDR3-2500의 성능은 20,000MB/s에 이른다. 메인 메모리의 처리 성능은 HDD보다 800배, 일반적인 SSD보다 40배, 가장 빠른 SSD보다 약 7배 빠르다. 게다가 요즘의 x86 서버는 서버 하나당 수백 GB 용량의 메인 메모리를 지원한다.

Michael Stonebraker에 따르면 전형적인 OLTP(online transaction processing) 데이터 용량은 약 1TB 정도이고, OLTP 처리 데이터 용량은 잘 증가하지 않는다고 한다. 만약 1TB 이상의 메인 메모리를 사용하는 서버 사용이 보편화된다면, 적어도 OLTP 분야에서는 모든 데이터를 메인 메모리에 둔 채 연산을 하는 것이 가능해진다.

컴퓨팅 역사에서 '좀 더 빠르게'는 언제나 최고의 덕목으로 추구해야 할 가치였다. 이렇게 메인 메모리 용량이 증가하게 된 만큼 영구 저장소 대신 메인 메모리를 저장소로 사용하는 플랫폼이 등장할 수 밖에 없게 된 것이다.

IMDG 아키텍처

메인 메모리를 저장소로 사용하려면 극복해야 하는 약점 두 가지가 있다. 용량의 한계와 신뢰성이다. 서버의 메인 메모리의 최대 용량을 넘어서는 데이터를 처리할 수 있어야 하고, 장애 발생 시 데이터 손실이 없도록 해야 한다.

IMDG는 용량의 한계를 분산 아키텍처를 이용하여 극복한다. 여러 기기에 데이터를 나누어 저장하는 방식으로 전체 용량 증가를 꾀하는 Horizontal Scalability 방식을 사용한다. 또한 신뢰성은 복제 시스템을 구성해 해결한다.

제품마다 세세한 차이가 있지만 IMDG 아키텍처를 일반화하면 그림 1과 같이 나타낼 수 있다.

imdg1

그림 1 IMDG 아키텍처

애플리케이션 서버(AS)에는 IMDG가 제공하는 클라이언트 라이브러리가 있고, 이 라이브러리를 이용해 IMDG에 접근한다.

많은 IMDG 제품이 데이터를 RDBMS 등에 동기화하는 기능을 제공한다. 그러나 이러한 별도의 영구 저장 시스템(RDBMS 등)을 반드시 구성해야 하는 것은 아니다. 일반적으로 IMDG에서는 직렬화를 통해 객체를 저장할 수 있도록 한다. Serializable 인터페이스를 구현한 객체를 저장할 수 있도록 한 제품도 있고, 독자적인 직렬화 방법을 제공하는 IMDG도 있다. 당연히 schemaless 구조라 사용 편의성이 매우 높다.

개념상 객체를 저장하고 조회할 수 있도록 한 In Memory Key-Value Database로 이해할 수 있다. IMDG에서 사용하는 데이터 모델은 Key-Value 모델이다. 그래서 이 키(key)를 이용해 데이터를 분산시켜 저장할 수 있다. NHN에서 사용하는 분산 메모리 캐싱 시스템인 Arcus와 같이 Consistency Hash 모델을 사용하는 것부터Hazelcast와 같이 단순한 modulo 방식을 사용하는 것까지 다양한 방식이 있다. 이렇게 저장할 때 반드시 하나 이상의 다른 노드를 복제 시스템으로 삼아서 장애 발생에 대처할 수 있도록 한다.

인터페이스는 제품별로 다양하다. 어떤 제품은 SQL-like한 형태의 문법을 제공하여 JDBC를 통해 접근하는 제품도 있고, Java의 Collection을 구현한 API를 제공하는 경우도 있다. 즉 여러 노드를 대상으로 하는 HashMap이나 HashSet을 사용할 수 있는 것이다.

IMDG는 Arcus와 같은 캐시 시스템과는 사용과 목적이 다르다. 그림 2는 Arcus의 아키텍처를 간단하게 표현한 것이다.

imdg2

그림 2 캐시 시스템인 Arcus의 아키텍처

Arcus와 같은 캐시 시스템도 메인 메모리를 저장소로 사용하고 Horizontal Scalability를 확보했다는 점에서는 IMDG와 같다. 하지만 그림 1과 그림 2에서와 같이 사용 형태와 목적은 크게 다르다. 캐시 시스템에서 영구 저장소의 사용은 필수이지만, IMDG에서 영구 저장소의 사용은 선택이다.

표 1 캐시 시스템과 IMDG의 읽기, 쓰기 성능 비교

 캐시 시스템IMDG
읽기캐시 안에 데이터가 있다면 데이터 베이스에서 읽어오지 않는다. 
캐시 안에 데이터가 없을 때는 데이터베이스에서 읽어온다.
언제나 IMDG에서만 읽어온다. 항상 메인 메모리에서 읽어오기 때문에 빠르다.
쓰기영구 저장소에 쓰기 때문에 캐시 시스템 적용과 쓰기 성능 향상은 관계 없다.영구 저장소에 데이터를 동기화하도록 구성하더라도, 제품에 따라 비동기 쓰기를 지원하는 제품이 있다. 비동기 쓰기를 지원하는 경우에는 매우 높은 수준의 쓰기 성능을 기대할 수 있다.

이외에도 데이터를 마이그레이션할 수 있는지, 신뢰성을 보장하는지, 복제 기능을 제공하는지 등의 차이가 캐시 시스템과 IMDG의 차이다.

IMDG의 기능

다음은 IMDG 제품 가운데 하나인 Hazelcast의 기능이다. HazelCast는 더블 라이선스 정책을 취하고 있는 제품으로, ElasticMemory와 같은 기능을 사용하려면 상용 라이선스를 구입해야 한다. 그러나 많은 기능이 오픈소스라서 별도의 비용 없이 사용할 수 있으며, 사용 레퍼런스 정보를 찾아 보기가 매우 쉽다.

HazelCast의 기능이 다른 모든 IMDG에서 제공하는 일반적인 기능이라고 할 수는 없지만 IMDG의 기능을 살펴보기에는 매우 좋은 예라서 간단하게 소개하겠다.

DistributedMap & DistributedMultiMap

Map<?, ?>을 구현한 클래스다. 여러 IMDG 노드에 Map 데이터가 분산 배치된다.

RDBMS의 테이블(table)은 Map<Object key, List<Object>>로 표현할 수 있기 때문에, RDBMS를 샤딩해서 쓰는 것과 비슷한 데이터 분산 효과를 얻을 수 있다. 더구나 HazelCast는 DistributedMap에서 SQL-like한 기능을 사용할 수 있도록 했다. Map에 있는 value를 검사할 때 WHERE 구문이나 LIKE, IN, BETWEEN 같은 SQL-like 구문을 사용할 수 있다.

HazelCast는 모든 데이터를 메모리에 두는 것뿐만 아니라 영구 저장소에 저장하는 기능도 제공한다. 이렇게 영구 저장소에 데이터를 저장하면 캐시 시스템으로 사용하도록 구성할 수 있다. LRU(Least Recently Used) 알고리즘이나 LFU(Least Frequently Used) 알고리즘을 선택해, 꼭 필요한 데이터만 메모리에 두고 상대적으로 잘 찾지 않는 나머지 데이터는 영구 저장소에 두게 할 수도 있다.

또한 MultiMap을 분산 환경에서 사용할 수 있도록 했다. 어떤 key를 조회하면 Collection <Object> 형태의 value 목록을 얻을 수 있다.

Distributed Collections

DistributedSet이나 DistributedList, DistributedQueue 등을 사용할 수 있다. 이런 Distributed Collection 객체에 있는 데이터는 어느 하나의 IMDG 노드가 아니라 여러 노드가 분산 저장된다. 그렇기 때문에 여러 노드에 저장된 단 하나의 List 객체 또는 Set 객체 유지가 가능하다.

DistributedTopic & DistributedEvent

HazelCast는 publish 순서를 보장하는 Topic 읽기가 가능하다. 즉 분산 Message Queue 시스템으로 이용할 수 있다는 뜻이다.

DistributedLock

말 그대로 분산 Lock이다. 여러 분산 시스템에서 하나의 Lock을 사용해 동기화할 수 있다.

Transactions

DistributedMap, DistributedQueue 등에 대한 트랜잭션을 사용할 수 있다. 커밋/롤백을 할 수 있기 때문에 더 신중한 연산이 필요한 곳에서도 IMDG를 사용할 수 있다.

대용량 메모리 사용과 GC

앞에서 소개한 대부분의 제품은 구현 언어로 Java를 사용한다. 수십 GB 크기의 힙을 사용해야 하는 만큼 Full GC에 필요한 시간도 상당히 오래 걸릴 수 있다. 그렇기 때문에 IMDG에서는 이런 제약을 극복할 수 있는 방법을 마련해 적용하고 있다. 바로 Off-heap 메모리(Direct Buffer)를 사용하는 것이다.

JVM에 Direct Buffer 생성을 요청하면 JVM은 힙 바깥의 공간에서 메모리를 할당해 사용한다. 이렇게 할당한 공간에 객체를 저장하도록 하는 것이다. Direct Buffer는 GC 대상 공간이 아니기 때문에, Full GC 문제가 발생하지 않게 된다. 보통 Direct Buffer에 대한 접근은 Heap Buffer보다 느리다. 하지만 큰 공간을 할당할 수 있고 Full GC에 대한 부담을 줄일 수 있기 때문에 매우 큰 용량의 메모리 공간을 사용할 때 Full GC 시간을 없앨 수 있어 항상 일정한 처리 시간을 확보할 수 있다는 것이 장점이다.

imdg3

그림 3 Heap Buffer와 Direct Buffer 디스크 비교(이미지 출처: Terracotta)

그러나 Direct Buffer를 이용해 객체를 저장하고 조회하는 데는, Memory Allocator를 만드는 것과 같은 매우 전문적인 기술이 필요하다. 그렇기 때문에 이러한 Off-heap 메모리를 사용해 객체를 저장하는 기능은 상용 IMDG에서만 제공하고 있다.

마치며

현재까지 IMDG를 주로 사용하는 곳은 캐시 시스템이다. 그러나 IMDG는 주저장소로 발전될 가능성이 매우 높은 플랫폼이다. 많은 경우 분산 Map은 충분히 RDBMS의 테이블을 대신할 수 있다. 제품에 따라 분산 Lock을 제공하는 제품이 있는데, 이런 분산 Lock을 바탕으로 정합성(Integrity Constraint) 기능을 제공할 수 있다면, 본격적으로 RDBMS를 대체할 수 있다.

이렇게 할 경우 백엔드 시스템으로 RDBMS를 사용해 통계 처리에 대응할 수 있을 것이다. 인터넷 서비스에서 RDBMS 사용이 보조 목적으로 바뀌는 것이다. 정합성 기능이 제공된다면 빠른 속도를 바탕으로 한 쾌적한 사용자 경험은 물론, 빠른 처리 속도를 바탕으로 그동안 제공하기 어려웠던 기능을 제공할 수 있는 기회가 생기는 것이다.

imdg4

그림 4 정합성을 지원하는 IMDG


출처 - http://d2.naver.com/helloworld/106824

:

Do You Really Get Classloaders?

Language/JAVA 2016. 8. 4. 16:00

Part I: An Overview of Java Classloaders, Delegation and Common Problems

In this part, we provide an overview of classloaders, explain how delegation works and examine how to solve common problems that Java developers encounter with classloaders on a regular basis.

Introduction: Why you should know, and fear, Classloaders

Classloaders are at the core of the Java language. Java EE containers, OSGi, various web frameworks and other tools use classloaders heavily. Yet, something goes wrong with classloading, would you know how to solve it?

Join us for a tour of the Java classloading mechanism, both from the JVM and developer point-of-view. We will look at typical problems related to classloading and how to solve them. NoClassDefFoundError, LinkageError and many others are symptoms of specific things going wrong that you can usually find and fix. For each problem, we’ll go through an example with a corresponding solution. We’ll also take a look at how and why classloaders leak and how can that be remedied.

And for dessert, we review how to reload a Java class using a dynamic classloader. To get there we’ll see how objects, classes and classloaders are tied to each other and the process required to make changes. We begin with a bird’s eye view of the problem, explain the reloading process, and then proceed to a specific example to illustrate typical problems and solutions.

Enter java.lang.ClassLoader

Let’s dive into the beautiful world of classloader mechanics.

It’s important to realize that each classloader is itself an object–an instance of a class that extends java.lang.ClassLoader. Every class is loaded by one of those instances and developers are free to subclass java.lang.ClassLoader to extend the manner in which the JVM loads classes.

There might be a little confusion: if a classloader has a class and every class is loaded by a classloader, then what comes first? We need an understanding of the mechanics of a classloader (by proxy of examining its API contract) and the JVM classloader hierarchy.

First, here is the API, with some less relevant parts omitted:

package java.lang;

public abstract class ClassLoader {

  public Class loadClass(String name);
  protected Class defineClass(byte[] b);

  public URL getResource(String name);
  public Enumeration getResources(String name);
  
  public ClassLoader getParent()
}

By far, the most important method of java.lang.ClassLoader is the loadClass method, which takes the fully qualified name of the class to be loaded and returns an object of class Class.

The defineClass method is used to materialize a class for the JVM. The byte array parameter ofdefineClass is the actual class byte code loaded from disk or any other location.

What if you no longer had to redeploy your Java code to see changes? The choice is yours. In just a few clicks you can Say Goodbye to Java Redeploys forever.

getResource and getResources return URLs to actually existing resources when given a name or a path to an expected resource. They are an important part of the classloader contract and have to handle delegation the same way as loadClass – delegating to the parent first and then trying to find the resource locally. We can even view loadClass as being roughly equivalent todefineClass(getResource(name).getBytes()).

The getParent method returns the parent classloader. We’ll have a more detailed look at what that means in the next section.

The lazy nature of Java has an effect on how do classloaders work – everything should be done at the last possible moment. A class will be loaded only when it is referenced somehow – by calling a constructor, a static method or field.

Now let’s get our hands dirty with some real code. Consider the following example: class A instantiates class B.

	public class A {
	  public void doSomething() {
  	 B b = new B();
   	 b.doSomethingElse();
	  }
	}

The statement B b = new B() is semantically equivalent to B b = A.class.getClassLoader().loadClass(“B”).newInstance()

As we see, every object in Java is associated with its class (A.class) and every class is associated with classloader (A.class.getClassLoader()) that was used to load the class.

When we instantiate a ClassLoader, we can specify a parent classloader as a constructor argument. If the parent classloader isn’t specified explicitly, the virtual machine’s system classloader will be assigned as a default parent. And with this note, let’s examine the classloader hierarchy of a JVM more closely.


출처 - http://zeroturnaround.com/rebellabs/rebel-labs-tutorial-do-you-really-get-classloaders/

'Language > JAVA' 카테고리의 다른 글

자바 JVM 정리(Java Virtual Machine)  (0) 2016.08.05
GC  (0) 2016.08.05
JVM ClassLoader의 작동원리  (0) 2016.08.04
클래스로더 1, 동적인 클래스 로딩과 클래스로더  (3) 2016.08.04
java class loader #2  (0) 2016.08.04
: