Redis Persistance


Redis Persistance 특징을 활용해 데이터를  저장하는 방법은 2가지가 존재한다.



RDB Mode 와 AOF Mode





RDB Mode


1) 정의


특정 시점 또는 반복적으로 메모리에 있는 전체 데이터를 디스크에 저장한다.



2) 장점


- 파일크기가 작아 AOF보다 로딩시간이 빠르다.




3) 단점


- 특정 시점에 데이터를 저장함에 따라 이슈 발생 시 데이터가 유실 될 수 있다.

ex)  13시에 데이터를 백업 하고 13시 30분에 장애가 발생하면 13시에서 13시 30분 사이의 데이터는 복구 불가능하다.


- 바이너리 파일로 백업을 제공한다. 





AOF Mode



1) 정의


명령이 실행될 때마다 기록이 저장된다.


2) 장점


- 서버 장애가 발생해도 데이터 유실이 거의 없다.

- 텍스트 파일로 백업을 제공한다. 따라서 손생이 발생해도 쉽게 복구 가능하다.




3) 단점


- 모든 명령이 기록되기 때문에 파일 크기가 커지고, 데이터 로딩이 느려질 수 있으며, OS의 파일크기 제한으로 장애가 발생할 수 있다.

 * Re-write를 통해 최종 데이터만 기록할 수 있고 파일을 크기를 줄 일 수 있다.






우선순위


-  RDB 와 AOF가 둘다 존재할 경우 redis.conf 설정에 따라 읽어들이는 우선순위가 다르다.


"AppendOnly" 가  yes인 경우 AOF 파일을 읽어 온다.

"AppendOnly" 가  no인 경우  RDB 파일을 읽어 온다.




권고사항


안전한 데이터의 보존을 위해선 RDB, AOF 모두 사용할 것을 권고한다.

또한 데이터를 보관하는 저장소가 있다면 스캐쥴을 통해 주기적으로 데이터 보관 스토리지에 데이터를 저장하는 것을 권고한다.








출처:http://ossian.tistory.com/42





'Cloud & NoSQL & Middleware > Redis' 카테고리의 다른 글

Java에서 Redis 연동 테스트 (jedis)  (0) 2018.07.01
MacOS에서 Redis 설치 및 실행  (0) 2018.07.01
Redis 특징 (2) - 지원 데이터 타입  (0) 2018.06.29
Redis 특징  (2) 2018.06.29
레디스(Redis) 란?  (1) 2018.06.29

Redis는 Key & Values로 이루어 진 구조이며, values의 데이터타입은 String, Hashes, Lists, Sets, Sorted Sets 5가지가 있다.




String (문자열 데이터)


- String 값으로 저장 할 뿐 아니라, String의 Binary 데이터도 저장할 수 있다.


Key & Values



Key : user:1:data


value: {

               "id": "user00",

               "name":"kim"

           }





Hashes (해쉬 데이터)


Key & Values



Key : user:1:data


value:  필드 - 값으로 이루어진 해쉬 데이터


필드

 

 id

user00 

 name

kim 



-> 새로운 데이터를 추가할 경우 필드-값의 데이터를 추가하면 된다.

ex) age - 15

 



Lists



Key & Values



Key : user:1:data


value:  요소




요소


user00 - kim


나이가 15인 요소 추가


: user00 - kim - 15






sets


Key & Values



Key : user:1:data


value:  요소



 user00

 kim

 15

 true


요소 추가

 user00

 kim

 15

 true


 korea

 







Sorted sets




Key & Values



Key : user:1:data


value:  가중치 - 값



 가중치

 

 22

 user00

 24

 kim


 

23의 가중치와 15의 값을 갖는 데이터 요소 추가


가중치

 값

 22

 user00

 23

 15

 24

 kim

  







'Cloud & NoSQL & Middleware > Redis' 카테고리의 다른 글

Java에서 Redis 연동 테스트 (jedis)  (0) 2018.07.01
MacOS에서 Redis 설치 및 실행  (0) 2018.07.01
Redis 특징(3) - Redis Persistance  (0) 2018.06.29
Redis 특징  (2) 2018.06.29
레디스(Redis) 란?  (1) 2018.06.29

