벤포드의 법칙이란걸 접했다. 상당히 흥미가 갔다. 내가 하는 업무가 빅데이터를 다루기도 하고… 데이터 검증을 해야 하기도 하니….상당히 흥미가 갔다.
도입부 설명이 아래와 같았다.
1~100만의 숫자중 랜덤으로 100만번 선택했을 경우 골라진 숫자의 맨 첫자리 숫자가 1일 확률이 가장 높고 그다음이 2.. 3…
이게 실제로 적용되는지 스크립트로 짜서 돌려봤다. 

굉장히 신기했다. 이게 말이 돼 ? 랜덤으로 뽑는건데 ? 실제로 적용되는지 궁금했다.

 

 

-MacBookPro benford % cat sss.sh

#!/bin/sh

 

num=1

 

while [ $num -le 1000000 ]

do

random_num="$(($RANDOM% 9999+1))"

first_num="${random_num:0:1}"

echo "$first_num" >> 123123.txt

((num++))

done

 

랜덤함수가 32767 까지밖에 안나오니 1부터 9999까지 랜덤으로 뽑도록 해보고… 결과는 아래와 같다.

 

MacBookPro benford % cat 123123.txt | sort | uniq -c

135337 1

128771 2

105152 3

105292 4

105207 5

105114 6

105024 7

105305 8

104798 9

1이랑 2가 많긴 하지만…이건 벤포드의 법칙보다는 내가 뭔가 간과한 부분이 있는것같다. 어쨌든 벤포드의 법칙을 설명할 때 적잖은 유튜버, 블로거들이 했던 설명인"1~100만의 숫자중 랜덤으로 100만번 선택했을 경우 골라진 숫자의 맨 첫자리 숫자가 1일 확률이 가장 높고" 은 잘못된 예제같다. 일단 패스.

 

벤포드의 법칙이 적용되려면 광범위한 데이터여야 하고 비선형의구조를 보이는? 데이터여야 한다고 한다.(정확히 이해한건지 모르겠다..)
그럼 진짜로 이게 실 데이터에 적용되는지… 실제 회사내의 데이터를 가지고 확인해보았다.

약 200 개 앱(게임)들의 365일간의 일일 매출들. 즉 약 7만개(200개 앱 * 365일)데이터가 벤포드 법칙에 적용이 되는지 확인해보았다.

 

결과는

 

MacBookPro benford % awk '{print $2}' benford.txt| sort | uniq -c

14610 1 (33프로) 

8585 2 (18프로) 

4893 3 (10프로) 

4447 4 (9.6프로) 

3479 5 (7.5프로) 

3013 6 (6.5프로)

2116 7 (4.6프로)

1870 8 (4프로)

2002 9 (4.3프로)

null값이나 오입력된 값(0 입력)등도 있어서 퍼센티지가 100이 되진 않는다.

 

이정도면 상당히 적용된다고 볼수 있다. 신기하다… 근데 9로 시작하는게 많네… 벤포드 법칙에 따르면 9로 시작하는 값들중 오입력된 값들이 많다는 뜻이겠다. 또한 1로 시작하는게 실제 벤포드의 법칙보다는 수치가 살짝 높고 그렇다. 

9로 시작하는 값들을 먼저 봐볼까..

MacBookPro benford % cat benford.txt| awk '{ if ($2==9) print $1}' |  sort -n | uniq -c  | sort -rn | more
 189 9.99
 135 9.98
  28 9.97
  25 9.95
  11 9.96
   6 9.9
   6 9.2161
   4 9.94
   4 9.59

 

9.99 가 굉장히 수상하다.

 

        "d250": 9.99,
        "d251": 1.99,
        "d252": 15.99,
        "d253": null,
        "d254": 4.99,
        "d255": 4.99,
        "d256": 9.99,
        "d257": null,
        "d258": 3.98,
        "d259": 9.99,
        "d260": 8.98,
        "d261": 19.97,
        "d262": 1.99,
        "d263": 14.97,
        "d264": 9.99,

 

