* 부작용(side effect)


함수가 결과값 이외에 다른 상태를 변경시킬 때 부작용이 있다고 말한다. 문서에서 side effect에 대해서 부정적으로 봐서는 안된다. 



* 순수 함수

부작용이 없는 함수



* 참조 투명성(referential transparency)


참조 투명성(referential transparency)은 부작용(side effect)이 없음을 표현하는 속성이다. 

입력 값에 대해 항상 같은 값을 돌려주는 것 외에 다른 기능이 없다. 내부적으로 관리되는 변수(상태)에 영향이 없는 것을 말한다. 



참조 투명성에 대한 예제는 다음과 같다.  항상 매개변수를 주면, 그 값을 언제 어디서든 그 값을 기대할 수 있다. 


scala> def sum(x: Int, y: Int): Int = x + y

sum: (x: Int, y: Int)Int


scala> sum(sum(1, 2), 3)

res2: Int = 6


scala> sum(3, 3)

res3: Int = 6





하지만, 변수(상태)값과 의존성이 있는 코드가 있다고 하자. sum 메소드를 호출하면, 계속 값이 변경된다. 이를 참조 투명성이 없다고 말할 수 있다. 

scala> var m = 0
m: Int = 0

scala> def sum(x: Int, y: Int): Int = { m = m + x + y; m}
sum: (x: Int, y: Int)Int

scala> sum(sum(1, 2), 3)
res10: Int = 21

scala>  sum(3, 3)
res11: Int = 27

scala>  sum(3, 3)
res12: Int = 33




sum 메소드는 바로 값을 기억하고 연산에 사용되기 때문에, 순수 함수가 아니고 참조 투명성이 없다. 


함수형 프로그래밍 언어에서는 참조 투명성을 극히 중요하는 것 같아서, 함 정리했다. 





나중에 scalaz의 Task와 Future를 설명하겠지만.. 

scala의 Future는 계산한 후 Future의 결과를 기억하는 반면, 

scalaz(외부 라이브러리)의 Task는 unsafePerformSync를 호출할 때마다 계산을 수행한다. 


다른 말로 말하면, Task는 참조 투명성이고 Future보다는 함수형 프로그래밍 패러다임에 가깝다.





이런 내용을 잘 설명한 내용이 하스켈의 참조 투명성 자료이다. 

https://wiki.haskell.org/Referential_transparency


Posted by '김용환'
,

scala에서 REPL을 사용하려면 간단하게 scala를 실행하면 된다.


$ scala 



그리고, 필요한 내부 라이브러리는 다음처럼 import문을 사용한다.


scala> import scalaz._




만약 외부 라이브러리(lib)를 어떻게 입력해야 하는가?



그러기 위해서는 sbt를 활용할 수 있다. 



sbt 프로젝트에서 sbt를 실행해서 아래처럼 간단하게 사용할 수 있다.  (참고로 sbt는 디렉토리 기반이기 때문에 global 설정이 아니다)


$ sbt



set scalaVersion := "2.11.8"

set libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.2.0"

set initialCommands := ""

set initialCommands += "import scalaz._, Scalaz._, scala.concurrent._, scalaz.concurrent._, java.util.concurrent._"

session save

console



console을 실행하면 다음과 같은 로그가 생성된다. lib을 로딩하고,import 문이 자연스럽게 만들어진다. 


[info]

import scalaz._

import Scalaz._

import scalaz.concurrent._

import java.util.concurrent._

Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).

Type in expressions for evaluation. Or try :help.



실행 환경을 구성한다. 

scalaz.concurrent.Promise는 외부 라이브러리이지만, REPL에서 사용할 수 있다. 

scala> val p = Promise[Int]
p: scala.concurrent.Promise[Int] = List()


scala> p.future.value
res19: Option[scala.util.Try[Int]] = None


scala>  p.success(20)
res20: p.type = Success(20)

scala> p.future.value
res21: Option[scala.util.Try[Int]] = Some(Success(20))





만약 중간에 외부 라이브러리를 읽어야 한다면, Ctrl + D를 누르고,  다시 모드 환경에서 내용을 설정한다.


ctrl + D를 눌러 REPL import문을 다시 구성할 수 있다. 


scala> // 여기서 Ctrl + D


[success] Total time: 371 s...



> set initialCommands := ""

