50
App Engine 의 Datastore [email protected] @devtainer

N03 app engineseminar

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: N03 app engineseminar

App Engine 의 Datas-tore

[email protected]@devtainer

Page 2: N03 app engineseminar

GAE/J Scalability

Google Data Store

Page 3: N03 app engineseminar

Google Data Store• Google App Engine 이 사용하는 분산

데이터베이스 시스템• Google File System 을 기반• Peta Byte 급 구조화된 데이터 저장 가능• 구조화된 데이터를 위한 분산 저장 시스템• 범용성 , 확장성 , 고성능 , 고가용성을 위해

개발됨• Non-Relational Database

– Key-Value Store

• JDO/JPA & Native API 지원• 단위 테스트를 위한 Local 버전

서버 ( 최소 100 만대 )

리눅스 OS

GFS(Google File System)

BigTable( 분산스토리지 )

Python

Django

App Application

JAVA

WAS

Page 4: N03 app engineseminar

Bigtable 의 주요 특징

• Big HASHMAP

• NoSQL, Key/Value Store

• No schema

• Entity Group 기반

• Write 비용 : Expensive

• Read 비용 : Cheap

Page 5: N03 app engineseminar

Google Data Store 의 데이터 모델• Google Data Store 의 특징

– Distributed– Persistent– Multidimensional– Sorted

• 디자인 핵심 키워드– Fault-tolerant– Persistent– Scalable– Self-managing

• 동적인 서버 확장 및 조정

MAP

Page 6: N03 app engineseminar

Google Datastore 의 장점

• Excellent read performance.

• Excellent query performance.

• Transparent redundant storage and load balancing.

• Flexible data structure.

• Query indexes.

Page 7: N03 app engineseminar

Datastore 의 제약사항• Write 가 느림

• 검색 가능한 Text 사이즈 : 500 자

• Entity 최대 사이즈 : 1Mb

• 최대 Batch (save/delete) : 500 Entity

• SQL 을 사용할 수 없음

• 데이터베이스의 제약조건을 적용할 수 없음

• Aggregation 함수를 지원하지 않음 (count, avg)

• 쿼리가 최대 조회 레코드 : 1000

• 쿼리에서 Equal 연산 이외의 조건은 1 개만 추가 가능

• 트랜잭션의 단위는 Entity Group 에 한정 됨

Page 8: N03 app engineseminar

GAE/J Data Storage Option

Page 9: N03 app engineseminar

Datastore Architecture

Google Application

Low-Level API

JDO JPA

Bigtable (Master Server)

Tablet Tablet Tablet Tablet

Google File System

……………

FS 0 FS 1 FS 2 FS 3 FS 4 FS n……

Page 10: N03 app engineseminar

Admin Console : Datastore Statistics

Page 11: N03 app engineseminar

Admin Console

Page 12: N03 app engineseminar

Admin Console : Datastore Viewer

Page 13: N03 app engineseminar

Admin Console : Datastore Indexes

Page 14: N03 app engineseminar

Datastore Interface (Native vs Stan-dard)• Low Level API & ORM Standard (JDO & JPA)• Low Level API & ORM Standard 의 기능적인 차이점은

없음• Schemaless 의 특정을 고려할 때 Native API 가 더 적합• ORM Standard 는 Google App Engine 에 애플리케이션

종속성을 추상화– Datanucleus 의 API 종속성을 제거

• Native API 를 사용할 경우 Entity 클래스를 이용하여 데이터 처리– 데이터를 클래스에 맵핑하기 어려움

Page 15: N03 app engineseminar

Native Datastore Interface

Page 16: N03 app engineseminar

Datastore 구성

• 모든 Entity 는 Kind 가 지정• Entity 는 하나이상의 Property 를 포함• 특정 Kind 에 포함된 Entity 는 동일한 Property 를 갖지 않음• Entity 의 Property 는 이름은 동일하지만 데이터 유형이 다를수 있음• Schemaless 의 특성• ID 는 지정하지 않을 경우 자동 할당 됨

Object-Oriented RDBMS Datastore

Class Table Kind

Object Record Entiry

Attribute Column Property

Page 17: N03 app engineseminar

Entity• App Engine Datastore 에서 관리하는 객체는 Entity• Entity 는 하나의 Key 를 포함

– 모든 Entity 중 유일한 구분자• Key 의 구성

– 패스– Parent Entity 의 key– Entity 의 Kind– Entity 에 할당된 이름

• App 이 할당한 값• Datastore 가 지정한 numeric ID

