이 블로그 검색

2021년 11월 22일 월요일

mariadb maxscale 사용 시 주의점 (readwritesplit)

이번에 프로젝트를 하면서 겪었던 상황을 정리해본다.

mariadb MaxScale 은 db proxy 로 위치투명성, 고가용성, 로드밸런싱 등의 목적으로 사용된다. 그런데 혹시 코드중에서 insert 후 바로 select 를 수행하는 경우에는, 방금 저장한 내용을 못 가져 오는 경우가 발생할수 있다. 

readwritesplit 라는 모듈의 동작으로 발생될수 있는 상황인데, maxscale 은 위에 언급된 여러 기능을 구현하기 위해서 동적으로 로드되는(즉 shared library) 여러개의 모듈들이 존재한다. router 는 이러한 모듈의 한 종류이며, router 유형의 모듈 중에서, 읽기 성능 향상을 위한 모듈이 바로 readwritesplit 이다. 

글자 그대로, 이것은 사용자의 query 가 읽기인지 쓰기 인지에 따라 master 혹은 slave 에서 분리 처리되게 해준다. 즉 읽기 query 는 여러개의 slave 중 하나에서 처리되고, 쓰기 query 는 master(single node)에서만 처리된다.

그런데, 이로 인해 문제가 되는 상황은, insert 후 바로 동일 데이터를 select 하는 경우에, 방금 저장한 데이터가 완전하게 slave 로 복제가 안된 상황이 발생될수 있고, 이렇게 되면 조회 결과가 없는 것처럼 처리될수 있다.

그래서 문서를 통해 찾은 해결책은 다음 2 가지가 있다.

  • mariadb 와 maxscale 설정을 변경하거나 아니면 
  • 사용자의 프로그램에서 동일한 트랜잭션으로 묶는다. 문서를 보면, 동일한 트랜잭션 안에서는 select 쿼리가 무조건 master로 라우팅되므로 일관성 문제가 해결 된다.

 

참고

https://mariadb.com/kb/en/mariadb-maxscale-6-readwritesplit/

https://mariadb.com/kb/en/mariadb-maxscale-6-readwritesplit/#limitations

https://mariadb.com/docs/solutions/maxscale/routers/readwritesplit/ensure-causal-consistency-maxscale-read-write-split-router/


2021년 8월 6일 금요일

golang : interface 로 전달받은 pointer 가 가르키는 type 을 찾기

reflect.Indirect 를 활용하면, interface 로 전달된 인자가 pointer인 경우, 그 pointer가 가르키는 실제 type 에 대한 정보를 알수 있다. 여러 type을 전달받는 공통 함수 등을 작성할때 유용한 tip

package main

import (
    "fmt"
    "reflect"
)

func testFunc(value interface{}) {
    fmt.Println("---------------------")
    fmt.Println("type = " + reflect.ValueOf(value).Type().String())
    fmt.Println("kind = " + reflect.ValueOf(value).Kind().String())
    if reflect.ValueOf(value).Kind()==reflect.Ptr {
	fmt.Println("--> pointer " )
	pointsToValue := reflect.Indirect( reflect.ValueOf(value))
	fmt.Println("-->",pointsToValue.Kind(), 
	    " - ",pointsToValue.Type(), " - ", pointsToValue)
	if pointsToValue.Kind()==reflect.Slice {
	    fmt.Println("--> slice !! " )
        }
    }
}