> set initialCommands += "import scalaz._, Scalaz._, scala.concurrent._, scalaz.concurrent._, java.util.concurrent._, java.util.collections._ "





Posted by '김용환'
,

[scala] Array, WrappedArray

scala 2016. 10. 29. 07:52


Array는 변경이 가능하고 값에 인덱스를 가진 컬렉션이다. 


배열은 랜덤 접근에 대해 Vector 대비  실제로 상수 시간의 복잡도를 제공한다. 하지만, Vector에 반해 Array는 메모리의 단일 및 연속 덩어리로 한 번에 할당된다. 그리고, Array는 엘리먼트의 앞과 뒤에 추가할 수 있는 오퍼레이션을 지원하지 않는다. 


scala의 Array는 java Array를 활용한 방식을 사용하고 있다. 그럼에도 불구하고 성능이 좋다. 추가 기능이 없지만, 상황에 따라서 Vector보다 더 좋을 수 있다. 



http://docs.scala-lang.org/overviews/collections/performance-characteristics.html


                             headtailapplyupdateprependappendinsert
ArrayCLCC---



Array에 대한 간단한 예시이다. 



var crew = Array("John","Samuel","Matt")
crew(0) = "Juno"
for (c <- crew) {
print(c + " ")
}
println()

Predef
var student = new Array[String](5)
student = crew
for (s <- student) {
print(s + " ")
}
println



결과는 다음과 같다.


Juno Samuel Matt 

Juno Samuel Matt 






특이할 점은 Array는 implicit을 잘 활용한다. Array와 WrappedArray가 되었다. 



scala> val a = Array(1, 2, 3, 4, 5)

a: Array[Int] = Array(1, 2, 3, 4, 5)


scala> val b:Seq[Int] = a

b: Seq[Int] = WrappedArray(1, 2, 3, 4, 5)



WrappedArray는 Array로 돌릴 수 있다. 


scala> val c = b.toArray

c: Array[Int] = Array(1, 2, 3, 4, 5)



그리고, 처음 배열과 비교해 본다. 동일한 값이다! 


scala> a==c

res3: Boolean = true





이제 Array.reverse 메소드를 적용해보자. Array는 reverse 되어도 Array타입이 되고, 6을 추가할 수 있다. 


scala> a.reverse

res4: Array[Int] = Array(5, 4, 3, 2, 1)


scala> a :+ 6

res5: Array[Int] = Array(1, 2, 3, 4, 5, 6)



WrappedArray.reverse 메소드를 적용하자. WrappedArray를 reverse하면 WrappedArray 타입이 되는데, 6을 추가할 수 있다. 하지만, 타입이 ArrayBuffer로 바뀌었다. ( Seq임을 잘 살펴본다)



scala> b.reverse

res6: Seq[Int] = WrappedArray(5, 4, 3, 2, 1)


scala> b :+ 6

res7: Seq[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)



implicit이 발생한 것이다. 




WrappedArray의 선언을 살펴보자.


*  A class representing `Array[T]`.
*
* @tparam T type of the elements in this wrapped array.
*

abstract class WrappedArray[T]
extends AbstractSeq[T]
with IndexedSeq[T]
with ArrayLike[T, WrappedArray[T]]
with CustomParallelizable[T, ParArray[T]]
..




Predef 에 보면, Array에 대한 implicit 함수가 있는 것이 눈에 보인다..

implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = {
if (xs eq null) null
else if (xs.length == 0) WrappedArray.empty[T]
else new WrappedArray.ofRef[T](xs)
}

implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null
implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null
implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null
implicit def wrapFloatArray(xs: Array[Float]): WrappedArray[Float] = if (xs ne null) new WrappedArray.ofFloat(xs) else null
implicit def wrapCharArray(xs: Array[Char]): WrappedArray[Char] = if (xs ne null) new WrappedArray.ofChar(xs) else null
implicit def wrapByteArray(xs: Array[Byte]): WrappedArray[Byte] = if (xs ne null) new WrappedArray.ofByte(xs) else null
implicit def wrapShortArray(xs: Array[Short]): WrappedArray[Short] = if (xs ne null) new WrappedArray.ofShort(xs) else null
implicit def wrapBooleanArray(xs: Array[Boolean]): WrappedArray[Boolean] = if (xs ne null) new WrappedArray.ofBoolean(xs) else null
implicit def wrapUnitArray(xs: Array[Unit]): WrappedArray[Unit] = if (xs ne null) new WrappedArray.ofUnit(xs) else null