• 지원 데이터 타임 : integers, floating point values, strings, dates, binary data 등 ,

• 각 엔티티는 하나이상의 Property 를 포함– 하나의 Property 에 복수의 데이터 타입 저장 가능– 하나의 Property 에는 복수의 값이 저장 가능– 복수의 값들의 데이터 유형은 다를 수 있음

Page 18: N03 app engineseminar

Datastore 저장 모델• 주요 구성

– Kind : Table– Key : Primary Key– Entity Group : Partitioning– Property : column

Kind Persion

key /Person:iu

Entity Group /Person:iu

Name iu

age 30

Page 19: N03 app engineseminar

Low Level API• com.google.appengine.api.datastore.DatastoreService; • com.google.appengine.api.datastore.DatastoreServiceFactory;• com.google.appengine.api.datastore.Entity; • com.google.appengine.api.datastore.Key;• com.google.appengine.api.datastore.KeyFactory;

Page 20: N03 app engineseminar

Entity 클래스 주요 메서드• com.google.appengine.api.datastore.Entity• 생성자

– public Entity(Key key) – public Entity(String kind) – public Entity(String kind, Key parent) – public Entity(String kind, String keyName) – public Entity(String kind, String keyName, Key parent)

• 주요 Property 관련 메서드– public Map<String,Object> getProperties() – public Object getProperty(String propertyName) – public void removeProperty(String propertyName) – public void setPropertiesFrom(Entity src) – public void setProperty(String propertyName, Object value)

Page 21: N03 app engineseminar

Entity 생성DatastoreService datastore =

DatastoreServiceFactory.getDatastoreService();

Entity player = new Entity("Player");player.setProperty("name", "kim yuna");player.setProperty("age", 20);datastore.put(player);

Entity player2 = new Entity("Player");player2.setProperty("name", "Park Taehwan");player2.setProperty("age", 21);datastore.put(player2);

Page 22: N03 app engineseminar

Entity 생성 - schema-freeDatastoreService datastore =

DatastoreServiceFactory.getDatastoreService();

Entity player = new Entity("Player");player.setProperty("name", ”kim chanho");player.setProperty(”position", “pitcher”);datastore.put(player);

Page 23: N03 app engineseminar

Entity – Root Entity, Entity Group, Ancestor Path Entity employee1 = new Entity("Employee");employee1.setProperty("position", "Boss");employee1.setProperty("age", 60);datastore.put(employee1);

Entity employee2 = new Entity("Employee", employee1.getKey());employee2.setProperty("position", "manager");employee2.setProperty("age", 40);datastore.put(employee2);

Entity employee3 = new Entity("Employee", employee2.getKey());employee3.setProperty("position", "sub-manager");employee3.setProperty("age", 35);datastore.put(employee3)

Page 24: N03 app engineseminar

Entity – Root Entity, Entity Group, Ancestor Path

aglub19hcHBfaWRyDgsSCEVtcGxveWVlGAQM

aglub19hcHBfaWRyHAsSCEVtcGxveWVlGAQMCxIIRW1wbG95ZWUYBQw

aglub19hcHBfaWRyKgsSCEVtcGxveWVlGAQMCxIIRW1wbG95ZWUYBQwLEghFbXBsb3l-lZRgGDA

BossEntity Manager

Entity Sub-man-ager

Entity

Page 25: N03 app engineseminar

Entity – Root Entity, Entity Group, Ancestor Path

aglub19hcHBfaWRy-DgsS-CEVtcGxveWVlGAQM

aglub19hcHBfaWRyHAs-SCEVtcGxveWVlGAQM-CxIIRW1w-bG95ZWUY-BQw

aglub19hcHB-faWRyKgsS-CEVtcGxveWVl-GAQMCxIIR-W1w-bG95ZWUY-BQwLEghFbXBs-b3llZRgGDA

Root Key Instance

Child Key Instance

Child Key Instance

Employee("BOSS")

Employee("BOSS")/Employee("manager")

Employee("BOSS")/Employee("manager")/Em-ployee("sub-manager")

Page 26: N03 app engineseminar

Entity – Root Entity, Entity Group, Ancestor Path

Root Key Instance

Child Key Instance

Child Key Instance

Root Entity

Ancestor Path

Entity Group

Key.getParent()

Key.getParent()

Page 27: N03 app engineseminar

Root & Parent Entity & Key• Root Entity• Parent Entity

Entity emp1= new Entity("Employee");datastore.put(employee);

employeeGroup En-

tity

Entity emp1= new Entity("Employee");datastore.put(employee);