특징


1. String, lists, sets, hashes, sorted sets  과 같은 자료구조를 지원한다.

2. 디스크가 아닌 메모리 기반의 데이터 저장소이다. 

3. DataBase로도 사용할 수 있고 Cashe로도 사용할 수 있다. (NoSQL & Cashe)

   - 캐쉬로 사용할 경우 저장소 기능을 off해야 함.

4. Redis Sentinel을 통해 높은 가용성을 갖을 수 있고, Redis Cluster를 통해 Master-slave의 클러스터링을 수행할 수 있다. 

5. 성능은 환경에 따라 다르겠지만 초당 2만~10만회 수행할 수 있다.





IMDB(in-memory DB)


메모리 기반 저장소 VS 디스크 기반 저장소


속도                                     >

내구성                                 <





Redis


Remote Dictionary Server 의 약자이며  데이터베이스, 캐시 및 메시지 브로커로 사용되는 오픈소스  메모리 데이터 구조 저장소이다. (in-memory data structure sotre)


Redis는 ANSI C로 작성되었으며 Linux, * BSD, OS X와 ​​같은 대부분의 POSIX 시스템에서 외부 종속성없이 작동한다.


Redis는 페이스북, 인스타그램, 네이버 LINE 서비스, StackOverflow, 블리자드 등 대형 서비스 업체들이 사용자들의 대규모 메세지를 실시간으로 처리하기 위하여 사용하고 있다.


바이트 순서


바이트 순서는 해당하는 OS 시스템이 내부적으로 데이터를 표현하는 방법을 의미한다.

그렇기 때문에 모든 시스템의 데이터 표현방식이 같지 않다.


표현방식에는 2가지 방식이 존재한다.






Little Endian, Big Endian


시스템이 내부적으로 데이터를 처리하는데 Big-Endian을 사용하느냐 Little-endian을 쓰느냐는 시스템의 CPU에 따라 달라진다.

이것을 호스트 바이트 순서라고 한다.



Little Endian 

Big Endian 

 intel x86

 IBM

 AMD

 ARM

 EDC

 Motorola




0x12345678 의 32비트 데이터를 표현



Big Endian : 0x12 0x34 0x56 0x78


낮은 주소 -> 높은 주소




Little Endian : 0x78 0x56 0x34 012


낮은 주소 -> 높은 주소





그렇기 때문에 빅 엔디안을 쓰는 CPU와 리틀엔디안을 사용하는 CPU가 데이터 통신을 하게 되면 문제가 발생할 수 있다.




네트워크 바이트 순서


네트워크 바이트 순서는 Big Endian 방식만을 사용한다.

따라서 Little Endian을 사용하는 경우  Big Endian 방식으로 데이터를 변경해서 전송해야 하며 수신한 데이터에 대해서 역순으로 조합해야 한다.

또한 포트와 주소는 항상 네트워크 바이트 순서 규칙을 사용하여 소켓 함수를 호출 할 때 지정된다.






바이트 순서 전환


h : host byte order

n : network byte order

l : long(32bit)

s : short(16bit)



일반적으로 4byte의 long  타입은 IP 변환에 사용되며, 2byte의 short 타입은 포트 변환에 사용된다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import socket
 
 
host_port = 0x3456
host_ip = 0x12345678
 
network_ip_order = socket.htonl(host_ip)
network_port_order = socket.htons(host_port)
 
print("CPU is Intel")
print("Host %x" %(host_ip))
print("Network Byte Order %x" %(network_ip_order))
print("Port %x" %(host_port))
print("Network Byte Order %x" %(network_port_order))
 
cs



>>CPU is Intel

>>Host 12345678

>>Network Byte Order 78563412

>>Port 3456

>>Network Byte Order 5634








JAVA


자바에서는 기본적으로 부호없는 정수 (Unsigned int)는 존재하지 않으며 정수를 표현할 때 빅 엔디안을 따른다.


그렇기 때문에 다른 플랫폼에서 사용한 데이터의 네트워크 바이트 순서 전환없이 리틀 엔디안의 데이터를 받는다면, 빅 엔디안으로 변경할 필요가 있다.