위와같이 1.99 2.99 9.99 등 오입력된 값들이 많음을 실제로도 볼 수 있었다. 왜 오입력이 됐는지는 개발자들에게 문의를 해야할것이고 ... 매출이 n.99 가 나올 가능성이 얼마 안될 듯 한데... 저것들 다 오입력된것같다. 그중 1.99나 2.99 등은 워낙 분포가 많으니 티가 안났겠지만 9의 경우 분포가 작으니 이렇게 티가 나는듯 ? 

여튼 데이터가 잘못된것을 찾아냈다. 상당히 유의미하다. 
처음 접했을땐 말이되나 ? 신기하다. 였는데  벤포드의 법칙에 대해서 위키등 설명을 더 자세히 읽어보니 이런 데이터가 나오는게 수긍이간다. 1 > 2로 가려면 2배 2 > 3은 1.5배 3 > 4는 1.3배....  점점 진입하기가 쉬워지기 때문이다.

 

흠..이걸 실제 데이터 검증에 쓸 수 있는 방법은 없을까 ? 서버 파일들의 용량을 점검한다면 ?

 

#!/bin/sh
ls -latr /bin/ | grep -v lrwx | awk '{print $5}' > /root/sss.txt
num=`cat /root/sss.txt`
for i in $num; do
first_num="${i:0:1}"
echo "$i $first_num" >> benford1.txt
done
awk '{print $2}' benford1.txt | sort | uniq -c

 

 

위와 같이 /bin/ 디렉토리내 파일들의 용량도 벤포드의 법칙이 적용된다. 변조여부 확인하는데 참고정도는 할 수 있을지도 ?

'일상 > 기타' 카테고리의 다른 글

ISMS인증 안내서 요약  (0) 2021.04.27

고객 요청에 의한 단일노드 설치나 테스트로 CRUD까지만 해봤는데 이번에 실무에서 처음으로 mongodb 구축 및 관리를 진행하게 됐다.
따라서 SE 관점에서 구성전 알아야 할 것, 설치방법, 백업&모니터링등 관리 노하우, 장애 대처법정도 메뉴얼로 정리해본다.

 

상황
GCP firebase realtimeDB 를 사용하고 있었는데 월 천만원정도 나오던게 월 2천만원이 발생하였다. firebase의 경우 데이터를 쓰는데는 금액이 무료(저장공간에 대한 비용은 발생)지만 다운로드 한 크기(즉 쿼리가 실행에 대한 응답, read)에 대해 비용이 발생한다. 따라서 수시로 데이터를 read 해야 한다면 ? (예를들어 실시간으로 랭킹이 바뀌는.) 비용이 어마어마하게 나올것이다.(나왔다.)

gcp firebase realtimedb price

비용에 대한 압박때문에 개발자가 맘편히 개발을 못하는 환경은 좋지 못하다고 판단하여 realtimeDB를 사내 IDC에 자체 구축한 DB로 옮기기로 하였고 그에 따라 mongodb를 구축하기로 하였다. nosql 인지도 1등, 기존에 사용하기도 했었기에.

 

 

구축전 알아야 할 것
1. mysql / mongodb 용어 차이


2.스키마 설계시 고려사항 - 우리는 설치까지만하고 이후부터는 개발자가 하겠지만 그래도 알면 나쁠거 없으니 쓰윽 읽어보면 좋을듯

1.도큐먼트의 최대 크기는 16MB

2.쿼리 및 쓰기의 접근 패턴
가장 일반적인(빈도가 가장 많은)쿼리와 함께 쿼리되는 데이터가 동일한 도큐먼트에 저장되도록 설계하고 이러한 쿼리(앞서 말한 일반적인 쿼리)에 사용되지 않는 데이터나 자주 사용하지 않는 데이터는 다른 컬렉션에 넣자.
동적(읽기/쓰기)-정적(대부분 읽기)데이터 분리 여부도 고려

3.cardinality
도큐먼트와 데이터의 관계가 one to (few,many,squilions) 을 고려 - https://m.blog.naver.com/heops79/221649719470 참고 