Entity address = new Entity("Address", employee.getKey());datastore.put(address);

employee, addressGroup En-

tity

Employee:8261

Employee:8261

Employee:8261 / Ad-dress:1

Entity emp2= new Entity("Employee");datastore.put(employee);

employeeGroup En-

tity Employee:8262

Page 28: N03 app engineseminar

Entity Group & Transaction• Transaction 의 최대 범위는 Entity Group• Entity Group 은 동일한 Tablet 서버에 위치

Entity emp1= new Entity("Employee");datastore.put(employee);

employeeGroup En-

tity

Entity emp1= new Entity("Employee");datastore.put(employee);

Entity address = new Entity("Address", employee.getKey());datastore.put(address);

employee, addressGroup En-

tity

Employee:8261

Employee:8261

Employee:8261 / Ad-dress:1

Entity emp2= new Entity("Employee");datastore.put(employee);

employeeGroup En-

tity Employee:8262

Page 29: N03 app engineseminar

Entity Group

• 하나의 트랜잭션에서 여러 Entity 를 조회 , 생성 , 수정 , 삭제

할 수 가능하지만 그 범위는 단일 Entity Group 에 국한

• Entity Group 는 부모 엔티티를 갖는 엔티티의 그룹

• 부모 엔티티를 가지 않은 엔티티를 Root 엔티티 라고 함

• Entity Group 은 하나의 Root Entity 와 Child Entity 로 구성

• 하나의 엔티티 그룹은 동일한 분산 네트웍 서버에 저장됨 (Tablet

서버 )

Page 30: N03 app engineseminar

Transaction DatastoreService datastore = DatastoreServiceFactory.getDatastoreService() ;

Transaction txn = datastore.beginTransaction(); try {     Key employeeKey = KeyFactory.createKey("Employee", "Joe");     Entity employee = datastore.get(employeeKey);     employee.setProperty("vacationDays", 10);      datastore.put(employee);      txn.commit(); } finally {     if (txn.isActive()) {         txn.rollback();     } }

Page 31: N03 app engineseminar

Batch Operation

import java.util.Arrays; import java.util.List;

// 코드 생략 Entity employee1 = new Entity("Employee"); Entity employee2 = new Entity("Employee"); Entity employee3 = new Entity("Employee"); // 코드 생략 List<Entity> employees = Arrays.asList (employee1, employee2, employee3); datastore.put(employees);

Page 32: N03 app engineseminar

Entity & Key Class• com.google.appengine.api.datastore.Entity

– public Entity(Key key) – public Entity(java.lang.String kind) – public Entity(java.lang.String kind, Key parent) – public Entity(java.lang.String kind, java.lang.String keyName) – public Entity(java.lang.String kind, java.lang.String keyName, Key

parent)

• com.google.appengine.api.datastore.KeyFactory– public static Key createKey(Key parent, java.lang.String kind, long

id)– public static Key createKey(Key parent, java.lang.String kind,

java.lang.String name) – public static Key createKey(java.lang.String kind, long id) – public static Key createKey(java.lang.String kind, java.lang.String

name)

Page 33: N03 app engineseminar

Entity 조회 , 수정 , 삭제DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();Key rootKey = KeyFactory.createKey("Employee", "BOSS");Entity employee = datastore.get(rootKey);

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();Key rootKey = KeyFactory.createKey("Employee", "BOSS");Datastore.delete(rootKey);

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();Key rootKey = KeyFactory.createKey("Employee", "BOSS");Entity employee = datastore.get(rootKey);employee.setProperty(“age”, 50);datasource.put(employee);

Retrieve

Modify

Remove

Page 34: N03 app engineseminar

Queryimport com.google.appengine.api.datastore.DatastoreService; import com.google.appengine.api.datastore.DatastoreServiceFactory; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.PreparedQuery; import com.google.appengine.api.datastore.Query;

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