(애초에 네트워크 바이트 순서의 빅 엔디안으로 사용하는 것이 좋을 것이다.)


1
2
3
4
5
6
7
8
public static int getBigEndian(byte[] v)throws Exception{
int[] arr = new int[4];
for(int i=0;i<4;i++){
arr[i] = (int)(v[3-i] & 0xFF);
}
return ((arr[0<< 24+ (arr[1<< 16+ (arr[2<< 8+ (arr[3<< 0));
}
}
cs








참고 : http://iblog.or.kr/hungi/it/server/network/2056

'System > Network ' 카테고리의 다른 글

AWS 네트워크 정리 - VPC, Subnet, Routing Table ..  (0) 2020.01.17
브릿지(Bridge)  (0) 2018.09.17
TCP 3-way Handshake vs 4-way Handshake  (0) 2018.05.19
TCP Header 구조체 분석  (0) 2018.05.09
TCP/IP , OSI 7 Layer  (0) 2018.04.01


Echo Server


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package netty_framework;
 
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
 
import javax.swing.plaf.synth.SynthProgressBarUI;
 
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
 
public class EchoServer {
 
    // 서버 소켓 포트 번호를 지정합니다.
    //private static final int PORT = 30081;
 
    public static void main(String[] args) {
    /*
        NioEventLoop는 I/O 동작을 다루는 멀티스레드 이벤트 루프입니다.
        네티는 다양한 이벤트 루프를 제공합니다.
        이 예제에서는 두개의 Nio 이벤트 루프를 사용합니다.
        첫번째 'parent' 그룹은 인커밍 커넥션(incomming connection)을 액세스합니다.
        두번째 'child' 그룹은 액세스한 커넥션의 트래픽을 처리합니다.
        만들어진 채널에 매핑하고 스레드를 얼마나 사용할지는 EventLoopGroup 구현에 의존합니다.
        그리고 생성자를 통해서도 구성할 수 있습니다.
    */
        EventLoopGroup parentGroup = new NioEventLoopGroup(1);
        EventLoopGroup childGroup = new NioEventLoopGroup();
        try{
            // 서버 부트스트랩을 만듭니다. 이 클래스는 일종의 헬퍼 클래스입니다.
            // 이 클래스를 사용하면 서버에서 Channel을 직접 세팅 할 수 있습니다.
            
            ServerBootstrap sb = new ServerBootstrap();
        
            sb.group(parentGroup, childGroup)
            // 인커밍 커넥션을 액세스하기 위해 새로운 채널을 객체화 하는 클래스 지정합니다.
            .channel(NioServerSocketChannel.class)
            // 상세한 Channel 구현을 위해 옵션을 지정할 수 있습니다.
            //동시에 수용 가능한 클라이언트 연결 요청 개수를 서버 소켓에 설정 가능한 옵션
            .option(ChannelOption.SO_BACKLOG, 100)
            .handler(new LoggingHandler(LogLevel.INFO))
            // 새롭게 액세스된 Channel을 처리합니다.
            
            // ChannelInitializer는 특별한 핸들러로 새로운 Channel의
            // 환경 구성을 도와 주는 것이 목적입니다.
            .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel sc) throws Exception {
                    ChannelPipeline cp = sc.pipeline();
                    cp.addLast(new EchoServerHandler());
 
                }
            });
            
            //SocketAddress address = new InetSocketAddress("169.254.40.218",10081);
    //        SocketAddress address2 = new InetSocketAddress("172.10.11.20",10081);
            
            // 인커밍 커넥션을 액세스하기 위해 바인드하고 시작합니다.
            ChannelFuture cf = sb.bind(8080).sync();
//            cf = sb.bind(10087).sync();
            
            // 서버 소켓이 닫힐때까지 대기합니다.
            cf.channel().closeFuture().sync();
        //    cf2.channel().closeFuture().sync();
        }catch(Exception e){
            e.printStackTrace();
        }
        finally{
            parentGroup.shutdownGracefully();
            childGroup.shutdownGracefully();
        }
    }
}
cs






Server Inbound Handler


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
package netty_framework;
 
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
 
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
 
    // 채널을 읽을 때 동작할 코드를 정의 합니다.
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("server read : " + msg);
        System.out.println(ctx.channel().localAddress().toString() );
        ctx.write(msg); // 메시지를 그대로 다시 write 합니다.
    }
 
    // 채널 읽는 것을 완료했을 때 동작할 코드를 정의 합니다.
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush(); // 컨텍스트의 내용을 플러쉬합니다.
    };
 
    // 예외가 발생할 때 동작할 코드를 정의 합니다.
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace(); // 쌓여있는 트레이스를 출력합니다.
        ctx.close(); // 컨텍스트를 종료시킵니다.
    }
}
cs