Array를 사용할 때, 다른 스칼라 컬렉션에서 사용 가능한 대부분의 메소드를 사용할 수 있다. 


implicit 변환은 Array을 ArrayOps와 WrappedArray를 확대하는데 사용된다. ArrayOps은 Array에 대한 간단한 래퍼 클래스이다. 


ArrayOps는 임시로 Array에 인덱스를 가진 순서 집합에서 찾을 수 있는 모든 오퍼레이션을 사용할 수 있게 해주는 간단한 Array 래퍼 클래스이다. 


ArrayOps의 메소드를 호출하면 Array를 리턴한다. 









Posted by '김용환'
,

[scala] Vector

scala 2016. 10. 28. 17:54



Java의 Vector와 달리 Scala의 Vector의 오퍼레이션은 거의 상수 시간대의 성능이 나올 정도로 훌륭하다. (정확히 말하면 효율적 상수 시간이다)


http://docs.scala-lang.org/overviews/collections/performance-characteristics.html



                        headtailapplyupdateprependappendinsert
VectoreCeCeCeCeCeC-



Vector는 Immutable 컬렉션이고, 트라이(https://en.wikipedia.org/wiki/Trie)라 부르는 순서가 있는 트리 데이터 구조로 구현되어 있다. 트라이에서, 키는 Vector에 저장된 값의 인덱스이다.




Vector의 구현은 패리티(parity) 32의 트리 구조이다. 각 노드는 32개의 배열로 구현되고, 


자식 노드 참조를 32개까지 저장하거나, 32개까지 값을 저장할 수 있다. 


* 주석을 보면, 다음과 같이 설명되어 있다. 

It is backed by a little
* endian bit-mapped vector trie with a branching factor of 32.


32진 트리 구조는 Vector의 복잡도가 왜 "상수 시간" 대신 "효율적 상수 시간"인지 설명한다. Vector의 실제 복잡도는  log(32, N)이며, N은 벡터의 크기를 말한다. 이는 사실 상 상수 시간과 매우 근접하다고 말할 수 있다


Vector는 메모리가 32개의 엘리먼트 청크(chunk)로 할당되기 때문에 매우 큰 순서 집합을 저장하기에 좋은 선택이다. 


해당 청크는 트리의 모든 레벨로 미리 할당하지 않으며 필요할 때마다 할당된다.



간단한 테스트 코드이다.

val vectorEmpty = scala.collection.immutable.Vector.empty
val v = vectorEmpty :+ 1 :+ 2 :+ 3
println(v)
println(v(2))


결과는 다음과 같다.


Vector(1, 2, 3)

3



val is = collection.immutable.IndexedSeq(1, 2, 3)
// scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3)
val v2 = is :+ 4 :+ 5
println(v2)
println(v2(4))


결과는 다음과 같다.


Vector(1, 2, 3, 4, 5)

5




Vector의 2번째 엘리먼트를 구하는 함수는 다음과 같이 개발할 수 있다. 

def returnSecondElement[A](vector: Vector[A]): Option[A] = vector match {
case _ +: x +: _ => Some(x)
case _ => None
}
println(returnSecondElement(v))


결과는 Some(2)이다.








좀 더 내용을 살펴본다.

:+의 구현은 다음과 같다. 커리된 함수와 암시가 쓰였다. 


override def :+[B >: A, That](elem: B) (implicit bf: CanBuildFrom[Vector[A], B, That]): That =
if (isDefaultCBF(bf))
appendBack(elem).asInstanceOf[That]
else super.:+(elem)(bf)




appendBack 함수를 들어가보면, 32진 트리 구조임을 드러나는 코드(31 and 연산)이 나온다. 



또한 Vector를 새로 만들어서 리턴하고 있음을 보여준다. Vector는 Immutable이다. 

  private[immutable] def appendBack[B>:A](value: B): Vector[B] = {
// //println("------- append " + value)
// debug()
if (endIndex != startIndex) {
val blockIndex = endIndex & ~31
val lo = endIndex & 31

if (endIndex != blockIndex) {
//println("will make writable block (from "+focus+") at: " + blockIndex)
val s = new Vector(startIndex, endIndex + 1, blockIndex)
s.initFrom(this)
s.dirty = dirty
s.gotoPosWritable(focus, blockIndex, focus ^ blockIndex)
s.display0(lo) = value.asInstanceOf[AnyRef]
s
} ....


Posted by '김용환'
,

zeppelin 과 spark 연동

scala 2016. 10. 28. 14:32

IPython(노트북)과 R Studio의 큰 장점을 알기 때문에 Spark과 zeppelin을 연동했다


* Hive 연동 완료

http://knight76.tistory.com/entry/apache-zepplin-062-%EC%84%A4%EC%B9%98-hive-R-%EC%97%B0%EB%8F%99




Legacy Spark 연동할 수 있도록 수정한다. 제플린의 용도는 이문수님이 Spark 써밋에서 발표한 내용을 참고한다.





데몬을 실행하면, 2개의 데몬이 실행됨을 볼 수 있다. 하나는 zeppelin 이고, 하나는 spark 이다. 따라서 간단한 spark 코드를 실행할 수 있다. 기본 내장이다. 


$ ./bin/zeppelin-daemon.sh start 


 /usr/java/default/bin/java..... org.apache.zeppelin.server.ZeppelinServer

/usr/java/default/bin/java -cp ... /usr/local/zeppelin/interpreter/spark/zeppelin-spark_2.11-0.6.2.jar 







Legacy Hadoop과 연동할 수 있도록 Spark 를 구성한다. 


현재 zepplelin은 cpu 코어를 min, max 이렇게 사용하는 구조가 아니기 때문에(dedicate),  따로 zeppelin용 spark을 구성했다. (1대의 Driver와 4대의 executor를 설치) spark에서 hadoop에 접근할 수 있도록 hadoop 설정 정보를 포함시킨다. 


dirver의 8080 페이지로 접속해서 정상적으로 동작하는지 확인한다. 



 1.6.2 Spark Master at spark://master:7077



이제 zeppelin만 잘 설정하면 된다. 참고로 zeppelin의 conf/zeppelin-site.xml에 보면, spark 인터프리터가 존재한다.


<property>

  <name>zeppelin.interpreters</name>

  <value>org.apache.zeppelin.spark.SparkInterpreter,org.apache.zeppelin.spark.PySparkInterpreter,org.apache.zeppelin.rinterpreter.RRepl,org.apache.zeppelin.rinterpreter.KnitR,org.apache.zeppelin.spark.SparkRInterpreter,org.apache.zeppelin.spark.SparkSqlInterpreter,org.apache.zeppelin.spark.DepInterpreter,org.apache.zeppelin.markdown.Markdown,org.apache.zeppelin.angular.AngularInterpreter,org.apache.zeppelin.shell.ShellInterpreter,org.apache.zeppelin.file.HDFSFileInterpreter,org.apache.zeppelin.flink.FlinkInterpreter,,org.apache.zeppelin.python.PythonInterpreter,org.apache.zeppelin.lens.LensInterpreter,org.apache.zeppelin.ignite.IgniteInterpreter,org.apache.zeppelin.ignite.IgniteSqlInterpreter,org.apache.zeppelin.cassandra.CassandraInterpreter,org.apache.zeppelin.geode.GeodeOqlInterpreter,org.apache.zeppelin.postgresql.PostgreSqlInterpreter,org.apache.zeppelin.jdbc.JDBCInterpreter,org.apache.zeppelin.kylin.KylinInterpreter,org.apache.zeppelin.elasticsearch.ElasticsearchInterpreter,org.apache.zeppelin.scalding.ScaldingInterpreter,org.apache.zeppelin.alluxio.AlluxioInterpreter,org.apache.zeppelin.hbase.HbaseInterpreter,org.apache.zeppelin.livy.LivySparkInterpreter,org.apache.zeppelin.livy.LivyPySparkInterpreter,org.apache.zeppelin.livy.LivySparkRInterpreter,org.apache.zeppelin.livy.LivySparkSQLInterpreter,org.apache.zeppelin.bigquery.BigQueryInterpreter</value>

  <description>Comma separated interpreter configurations. First interpreter become a default</description>

</property>

..




conf/interpeter.json에서 spark.cores.max와 spark.executor.memory 잘 설정한다. 그냥 두면 기본 값을 사용하니. 병목이 발생할 수 있다. 관련 내용은 https://zeppelin.apache.org/docs/latest/interpreter/spark.html에 있으니 참조한다.



      "id": "2C1FUYTWJ",

      "name": "spark",

      "group": "spark",

      "properties": {

        "spark.executor.memory": "",

        "args": "",

        "zeppelin.spark.printREPLOutput": "true",

        "spark.cores.max": "32",




bin/common.sh에서 일부 수정해서 메모리 이슈가 없도록 수정한다. 


if [[ -z "${ZEPPELIN_MEM}" ]]; then

  export ZEPPELIN_MEM="-Xms3024m -Xmx5024m -XX:MaxPermSize=512m"

fi


if [[ -z "${ZEPPELIN_INTP_MEM}" ]]; then

  export ZEPPELIN_INTP_MEM="-Xms3024m -Xmx5024m -XX:MaxPermSize=512m"

fi




배시 환경에 따라 .bashrc에 다음을 추가한다.


export http_proxy=

export SPARK_HOME=





마지막으로 재시작한다. 


$ ./bin/zeppelin-daemon.sh restart 




노트 하나를 만들어 spark 코드가 잘 동작되는지 확인한다.


val textFile = sc.textFile("hdfs:///google/log/2016/10/23/00/*")
val count = textFile.count();
println(count)





노트북 관련 좋은 데모를 소개한다.


https://github.com/uosdmlab/playdata-zeppelin-notebook

Posted by '김용환'
,



스칼라 언어가 sugar syntax가 많이 있는 반면, Option에 대한 에러 처리 부분은 친절하지 않다. Option은 Some과 None만 있는 ADT이지 Throwable이나 Exception와 값을 갖지 못한다. 


따라서 scalaz의 Either 라이브러리(Either[Exception, Int])  또는 disjunction(Exception \/ Int) 라이브러리를 살펴봐야 한다. 


(나중에 공부해야지)


http://eed3si9n.com/learning-scalaz/Either.html



(참고) http://danielwestheide.com/blog/2013/01/02/the-neophytes-guide-to-scala-part-7-the-either-type.html

import scala.util.control.Exception.catching def handling[Ex <: Throwable, T](exType: Class[Ex])(block: => T): Either[Ex, T] = catching(exType).either(block).asInstanceOf[Either[Ex, T]]



http://appliedscala.com/blog/2016/scalaz-disjunctions


def queryNextNumber: Exception \/ Long = { val source = Math.round(Math.random * 100) if (source <= 60) \/.right(source) else \/.left(new Exception("The generated number is too big!")) }

'scala' 카테고리의 다른 글

[scala] Vector  (0) 2016.10.28
zeppelin 과 spark 연동  (0) 2016.10.28
List에 적용하는 for yield 예시 2  (0) 2016.10.24
[scala] 정수의 산술 연산시 IllegalFormatConversionException 발생  (0) 2016.10.19
[scala] 특이한 Iterator  (0) 2016.10.19
Posted by '김용환'
,




너무나도 당연한 했던 생명, 생명이 사라지자 벌어지는 일들을 영화화했다. 


롱 테이크 신이 꼭 게임과 같은 느낌이 들었다. 








<좋은 대사>


(아이의 울음소리에 다들 반응한다)


Cease Fire!!

(정적)






아기와 함께 있어, 떨어지지 마. 무슨 일이 있든, 사람들이 뭐라든 함께 있어.



아기들 모습을 잊어버렸어.정말 아름다워.정말 조그맣고

'영화를 보고' 카테고리의 다른 글

[더스토리] 영화의 기억나는 대사  (0) 2018.06.26
레디 플레이어 원  (0) 2018.04.04
[마이크롭 앤 가솔린]  (0) 2016.07.02
주먹왕 랄프  (0) 2016.03.18
세기의 매치  (0) 2016.03.04
Posted by '김용환'
,

hadoop client 설치 URL

hadoop 2016. 10. 24. 19:11



cloudera 5.5.1의 hadoop 2.6.0 버전을 설치하고 싶다면, 아래 싸이트에 접속해서

hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64.rpm를 다운로드한 후 설치한다. 



https://archive.cloudera.com/cdh5/redhat/6/x86_64/cdh/5.5.1/RPMS/x86_64/ 





막상 설치하려면, 아래와 같은 에러가 발생한다. 



경고: hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID e8f86acd: NOKEY

오류: Failed dependencies:

bigtop-utils >= 0.7 is needed by hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64

zookeeper >= 3.4.0 is needed by hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64

avro-libs is needed by hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64

parquet is needed by hadoop-2.6.0+cdh5.5.1+924-1.cdh5.5.1.p0.15.el6.x86_64



따라서, RPM을 따라하면 엄청 쉽지 않은 작업이 계속 연결되어 있다 .


한번 제대로 설치한 후, 꼭 tar.gz으로 묶어 들고 공유 디렉토리에 잘 저장해 두어야 한다.. 


Posted by '김용환'
,


for yield 첫번째 예시 다음 공부이다

http://knight76.tistory.com/entry/scala-for-%EB%AC%B8-yield



list에 for yield를 사용한 예시이다.


간단한 for 코드이다. if 문은 for에 존재할 수도 있고, for 문 블럭 안에 존재할 수 있다.

for {
i <- 1 to 4 //1,2,3,4
if i % 2 == 0
} print(i)
println

결과는 24이다.



그런데, 컬렉션(List)라면 상황이 좀 달라진다. 컬렉션으로 비슷하게 코딩하면 에러가 발생한다.


//  에러 : Error:(37, 3) '<-' expected but '}' found.
// for {
// i <- list
// i % 2 == 0
// } println(i)


다음처럼 바꿔야 잘 동작한다.

val list = List(1, 2, 3, 4)
for (i <- list) {
print(i)
}
println

결과는 다음과 같다.


1234




List에 for yield를 간단하게 사용할 수 있다.

print(for (i <- list) yield i * 2)
println

결과는 다음과 같다.


1234




여기에 if문을 추가한 코드이다. if문을 안에 넣을 수 있지만, for 문장에 포함시킬 수 있다.

for (i <- list) {
if (i % 2 == 0) print(i)
}
println

for (i <- list if i % 2 == 0) {
print(i)
}
println


결과는 동일하게 24이다.





for문은 내부적으로 sugar스럽게 사용할 수 있다. 이를 scala's for comprehension(for 내장, 오현석님이 이미 이렇게 번역하셔서;; )이라고 한다. 스칼라 컴파일러가 for 코드를 내부적으로 flatMap 또는 forEach로 변경됨을 의미하는 개념이라 할 수 있다. 



// scala's comprehension
println(for(x <- List(1) ; y <- List(1,2,3)) yield (x,y))
println(List(1).flatMap(x => List(1,2,3).map(y => (x,y))))



결과는 다음과 같다.


List((1,1), (1,2), (1,3))

List((1,1), (1,2), (1,3))




Posted by '김용환'
,



replica 구성한 mongodb(wiredTiger)의 3.2.0을 3.2.10으로 버전업한 내용을 설명한다. (별 내용은 아니지만..)


replica 버그가 의심되는 부분이 있어서 버전업을 진행했다.


관련 내용 : http://knight76.tistory.com/entry/mongodb-32%EC%9D%98-slave%EC%9D%98-recovering-%EC%83%81%ED%83%9C-%EB%B3%B5%EA%B5%AC%ED%95%98%EA%B8%B0




먼저 slave 한대에 서버에 접속해서 shutdown한다. (그냥 kill 하면 pid 파일도 같이 지워야 하니. 이 명령대로 사용하는 것이 좋다.


$mongo


> use admin

>db.shutdownServer({timeoutSecs: 1});




새로운 mongodb를 설치한다. 나는 SSL을 지원하지 않는 linux x386 64 비트 파일(mongodb-linux-x86_64-3.2.10.tgz)를 설치했기 때문에, 3.2.10에 맞춰 다운로드했다.


$ which mongo

/usr/local/mongodb/bin/mongo


$ sudo tar zxvf mongodb-linux-x86_64-3.2.10.tgz


$ sudo chown -R www:www mongodb-linux-x86_64-3.2.10


$ sudo rm mongodb


$ sudo ln -sf mongodb-linux-x86_64-3.2.10 mongodb




이제 데몬을 재실행한다.

설정 파일을 항상 따로 두어야. 업그레이드시 손이 덜 간다.


$ /usr/local/mongodb/bin/mongod -f /etc/mongod.conf


테스트해본다.


$ mongo

MongoDB shell version: 3.2.10

connecting to: test

replset:SECONDARY> rs.status()

..


정상적이다.


이렇게 다른 slave, master에 적용하고, 마지막에 rs.status()로 제대로 동작되는지 확인한다.






참고


https://docs.mongodb.com/manual/reference/command/shutdown/




Posted by '김용환'
,