func main() {
    var testVar1 string
    var testVar2 []string
    var testVar3 []*string 
    
    testVar2 = append(testVar2,"A")
    testVar2 = append(testVar2,"B"
 
    testFunc(testVar1)
    testFunc(&testVar1)
    testFunc(testVar2)
    testFunc(&testVar2)
    testFunc(testVar3)
    testFunc(&testVar3)
}

 

https://play.golang.org/p/1PEOYIPdyFb


2021년 5월 29일 토요일

macbook pro 2012 mid LCD replacement (맥북 액정 교체기)

지금 사용중인 맥북 프로가 몇달전에 갑자기 화면에 세로줄들이 발생했다. 외부 디스플레이는 문제 없는 상태라서 로직 보드 문제는 아닌거 같다. 새로 살 필요까지는 없는거 같아서 맥북 수명 연장에 좀 투자 하기로 했다.

2021년 5월 1일 토요일

맥북 배터리 스로틀링

 

macbook pro 2012 mid 의 배터리를 교체하기 위해 제거하고, 지금 전원 어댑터만 연결해서 사용을 해보니 심각한 속도 저하가 발생하고 있다. 그냥 내 느낌인가 싶었는데 찾아보니,.. 정말로 맥북은 배터리가 없으면 cpu, gpu 쓰로틀링이 강제로 걸려서 체감 속도가 확 떨어진다고 한다. 전원 만으로는 감당 안되게 하드웨어 구조가 되있어서 부하가 걸리는 작업에는 배터리 + 전원이 같이 동작해야만 속도 저하가 안 일어 난다고 하니... 참 이게 뭔 말도 안되는 상황인지 모르겠다.. 애플이 배터리 장사할려고 이런식인지.. 윈도우 랩탑에서도 이런 문제가 있는지 모르겠지만 황당해서 남겨본다.

2021년 4월 27일 화요일

Go 1.16 에서 $GOPATH/src 에서 코드 작성하고 사용하기

Go 1.16 버전 부터는 기본적으로 module 을 사용하게 변경 되었다. 덕분에 GOPATH  와 상관없이 아무 위치에서든 자신의 소스파일을 작성하면 된다.  그리고 모듈을 사용하기 위한 go.mod 파일이 반드시 필요하게 되었다.  하지만 1.16 버전에서도 선택적으로 module 사용을 할지 말지 여부를 결정 할 수 있다. 예를 들어 기존 프로젝트 구조가 GOPATH 내 src 를 사용하는 경우등이 해당될수 있다.

2021년 4월 25일 일요일

go module과 package 관계, 그리고 module path 개념 정리

go 의 기본적인 개념 중에서 모듈, package 그리고 모듈 경로에 대해 알아본다. 처음에 개인적으로 많이 헷갈렸던 부분이라서 정리해 본다. 지금 우리가 go 로 어떤 프로젝트를 수행한다고 가정해 보면, 다음처럼 정리 할 수 있겠다. 

  • 이 프로젝트는 여러개의 모듈을 가질수 있다.
  • 각 모듈에는 여러개의 package들이 존재할수 있다.
  • 각 package 들은 1개 이상의 go 소스파일로 구성된다.
  • 모듈내의 각 package 들은 자신의 package 폴더를 go mod init 으로 지정한 모듈 경로 + 폴더로 만들면 된다. 
  • 패키지명은 (반드시) 경로의 마지막 문자열로 해준다.
  • 개발중인 모듈은 반드시 원격 저장소에 배포될 필요가 없다.
  • 로컬 개발환경에서 동시에 여러 모듈을 개발중이고, A모듈이 B모듈을 사용해야 한다면, B모듈의 경로를 개발 중인 로컬 경로로 변경하는 작업이 필요하다.(이건 예전 상황이고.. go 1.18 부터는 그냥 workspace 를 사용하면 됨)

위 내용들을 하나씩 살펴보자. (go 1.16 기준으로 작성됨)

2021년 4월 24일 토요일

go 에서 gRPC-Gateway 사용하기

이번에는 go 에서 gRPC-Gateway 를 사용하는 방법에 대해 알아보려 한다. 

최종 코드는 다음에서 확인 가능 : https://github.com/jeremyko/grpc-gateway-sample

앞서 살펴본 go 에서 proto buffer 사용하기 와 거의 비슷한 절차이나 gRPC-Gateway 사용을 위해 추가되는 절차가 있다. 다음 내용을 기초로 작성되었다 (그대로 따라 했더니 에러가 발생되어, 최신 go 버전에 맞게 내용이 추가된 부분이 있다. go 1.16 버전 기준).

https://grpc-ecosystem.github.io/grpc-gateway/docs/tutorials/introduction/

필요한 패키지 다운로드

go get google.golang.org/grpc
go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go get google.golang.org/protobuf/cmd/protoc-gen-go
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc

2021년 4월 22일 목요일

go 에서 proto buffer 사용하기

1. proto buffer 를 정의
2. go 로 변환하여 모듈을 만들고
3. 이 모듈을 로컬에서 호출해서 사용 하는 간단한 예제를 정리해 본다 (go 1.16 버전을 기준)

최종 코드는 다음을 참고 : https://github.com/jeremyko/go-proto-buffer-sample

2021년 4월 15일 목요일

flutter : push-up mania

flutter 를 사용한 모바일 크로스 플랫폼 앱 개발 예제. 

https://play.google.com/store/apps/details?id=com.jeremyko.pui

뭘 일단 만들어볼까 하다가, 한 10년 전에 ios 앱으로 만들었던 푸쉬업 카운터를 또 만들어 봤음.

 


 

2021년 4월 3일 토요일

flutter : using mixed null safety for legacy packages

null safety 가 없는 기존 package 들을 최신 flutter, dart 개발 환경에서 사용하기.

flutter 프로젝트 내에서 dart 버전을 소스파일 단위로 다르게 지정하여 오래된 package 들도 null safety 에러가 안나게 개발할수 있다.  

2021년 3월 19일 금요일

golang module 작성, 타 모듈에서 로컬 테스트 및 배포 개념 정리

2022-03-24 update

go 1.18부터 도입된 workspace 기능을 사용하면 mod replace 를 대체 가능하다 

https://jeremyko.blogspot.com/2022/03/golang-118-workspace-mode.html

 

 

golang 모듈을 만들고 타 모듈에서 사용하는 것을 한번 정리해보았다.
내가 만들려고 하는 모듈이
github.com/jeremyko/my_mod 이며, 모듈 폴더는 ~/mydev/my_mod 라고 가정한다.