Client


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package netty_framework;
 
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
 
public class EchoClient {
    // 호스트를 정의합니다. 로컬 루프백 주소를 지정합니다.
    private static final String HOST = "localhost";
    // 접속할 포트를 정의합니다.
    private static final int PORT = 8080;
    // 메시지 사이즈를 결정합니다.
    static final int MESSAGE_SIZE = 256;
 
    public static void main(String[] args) {
        EventLoopGroup group = new NioEventLoopGroup();
 
        try{
            Bootstrap b = new Bootstrap();
            b.group(group)
            .channel(NioSocketChannel.class)
            .option(ChannelOption.TCP_NODELAY, true)
            .handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel sc) throws Exception {
                    ChannelPipeline cp = sc.pipeline();
                    cp.addLast(new EchoClientHandler());
                }
            });
 
            ChannelFuture cf = b.connect(HOST, PORT).sync();
            cf.channel().closeFuture().sync();
        }
        catch(Exception e){
            e.printStackTrace();
        }
        finally{
            group.shutdownGracefully();
        }
    }
}
cs



Client Inbound Handler


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package netty_framework;
 
import java.util.Arrays;
 
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
 
public class EchoClientHandler extends ChannelInboundHandlerAdapter{
    private final ByteBuf message;
 
    // 초기화
    public EchoClientHandler(){
        message = Unpooled.buffer(EchoClient.MESSAGE_SIZE);
        // 예제로 사용할 바이트 배열을 만듭니다.
        byte[] str = "abcefg".getBytes();
        // 예제 바이트 배열을 메시지에 씁니다.
        message.writeBytes(str);
        message.writeByte((byte)0x11);
 
    }
 
    // 채널이 활성화 되면 동작할 코드를 정의합니다.
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 메시지를 쓴 후 플러쉬합니다.
        ctx.writeAndFlush(message);
    }
    
    public byte[] getMessageID(byte[] body) {
 
        int readCount = 0;
        // ByteBuf buf = Unpooled.buffer(body.length);
        int bodySize = body.length;
 
        for (int i = 0; i < bodySize; i++) {
            if (body[i] == (byte)0x11) {
                break;
            }
            readCount++;
        }
 
        byte[] messageID = new byte[readCount];
 
        messageID = Arrays.copyOfRange(body, 0, readCount);
 
        return messageID;
 
    }
    
    
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception {
        // 받은 메시지를 ByteBuf형으로 캐스팅합니다.
        ByteBuf byteBufMessage = (ByteBuf) msg;
        // 읽을 수 있는 바이트의 길이를 가져옵니다.
        int size = byteBufMessage.readableBytes();
 
        // 읽을 수 있는 바이트의 길이만큼 바이트 배열을 초기화합니다.
        byte [] byteMessage = new byte[size];
        // for문을 돌며 가져온 바이트 값을 연결합니다.
        for(int i = 0 ; i < size; i++){
            byteMessage[i] = byteBufMessage.getByte(i);
        }
        byte[] message =getMessageID(byteMessage);
        System.err.println(new String(message));
        // 바이트를 String 형으로 변환합니다.
//        String str = new String(byteMessage);
 
        // 결과를 콘솔에 출력합니다.
//        System.out.println(str);
 
        // 그후 컨텍스트를 종료합니다.
        ctx.close();
    }
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }
 
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
cs