Query q = new Query(”employee") q.addFilter("lastName", Query.FilterOperator.EQUAL, lastNameParam); q.addFilter("height", Query.FilterOperator.LESS_THAN, maxHeightParam);

PreparedQuery pq = datastore.prepare(q);

for (Entity result : pq.asIterable()) { String firstName = (String) result.getProperty("firstName"); String lastName = (String) result.getProperty("lastName"); Long height = (Long) result.getProperty("height"); System.out.println(lastName + " " + firstName + ", " + height.toString() + " inches tall"); }

Page 35: N03 app engineseminar

Filter Operator• Query.FilterOperator.LESS_THAN• Query.FilterOperator.LESS_THAN_OR_EQUAL• Query.FilterOperator.EQUAL• Query.FilterOperator.GREATER_THAN• Query.FilterOperator.GREATER_THAN_OR_EQUAL• Query.FilterOperator.NOT_EQUAL• Query.FilterOperator.IN

Page 36: N03 app engineseminar

Java Data Object

Page 37: N03 app engineseminar

Portability 확보

Page 38: N03 app engineseminar

JPA 2.0 (Data Nucleus JDO 구현체를 Provider 로 사용 )

JDO 2.3

Data Nucleus 의 JDO Provider

Low Level API

Datastore Interface (JDO vs JPA)• JPA 와 JDO 어노테이션으로 ORM 설정 가능• 두 표준간의 기능적인 차이는 없음• JDO-QL 과 JPA-QL 사용 가능

Google Datastore

Page 39: N03 app engineseminar

Datastore Interface (JDO & JPA)• JPA(Java Persistence API)

– RDBMS 를 저장소로 테이블과 객체 맵핑 표준 스펙• JDO(Java Data Object)

– Non-RDBMS 를 포함하는 저장소를 대상으로 하는 객체 맵핑 표준

Page 40: N03 app engineseminar

App Engine 의 JDO• App Engine Java SDK 는 JDO 구현체를 포함• Datastore 의 영속성 인터페이스로 지원• Version: JDO 2.3• DataNucleus Access Platform 의 구현체 사용

Page 41: N03 app engineseminar

JDO 설치 - jdoconfig.xml & JAR• war/WEB-INF/classes/META-INF/jdoconfig.xml

• 라이브러리 추가– war/WEB-INF/lib/appengine-api.jar

Page 42: N03 app engineseminar

JDO 설치 - Enhance 프로세스 적용• 클래스 컴파일 후 POJO Enhance 프로세스 적용

– java -cp classpath com.google.appengine.tools.enhancer.Enhance class-files

– appengine-java-sdk/lib/appengine-tools-api.jar

Page 43: N03 app engineseminar

JDO 설치 - Enhance 프로세스 적용 in Eclipse

Page 44: N03 app engineseminar

JDO 설치 - Enhance 프로세스 적용 in maven

Page 45: N03 app engineseminar

JDO 설치 - Enhance 프로세스 적용 in Ant<property name="sdk.dir" location="../appengine-java-sdk" />

<import file="${sdk.dir}/config/user/ant-macros.xml" /> 

<target name="datanucleusenhance" depends="compile"      description="Performs JDO enhancement on compiled data classes.">    <enhance_war war="war" /></target>

<target name="runserver" depends="datanucleusenhance"      description="Starts the development server.">    <dev_appserver war="war" port="8888" >      <options>        <arg value="--jvm_flag=-Xdebug"/>        <arg value="--jvm_flag=-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9999"/>      </options>    </dev_appserver></target>

Page 46: N03 app engineseminar

JDO 설치 - PMF 클래스import javax.jdo.JDOHelper;import javax.jdo.PersistenceManagerFactory;

public final class PMF { private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");

private PMF() { }

public static PersistenceManagerFactory get() { return pmfInstance; }}

// PersistenceManager pm = PMF.get().getPersistenceManager();

Page 47: N03 app engineseminar

데이터 클래스import com.google.appengine.api.datastore.Key;

import java.util.Date;import javax.jdo.annotations.IdGeneratorStrategy;import javax.jdo.annotations.PersistenceCapable;import javax.jdo.annotations.Persistent;import javax.jdo.annotations.PrimaryKey;

@PersistenceCapablepublic class Employee {    @PrimaryKey    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)    private Key key;

    @Persistent private String firstName;

    @Persistent private String lastName;

    @Persistent private Date hireDate; // 생성자 getter setter 생략}

Page 48: N03 app engineseminar

Object 영속성PersistenceManager pm = PMF.get().getPersistenceManager();

Employee e = new Employee(”Park", ”Chanho", new Date());

try {      pm.makePersistent(e);} finally {      pm.close();}

Page 49: N03 app engineseminar

Object 영속성 - IIpublic void updateEmployeeTitle(User user, String newTitle) {    PersistenceManager pm = PMF.get().getPersistenceManager();    try {        Employee e = pm.getObjectById(Employee.class, user.getEmail());        if (titleChangeIsAuthorized(e, newTitle) {            e.setTitle(newTitle);        } else {            throw new UnauthorizedTitleChangeException(e, newTitle);        }    } finally {        pm.close();    }}

pm.deletePersistent(e);

Page 50: N03 app engineseminar

Q&A