4.스키마 설계 패턴 - 개발자에게 패턴을 추천해주면 좋을듯
다형성 패턴 - 
속성 패턴 - 
버킷 패턴 - 
이상치 패턴 - 
계산된 패턴 - 
서브셋 패턴 - 
확장된 참조 패턴 - 
근사 패턴 - 
트리 패턴 - 
사전 할당 패턴 - 
도큐먼트 버전 관리 패턴 - 

5.정규화 vs 비정규화 
일반적으로 정규화(데이터를 여러 컬렉션에)는 쓰기가 빠르고 비정규화(모든 데이터를 하나의 도큐먼트에)는 읽기가 빠르다.

6.오래된 데이터 제거
제한 컬렉션 사용 - 오래된 데이터가 밀려나는 방식, 급격히 증가하는 트래픽에 안좋음
TTL 컬레션 사용 - 294페이지
주기마다 컬렉션 삭제 - 여러개의 컬렉션을 사용(rotate 방식이라 생각하면될듯) - 컬렉션네임을 동적으로 사용ㅎ애 여러 데이터베이스를 조회하기에 구축하기에 복잡
7.데이터베이스와 컬렉션 설계시 고려사항
- 스키마가 유사한 도큐먼트는 같은 컬렉션에

 

 

 

 

이제부터가 se 영역

mongodb 구성은 보통 3가지로 진행한다.
단일 - 테스트용도

replica set - 일반적으로 사용됨
샤딩 - 대용량 고사양 필요시

 

여기서는 replica set을 구성했고 각각 다른 3개의 서버에 각각의 mongodb 컨테이너를 실행해서 프라이머리(P)세컨(S)세컨(S)pss 방식으로 리플리카셋 구성(하나의 서버에 컨테이너 실행할때도 동일하게 하되 바인딩포트만 바꾸면됨)

 

 

1.각각의 서버에 mongodb 실행

compose.yaml 파일 내용

version: "3"
services:
  devmongo.test.co.kr:
    image: docker.bitmango.com/mongodb.test.co.kr:2021_10_5
    restart: always
    container_name: devmongo.test.co.kr
    ports:
      - "28017:27017"
    volumes:
      - ./data/db:/data/db
    entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "replication", "-f", "/etc/mongod.conf", "--journal", "--dbpath", "/data/db", "--enableMajorityReadConcern", "false" ]

 

 

이미지 안에는 mongodb 4점대 latest기본 이미지 파일에 

관리자계정 생성한다음 (생성하느건 구글링 많음)

 


[root@db1 mongore.datawave.co.kr]# cat mongod.conf
# mongod.conf
security:
  keyFile: "/etc/mongodb.key"
  clusterAuthMode: "keyFile"
  authorization: "enabled"


/etc/mongodb.key 파일 들어가있고 key파일 들어가있는걸 컨테이너 커밋한거고 생성하는건 아래처럼

openssl rand -base64 756 > /etc/mongodb.key
chmod 400 /etc/mongodb.key

출처: https://appledog.tistory.com/entry/MongoDB-Replica-Set-설정 [김군이다 (머리가 나쁘면 적어!)]

 

 

 

2.리플리카셋 구성 

한서버에서만 아래 입력(아마 입력하는곳이 프라이머리가 되는것같음?)

> var config = {
... _id: "replication",
... members: [
... {_id: 0, host: "db1.test.co.kr:28017"},
... {_id: 1, host: "db2.test.co.kr:28017"},
... {_id: 2, host: "db3.test.co.kr:28017"}
... ]
... };

 

이러면 리플리카셋 구성 끝.

 

3. 실제 사용자에게 제공할 유저&디비 생성하기
replication:PRIMARY> use 2222222
replication:PRIMARY> db.createUser({ user: "2222222", pwd:"1111111", roles: ["readWrite"]})

위처럼 생성할 디비 를 use 디비명 해주고 거기서 createUser 해주면 됩니다.


접속은