'Framework > Netty' 카테고리의 다른 글

Nety JVM Option  (0) 2018.12.02
Netty HttpClient Example Code  (0) 2018.08.04
#Nettty Framework - Codec 종류 및 사용  (0) 2018.05.21
#Nettty Framework - ByteBuffer, ByteBuf  (0) 2018.05.09
#Nettty Framework - ChannelFutureListener  (0) 2018.05.09



local host Name 및 IP , Remote Host 와 IP 구하기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import socket
 
def print_mynetwork_info():
    host = socket.gethostname()
    ip_addr = socket.gethostbyname(host)
    print('HOST:' + host)
    print("ip Address:" + ip_addr)    
 
def print_remoteNetwork_info():
    remote_host = 'www.naver.com'
    remote_ip = socket.gethostbyname(remote_host)
    try:
        print(remote_host)
        print(remote_ip)
    except socket.error as identifier:
        print('error msg:' + expression)
        #예외 무시
        pass
    except:
        print('all eror')
        #예외 무시
        pass    
    finally:
        print('end')
 
 
if __name__ == '__main__':
    print_mynetwork_info()
    print_remoteNetwork_info()
cs



>>

HOST:myHost

ip Address:192.168.0.24

www.naver.com

210.89.160.88

end





로우 레벨의 네트워크 함수를 다루는 경우 IP 주소의 일반적인 문자열 표기 방식은 많이 사용하지 않는다. 이 문자열을 32비트의 바이너리 형식으로 변경해야한다.




IPv4 주소를 다른 포맷으로 변환


파이썬의 소켓 라이브러리는 여러가지 IP주소포맷을 다룰 수 있는 유틸리티 함수를 가지고 있고, 여기서 inet_aton()과  inet_ntoa()를 사용할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import socket
from binascii import hexlify
 
def convert_ipAddress():
    host = socket.gethostname()
    ipAddr = socket.gethostbyname(host)
    packed_ip = socket.inet_aton(ipAddr)
    unppcked_ip = socket.inet_ntoa(packed_ip)
 
    print(ipAddr)
#바이너리 데이터를 16진수로 표현
    print(hexlify(packed_ip))
    print(unppcked_ip)
 
 
if __name__ == '__main__':
    convert_ipAddress()
cs




>>

192.168.0.24
b'c0a80018'
192.168.0.24




호스트와 네트워크 바이트 순서에 맞게 정수 변환

호스트의 운영체제로부터 얻은 데이터를 네트워크 바이트 순서로 변환하거나 반대로 변환하는 작업을 수행하는 경우가 있는데, 운영체제 혹은 네트워크 환경에 따라 데이터의 포맷의 표현방식이 각자 다르기 때문이다.

네트워크 바이트 순서 = 시스템이 내부적으로 데이터를 표현하는 방법 



1
2
3
4
5
6
7
8
9
10
11
import socket
 
def convert_integer():
    data=1234
    # 32-bit long
    print ('original: %s -> long host byte order: %s, network byte order:%s' %(data,socket.ntohl(data),socket.htonl(data)))
    # 16-bit short
    print ('original: %s -> long host byte order: %s, network byte order:%s' %(data,socket.ntohs(data),socket.htons(data)))
 
 
convert_integer()
cs



>>

original: 1234 -> long host byte order: 3523477504, network byte order:3523477504

original: 1234 -> long host byte order: 53764, network byte order:53764










참고 서적 : 파이썬을 활용한 네트워크 프로그래밍


'programming > Python' 카테고리의 다른 글

django framework overview  (0) 2019.01.28
pyenv를 통한 python 개발환경 구성  (0) 2018.12.12
Python 주요사항 및 특징  (0) 2018.06.13


Python


- 파이썬은 1991년 발표된 인터프리터 방식의 프로그래밍 언어이다. 


- 인터프리터란 코드 한줄 한줄 읽어가며 실행하는 프로그램이고 실행하는 도중 에러가 나면 다음 코드는 실행되지 않는다.


- 즉, 파이썬은 스크립트 기반의 언어이다.


- 2000년도에 python2, 2008년도에 python3가 나왔다.




특징