mongodb://222222:*****@db1.test.co.kr,db2.test.co.kr,db3.test.co.kr:28017/?authSource=222222&replicaSet=replication&readPreference=nearest&appname=MongoDB%20Compass&ssl=false

위와같이...

이중에 readPreference 옵션은(https://rastalion.me/mongodb-replica-set-%EC%84%B8%EB%B6%80-%EC%84%A4%EC%A0%95%EA%B0%92-%EC%A1%B0%EC%A0%95%ED%95%98%EA%B8%B0/참고)

  • primary: 기본값이며, Primary 구성원으로부터 값을 읽고 오며, 딜레이 없이 데이터 수정 및 삽입 작업이 가능합니다.
  • primaryPreferred: Primary 구성원으로부터 우선적으로 데이터를 읽어옵니다. 특별히 Primary 쪽의 읽기 작업이 밀려있지 않으면 Primaey에서 데이터를 가져오기 때문에 변경사항을 바로 확인 할 수 있습니다. 읽기가 밀려 있는 상태라면 Secondary에서 데이터를 읽어옵니다.
  • secondary: 모든 읽기 작업을 Secondary 에서 처리합니다.
  • secondaryPreferred: 우선적으로 읽기 작업이 발생하면 Secondary에 작업을 요청합니다. 하지만 모든 Secondary에서 작업이 밀려 있는 경우 Primary에 읽기 작업을 요청합니다.
  • nearest: 해당 구성원이 Primary인지 Secondary인지에 관계없이 네트워크 대기 시간이 가장 짧은 복제본 세트의 구성원에서 읽기 작업을 합니다.




  •  
  •  
    mongo "mongodb://mongodb0.example.com.local:27017,mongodb1.example.com.local:27017,mongodb2.example.com.local:27017/?replicaSet=replA&ssl=true"

 

 

 

자주 사용하는 명령어
rs.conf() - rs설정 확인
rs.isMaster() - rs 프라이머리 확인
use dbname
db.createCollection("[COLLECTION_NAME]") - collection 생성
rs.slaveOk() - slave 에서 쿼리하고싶을때
db.getUsers() - DB에 연결된 유저 리스트 확인

db.createUser({ user: "USERNAME", pwd: "PASSWORD", roles: [ "readWrite" ]})

db.auth("아이디", "패스워드")

 

빌트인돼있는 주요 디비 권한들

read

readWrite

 

 

 

 

참고 책
몽고디비 완벽가이드3판-크리스티나초도로

 

참고 사이트
https://edu.goorm.io/learn/lecture/557/%ED%95%9C-%EB%88%88%EC%97%90-%EB%81%9D%EB%82%B4%EB%8A%94-node-js/lesson/174384/mongodb%EB%9E%80

윈도우에서 슬랙 메세지 보내기

 

상황 : 윈도우에 누군가 로그인 할 때마다 슬랙으로 메세지를 받고자 한다.

 

작업스케쥴러에 로그인시 특정프로그램(슬랙메세지프로그램)실행되도록 하면 될듯.

 

작업스케쥴러 설정하는건 구글링하면 많이 나온다. 근데 윈도우에서 슬랙메세지 보내는건 잘 안나온다. 리눅스처럼 curl 명령어로 해봐도 에러가 난다. 그래서 파워쉘모듈중 psslack 이라는 파워쉘-슬랙 모듈을 사용해본다.

 

https://github.com/RamblingCookieMonster/PSSlack

 

GitHub - RamblingCookieMonster/PSSlack: PowerShell module for simple Slack integration

PowerShell module for simple Slack integration. Contribute to RamblingCookieMonster/PSSlack development by creating an account on GitHub.

github.com

 

여기서 import-module psslack 할 때 에러난다.

 

나의 경우는 권한문제로 에러가 발생했고 파워쉘 실행할 때 관리자권한으로 실행해주고

 

execution policy 입력시 결과가 restricted 라면 set execution-policy unrestricted 로 해준 뒤 임폴트-모듈 psslack 하면 잘 된다.

+ Recent posts