- 명시적이고 심플하며 간결하다.


- 그렇기 때문에 높은 생산성을 가지고 있다.


- 문법이 굉장히 쉽다.


- 하지만 문법이 엄격하다. 예를 들면, 들여쓰기가 의무 규칙이고 자체가 하나의 코드 블럭이 되기 때문에 tab문자를 사용하지 않도록 권장한다.


- PEB-8에 명시된 공식 코딩 가이드에서는 스페이스 바로 공백 4문자를 넣기를 권장한다.


- 반복 가능한 객체. 이것은 파이썬의 가장 큰 특징 중 하나이다.

 : 파이썬에서는 반복가능한 객체(iterable)라는 강력한 기능을 제공하며 집합,문자열,리스트,함수 등 반복을 가능하게 한다.


- 가상 머신 위에서 실행되기 때문에 실행속도는 느린편이다. 

 : 가상 머신은 3.3 버전 이후 pyvenv를 사용한다.


- 다양하고 많은 라이브러리를 지원한다.




병렬 처리


- 기본적으로 파이썬 프로그램은 하나의 쓰레드에서 실행된다. (Single Thread)


- 쓰레드 클래스에서 daemon 속성은 서브쓰레드가 데몬 쓰레드인지 아닌지를 지정하는 것인데, 데몬 쓰레드란 백그라운드에서 실행되는 쓰레드로 메인 쓰레드가 종료되면 즉시 종료되며, 데몬 쓰레드가 아니라면 서브 쓰레드는 메인 쓰레드가 종료되도 자신의 작업이 끝날 때까지 계속 실행된다.


- 파이썬은 멀티스레딩을 지원하기 위해 GIL(Global Interpreter Lock)을 도입하여 사용하게 되었다. 따라서 python  스레드 10개를 만들어도 실제 10개가 만들어져도 GIL때문에 하나밖에 안돌아가는 현상이 있다. 뿐만 아니라 여러 성능 문제도 존재하기 때문에 파이썬에서의 병렬처리는 다중 스레드가 아닌 다중 프로세스로 GIL을 우회하는 방식을 사용한다.


네트워크 프로그래밍을 수행할 경우 파이썬의 동시성 및 병렬성에 대해 자세히 알아봐야 할 것 같다.




Python2 vs Python3


- 특이하게 python3는 python2와 호환되지 않는다.


- python2에는 많은 문제와 취약점을 갖고 있다.


- python3.x 부터 모든 문자는 유니코드 처리한다. 유니코드 특성상 2바이트 혹은 4바이트를 차지하는데 2.x 는 기본 1바이트이기 때문에 속도차이는 당연히 날 것이고 이 문제를 해결하기 위해 3.3 버전 이후부터 문자열 객체에서 가장 많은 바이트를 차지하는 문자를 기준으로 각 문자가 차지할 공간을 정하도록 변경되었다.




PEP


- PEP 이란 Python Enhancement Proposals 약자로서 파이썬을 개선하기 위한 제안서를 의미한다. 이러한 PEP 다음과 같이 크게 3 종류로 구분할 있으며, Python Software Foundation 공식 웹사이트인 python.org 에서 관리한다


- 특히 파이썬 코딩에 관련된 제안서는 PEP-8 에서 확인 할 수 있다.




FrameWork


Django : 풀 스택 웹 프레임워크

Flask : 마이크로 웹 프레임워크

Pygame : 파이썬으로 비디오 게임을 제작하기 위한 프레임워크






개발환경


파이썬 IDLE, Atom, SublimeText, VisualStudio Code, Eclipse-PyDev







앞으로 파이썬을 통해 주로 다뤄보고자 하는 것은  파이썬을 통한 네트워크 프로그래밍과 Django 프레임워크이다.








참고


http://pythonstudy.xyz/python/article/24-쓰레드-Thread

https://namu.wiki/w/Python



'programming > Python' 카테고리의 다른 글

django framework overview  (0) 2019.01.28
pyenv를 통한 python 개발환경 구성  (0) 2018.12.12
HOST, IP Address 간단하게 활용  (0) 2018.06.16

+ Recent posts