読者です 読者をやめる 読者になる 読者になる

tail -fの結果にタイムスタンプをつける方法のメモ

f:id:komeiy:20150107164847j:plain

メモです。アプリからログに書き込まれたタイミングを確認するなど、出力にタイムスタンプをつけたい時などに使います。

tail -f error.log | while read line; do printf "$(date -u '+%F %T%z')\t$line\n"; done

出力は以下のような感じです。

2015-11-06 23:14:38+0000 Nov  6 23:14:12 komei login[3783]: USER_PROCESS: 3783 ttys000

シェアして頂けると嬉しいです。
参考になったという方がいれば是非お願いしますm(_ _ )m
モチベーション維持の観点で非常に励みになります。

このエントリーをはてなブックマークに追加

新しいLinuxの教科書

新しいLinuxの教科書

Linuxシステム[実践]入門 (Software Design plus)

Linuxシステム[実践]入門 (Software Design plus)

広告を非表示にする

zabbix_senderで複数の値を一括登録する

f:id:komeiy:20141012172923p:plain

Zabbixは非常に便利で、Agentでの監視の他に自身で取得可能なあらゆる情報をZabbix senderを使用してサーバへ送信することが可能です。

Zabbix_Senderの使い方

$ zabbix_sender -z zabbix -s "Linux DB3" -k db.connections -o 43

z - Zabbix サーバのホスト(IP アドレスでの指定でも可) s - 監視対象のホスト名 (Zabbix フロントエンドで登録されたもの) k - アイテムキー o - 送信する値

Zabbix_Senderで複数の値を投入する

上記の例だと一つのkeyに対して値を投入していますが、複数のkeyを扱うことが可能です。監視対象側の負荷を軽減することができるので非常に重宝します。

ファイルからデータを投入する

$ zabbix_sender -z 127.0.0.1 -i /tmp/traptest.txt 
Info from server: "Processed 250 Failed 0 Total 250 Seconds spent 0.002668"
Info from server: "Processed 50 Failed 0 Total 50 Seconds spent 0.000540"
sent: 300; skipped: 0; total: 300

-iでファイルを指定します。ファイルの中身はシンプルに以下のような内容でOKです。

<hostname> <key> <value>
<hostname> <key> <value>
<hostname> <key> <value>
<hostname> <key> <value>

直接データを投入する

ファイルに書き出す必要がない場合は以下の通り直接コマンドラインから複数のデータを扱うことも可能です。

$ echo -n -e '<hostname> <key> <value>\n<hostname> <key> <value>' | zabbix_sender -z 127.0.0.1 -p 10051 -i -
info from server: "processed: 2; failed: 0; total: 2; seconds spent: 0.000066"
sent: 2; skipped: 0; total: 2

他にもzabbix_senderとディスカバリを組み合わせることでitemを動的に作成するという小技もありますので、時間を見つけて書いておきたいと思います。


シェアして頂けると嬉しいです。
参考になったという方がいれば是非お願いしますm(_ _ )m
モチベーション維持の観点で非常に励みになります。

このエントリーをはてなブックマークに追加

広告を非表示にする

haproxyのステータス確認

haproxy ネットワーク

f:id:komeiy:20150107164847j:plain haproxyのステータス確認方法をいつも忘れてしまうのでメモ代わりに書いておきます。

haproxyのsocketをcatするsocatコマンドを使います。 以下のように書くことで8080番への入力を標準出力に書き込むことができます。 簡単dす。

$ socat tcp-listen:8080 stdout

haproxyではechoを使って取得したいログの種別を指定します。 まずはバージョン情報など基本的な情報を取ってみます。

root@gw01:~# echo "show info" | socat unix-connect:/etc/haproxy/sock stdio
Name: HAProxy
Version: 1.4.24
Release_date: 2013/06/17
Nbproc: 1
Process_num: 1
Pid: 24498
Uptime: 0d 0h08m59s
Uptime_sec: 539
Memmax_MB: 0
Ulimit-n: 4013
Maxsock: 4013
Maxconn: 2000
Maxpipes: 0
CurrConns: 1
PipesUsed: 0
PipesFree: 0
Tasks: 2
Run_queue: 1
node:gw01
description:

コマンド一覧をhelpで取ってみました。

  clear counters : clear max statistics counters (add 'all' for all counters)
  help           : this message
  prompt         : toggle interactive mode with prompt
  quit           : disconnect
  show info      : report information about the running process
  show stat      : report counters for each proxy and server
  show errors    : report last request and response errors for each proxy
  show sess [id] : report the list of current sessions or dump this session
  get weight     : report a server's current weight
  set weight     : change a server's weight
  set timeout    : change a timeout setting
  disable server : set a server in maintenance mode
  enable server  : re-enable a server that was previously in maintenance mode

backendのステータスなどはshow statで確認可能です。

root@gw01:~# echo "show stat" | socat unix-connect:/etc/haproxy/sock stdio
# pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,eresp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,qlimit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_status,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt,
07625016-88cc-4533-a0b0-cd006b54c110,FRONTEND,,,0,0,2000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,1,0,,,,0,0,0,0,,,,,,,,,,,0,0,0,,,
2c8ff70e-1345-4642-8689-1ce7d74506a8,6f37e25b-713e-4c31-8671-aec5c23a878e,0,0,0,0,,0,0,0,,0,,0,0,0,0,UP,1,1,0,0,0,1278,0,,1,2,1,,0,,2,0,,0,L4OK,,3,,,,,,,0,,,,0,0,
2c8ff70e-1345-4642-8689-1ce7d74506a8,BACKEND,0,0,0,0,0,0,0,0,0,0,,0,0,0,0,UP,1,1,0,,0,1278,0,,1,2,0,,0,,1,0,,0,,,,,,,,,,,,,,0,0,

こんな感じで必要な情報だけ引っ張ります。svnamestatusをピックアップしています。

root@gw01:~# echo "show stat" | socat unix-connect:/etc/haproxy/sock stdio | grep -v -e '^#\|^$' | cut -d ',' -f 2,18 --output-delimiter=':'
FRONTEND:OPEN
6f37e25b-713e-4c31-8671-aec5c23a878e:UP
BACKEND:UP

サーバ負荷分散入門

サーバ負荷分散入門

サーバ負荷分散入門

サーバ負荷分散入門


シェアして頂けると嬉しいです。
参考になったという方がいれば是非お願いしますm(_ _ )m
モチベーション維持の観点で非常に励みになります。

このエントリーをはてなブックマークに追加




パーフェクトPHP
パーフェクトPHP
posted with amazlet at 15.08.29
技術評論社 (2014-10-31)
売り上げランキング: 10,488


広告を非表示にする

sflowもFluentd+Elastic Searchに入れて可視化してみた

fluentd ElasticSearch ネットワーク

以前にNetflowについて書いたのですが、sflowもelastcsearchに入れたいなと思って色々調べてみました。ちなみに前回からkibanaのバージョンをあげましてkibana 4はこんな画面になってます。検証用のデータですが気持ち的にIPアドレスは隠しました。

f:id:komeiy:20150902212446j:plain

ホワイトを基調のデザインに一新されており個人的には好感が持てるデザインになっています。機能的にはグラフオプションが強化されて実現できることが多くなっています。

komeiy.hatenablog.com

  • kibana 4になり、対応するElastic Searchのバージョンも1.4以降に変更になっているため注意が必要です

調査フェーズ

logstashを使ってElastic Searchへ入れるパターン

まず、調べてたところlogstashで以下のような方法があるようなので少し調査。

https://github.com/NETWAYS/sflow

Tiny sflow collector and parser script based on eventmachine. It listens for sflow v5 samples, parses them and sends it to logstash.

インストール自体は楽そうですが、issuesのやりとりやflow sourceを都度設定ファイルやhostsに書かなければいけない(っぽい)点とsnmpがなぜか絡んでくるのがどうしてもすっきりせずパスしました。

(できれば設定はtd-agent.confで統一したいという思いもありすいません)

sflowをnetflowに変換してあれこれするパターン

世の中には便利なものがあるもので、今回sflowtoolを使うことにしました。結局、NETWAYS/sflowのissueでもsflowtoolをwrapperとして使用する方法について記載がありました。

sflowtoolは名前の通りsflowを扱うためのツールなのですが、任意のポートで受信し他のコレクタに渡したりcsvで吐き出したり、pcap形式に落としたり、あと今回重要なnetflowに対応したコレクタにフローを飛ばすことも可能です。

ということで、sflowtool -> fluentd -> elastic searchの流れでデータを注入することにしました。

sflowtoolインストール

最新版はgithubにあります。Versionは3.28でした。

git clone https://github.com/kplimack/sflowtool.git
cd sflowtool/

cloneしたら、configure / make / make installしてください。

パスが通っていれば$ sflowtoolで起動します。

参考)以下のログが出た人へ

v6 socket() creation failed, Address family not supported by protocol

デフォルトでlisten on both IPv4 and IPv6 socketsなので、ipv6をdisableにしている人は-4オプションを使ってください。

sflowを受信してみる

起動して受信すると以下の項目が値と共に出力されます。

startDatagram 
datagramSourceIP
datagramSize
unixSecondsUTC 
datagramVersion 
agentSubId 
agent
packetSequenceNo
sysUpTime 
samplesInPacket 
startSample ----------------------
sampleType_tag
sampleType
sampleSequenceNo 
sourceId 
meanSkipCount 
samplePool 
dropEvents 
inputPort 
outputPort 
flowBlock_tag
flowSampleType 
headerProtocol 
sampledPacketSize 
strippedBytes 
headerLen 
dstMAC 
srcMAC 
decodedVLAN 
decodedPriority 
IPSize
ip.tot_len 
srcIP 
dstIP 
IPProtocol 
IPTOS 
IPTTL 
TCPSrcPort 
TCPDstPort 
TCPFlags 
endSample   ----------------------
endDatagram   =================================

NetFlowに飛ばしたいのであれば以下のオプションを使います。

To forward Cisco NetFlow v5 records to UDP port 9991 on host collector.mysite.com, the
options would be:

% ./sflowtool -p 6343 -c collector.mysite.com -d 9991

Fluentd(td-agent)で受けてstdoutに出るようtagをdebugにしてみました。一回sflowtoolが受信するのでhostが127.0.0.1になってしまうのが残念です。ただ、本来のNetflowへ変換という意味ではVersion 5へしっかりと変換してくれました。

2015-09-02 23:23:10 +0900 debug.netflow: {"version":"5","flow_seq_num":"19","engine_type":"0","engine_id":"0","sampling_algorithm":"0","sampling_interval":"0","flow_records":"1","ipv4_src_addr":"1.1.4.1","ipv4_dst_addr":"1.1.7.1","ipv4_next_hop":"0.0.0.0","input_snmp":"1026","output_snmp":"1026","in_pkts":"32768","in_bytes":"1507328","first_switched":"2015-09-02T23:23:10.000Z","last_switched":"2015-09-02T23:23:10.000Z","l4_src_port":"52193","l4_dst_port":"80","tcp_flags":"16","protocol":"6","src_tos":"0","src_as":"0","dst_as":"0","src_mask":"0","dst_mask":"0","host":"127.0.0.1"}

ここからのElastic Searchへの挿入は前回と同様です。

その他

  • Elastic Search pluginで@timestamp_sourceは挿入されるのでkibanaから見ると前回と同じ仕様です
  • sflowtoolが増えましたが、既存のFluentdの設計を踏襲できるのでシンプルで分かりやすいと思っています

シェアして頂けると嬉しいです。
参考になったという方がいれば是非お願いしますm(_ _ )m
モチベーション維持の観点で非常に励みになります。

このエントリーをはてなブックマークに追加

高速スケーラブル検索エンジン ElasticSearch Server (アスキー書籍)

高速スケーラブル検索エンジン ElasticSearch Server (アスキー書籍)

広告を非表示にする

Network機器をAnsibleで操作(?)してみた

Ansible

f:id:komeiy:20140820203642j:plain

RAWコマンドならいけるよねということで夜な夜な試してみましたメモです。今回、showコマンドやwr memなどしか試していないです。個人的には設定投入はエラー処理とか考えると他に任せたいなと思います。

Network機器でAnsibleの環境

新たに準備するのが面倒だったので以前に使ったvirtual boxで。古くてすいません。 opensshのバージョンは気にした方が良いです。理由は後述します。

$ ansible --version
ansible 1.9.1

$ cat /etc/redhat-release
CentOS release 6.5 (Final)

$ sudo yum list installed | grep openssh
openssh.x86_64                     5.3p1-112.el6_7                     @updates

Ansible設定

SFTPが開いていないデバイスのために念のためscp_if_sshTrueにしておきます。 セッションは1分あれば十分と判断し、60sにしています。

$ more ansible.cfg
[defaults]
host_key_checking = False
transport=ssh
log_path=ansible.log

[ssh_connection]
scp_if_ssh=True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

インベントリはメーカーごとに分けています。ここは環境により分けて頂ければと思います。

$ more hosts
[all:vars]
ansible_ssh_user=<username>
ansible_ssh_pass=<password>

[cisco]
1.1.1.1

冒頭に書いた通りrawモジュールを使ってコマンドを打ちます。 show runを出力するtaskと出力をローカルに保存するtaskを作っています。

$ more show-run.yml
---
- hosts: cisco
  gather_facts: no

  tasks:
  - name: sh run
    raw : "show run"
    register: show_run
  - name: sh run output
    local_action: shell /bin/echo "{{ show_run.stdout }}" > /home/komei/ansible-
test/sh_run_{{ inventory_hostname }}.txt
$ ansible-playbook show-run.yml -i hosts

PLAY [cisco] ******************************************************************

TASK: [sh run] ****************************************************************
ok: [1.1.1.1]

TASK: [sh run output] *********************************************************
changed: [1.1.1.1 -> 127.0.0.1]

PLAY RECAP ********************************************************************
1.1.1.1                  : ok=2    changed=1    unreachable=0    failed=0
$ ls -la
-rw-rw-r--  1 komei komei   689 Aug 24  23:55 sh_run_1.1.1.1.txt

1つイケてないのがインデントがなくすべて前詰めになってしまう点です。。copyコマンド入れてもプロンプトが出るし何かうまい方法ないかな。。 スイッチ側の設定を書いてないですが、Ansibleなので基本的にSSH開けておけばOKです。たた、個人的にはprivilegeレベルを下げたユーザでアクセスさせたいため、show runではなくwr mem & show confで動かすつもりです。↓みたいな感じ。

$ more show-conf.yml
---
- hosts: cisco
  gather_facts: no

  tasks:
  tasks:
  - name: wr mem
    raw : "wr mem"
  - name: sh conf
    raw : "show conf"
    register: show_conf
  - name: sh conf output
    local_action: shell /bin/echo "{{ show_conf.stdout }}" > /home/komei/ansible
-test/sh_conf_{{ inventory_hostname }}.txt

その他

エラーが出た時の対処

文言通りsshpassを入れてください

TASK: [sh run] **************************************************************** 
fatal: [1.1.1.1] => to use the 'ssh' connection type with passwords, you must install the sshpass program

$ sudo yum install sshpass

opensshのバージョンによってはparamikoを使ってしまってtty周りで苦戦するかもしれません。

http://docs.ansible.com/ansible/intro_getting_started.html

However, when using Enterprise Linux 6 operating systems as the control machine (Red Hat Enterprise Linux and derivatives such as CentOS), the version of OpenSSH may be too old to support ControlPersist. On these operating systems, Ansible will fallback into using a high-quality Python implementation of OpenSSH called ‘paramiko’.

使いどころ

全台のwr memくらいなら有りかなくらいです。バージョンとかはSNMPでGETすれば良いと思いますし。ただ、RAWコマンドがうまく通らないメーカーもあったので、うーんという感じです。もう少し頑張ればわかるかな。。バックアップの仕組みはインデントの件もあるので、copyコマンドで吐き出した方が良いと思います。


シェアして頂けると嬉しいです。
参考になったという方がいれば是非お願いしますm(_ _ )m
モチベーション維持の観点で非常に励みになります。

このエントリーをはてなブックマークに追加

入門Ansible

入門Ansible

Ansible: Up and Running

Ansible: Up and Running

広告を非表示にする

chefのdata_bagを暗号化する

Chef

f:id:komeiy:20140820204528p:plain

chef serverだとdata baseのcreate時に--secret-file オプションで暗号化が簡単に可能ですが、chef solo / knife solo環境data bagでも実はknife-solo_data_bagを使うと簡単に実現可能です。

knife-solo_data_bagインストール

gem install knife-solo_data_bag

or

Gemfiles & bundle install

使い方などは以下を参照すると

  • usage & Version Support

https://github.com/thbishop/knife-solo_data_bag

秘密鍵の作成

今回、RSAの2048bitで作成します。

$ openssl genrsa -aes256 2048 | tr -d '\r\n' > .chef/data_bag_key

knife設定とその他

--secret-file .chef/data_bag_keyでも可能ですが、毎回指定していると忘れるので書いておきます。

$ vim .chef/knife.rb
encrypted_data_bag_secret ".chef/data_bag_key"
$ vim ~/.bash_profile
export EDITOR='vim'

knife soloでdata bagの作成

作成はknife solo data bag createです。

$ knife solo data bag create s3 test
{
  "id": "test",
  "keys": {
    "key_1": "12345",
    "key_2": "54321"
  }
}

作成されたデータを覗くとdata部分が暗号化されているかと思います。 ファイルはeditor経由ではなくknife solo editで編集します。


シェアして頂けると嬉しいです。
参考になったという方がいれば是非お願いしますm(_ _ )m
モチベーション維持の観点で非常に励みになります。

このエントリーをはてなブックマークに追加

Chef実践入門 ~コードによるインフラ構成の自動化 (WEB+DB PRESS plus)

Chef実践入門 ~コードによるインフラ構成の自動化 (WEB+DB PRESS plus)

Chef活用ガイド コードではじめる構成管理

Chef活用ガイド コードではじめる構成管理

広告を非表示にする

Aerospike Deep Driveに参加してきた

f:id:komeiy:20150329230850p:plain

参加メモです。6/24(水) 19:00〜22:00。

個人的にはpartition mapの話が勉強になりました。Aerospikeは構築するだけであれば非常に簡単でドキュメントにインフラ周りの仕組みがなかなか記載されていないので、裏側を知れたのは非常に嬉しいです。

Aerospikeと他KVSとの違い、適用分野等

  • 導入事例
  • 導入時に検討した他のKVS
  • 導入して気づいたこと

IDSyncサービス

  • 自社IDと他社IDのマッピング
  • 属性データの加工

  • ID Syncサービスとは

  • マッピングテーブルを生成
  • アンケートで特定の解答をした人に広告配信
  • 自社サイトに訪問した人にメール広告を配信

  • システム

  • ELB + Nginx + uWSGI
  • バックエンドにaerospike
  • 平均応答速度は1ms
  • ピーク時で1000req/s程度
  • 主キーが自社ID、他社IDを主キーとしたものを保持

  • 様々な属性情報を、異なるソースから取得

  • 保持している属性情報を人が理解できるように
  • 基盤にaerospike
  • cookie IDを元に様々なデータを保持
  • 要素ごとに個別のsetを保持(useragent, IP, company, ...etc)

他のKVSとの比較

  • DynamoDB

    • 費用面がネック
    • キャパシティを超えたリクエストがロスト(キューイングなし)
    • 10万read/sで130万/月、10万write/sで650万/月
  • Redis(ElasticCache)

    • 容量制限あり(最大240GB)
    • 到達した場合に代替手段がないのでスケールしない
  • Cloud Bigtable

    • GCPにしないとレイテンシが発生する
    • 応答速度がAerospike比で約5〜10倍(らしい)

導入して気づいたこと

  • clientが高機能
  • レコードがどのノードに配置されているか主キーのハッシュ値で把握している
  • コネクション取得時にテーブルを取得する
  • マッピングテーブルはノードの削除・追加時に更新される

  • Clientもパワーが必要

  • 高多重度でリクエストを行う必要あり
  • 1リクエスト1msで3.6億レコードを取り出す

  • メモリの使用量が大きい

  • SSDのみの利用でも意外とメモリを利用する

    • インデックスがメモリ展開される
    • 1レコードにつき64バイト
  • Nmaespaceが分割しにくい

  • SSDを使用する場合、ブロックデバイス単位でしかNamespaceを分けることができない

  • Queryの制約

  • SQLライクな記述でレコードを参照するこも可能だが・・・
  • 指定したサーバで処理が走る(クライアント側ではない)
  • 並列実行ができない
  • バックアップのQuery扱い
  • mysqldumpの様なコマンドがある。平文。データ量と時間に注意

  • その他 雑感

  • インメモリだと特に速い
  • 設定項目がほぼないので構築が楽
  • ドキュメントにない機能がライブラリにある(ソースコードみよう!)

  • まとめ

  • Aerospikeの速度が必要なケースってあまり多くなさそう
  • マッチしそうなケース
    • データ量の見積もりが難しい場合
    • 時間あたりのリクエスト数が膨大な場合
  • リソースの見積もりが難しい

新機能を使ってみて

クライアントライブラリ

  • 新機能の実装優先度

    1. jaba / c / node
    2. go /python ruby /php
  • scalaもcommunity Labsにあるよ

  • 大体の使い方を知るにはサンプルプログラムを読む/実行するのがよい

  • vagrantで入れてAMCでアクセスしてみよう(ここまで30分)
  • GitHubで公開されているclientライブラリにもexamplesが同梱
  • 充実度はJavaが一番

  • 基本の保存と検索

  • client.put / client.get
  • サポートしている型はシンプル
  • list / mapはgetlist/getmapはないget objectでダウンキャスト
  • ver3からlist / set / map / stackをサポート。LDTS
  • LargeListは昇順でソートされている

  • executeはサーバに配置されたluaプログラムを実行するためのメソッド

  • luaスクリプトを自分で書くことができUDFと呼ぶ

  • limitation

    • ソートは昇順
    • write block size設定によって1要素の容量が制限される
    • 1Mbなら200kb / 128kbなら30kb
    • add_all(), udate_all()は1GBまで
    • XDRはLDT対象外
    • aqlで内容を確認できない

その他

  • LDTのデータは1つのサーバノードで保存されクラスタ内に分散しない
  • TTLはRecord単位
  • LDTの堀はluaを使うのでCPUを消費する
  • LDT * luaはサンプル少なくて苦労する

  • OSS

    • あまり使われてない機能・環境を使う場合はEnterprise Editionを推奨
  • Aerosparkあるよ

Node.jsクライアントを半年間、使ってみて

− 運用のし易さで選定 - クラスタ構成、パフォーマンス、サーバ台数削減 - メモリリーク問題 - heapdump / tcp connection? /clinen closeで治るか? -> 治らず - binの文字長 - 感想:サーバサイドの運用が楽、クライアントは・・・

マイグレーション

partition map

  • クラスタ内のデータを4096個に分割したもの
  • partitionはレコードを均等に入れる4096個のバケツ
  • キーのハッシュの先頭12bitを使用
  • パーティションをサーバに均等に分割
  • 各サーバのMACとpartitionIDを使って各ノードの順番を決める。これをパーティションマップ。
  • partition mapは左からreplication factorに従い選択される
  • clientからのアクセスは1ホップ
  • オートシャーディング、オートバランシング

ノード追加

  1. ノード追加
  2. Gossipプロトコルで伝達。全ノードのノードリストができてからMap作成に移る
  3. patition mapが更新される。計算上既存ノードの順序は変わらず新規ノードが入ってくる(マイグレーション処理が少ない)
  4. 新規ノードにデータがあるノードからコピーされる
  5. 新規ノードがslaveであればClientはMasterへ、新規ノードがMasterならclientはコピーが終るまではslaveへ。2台同時追加でmaster/slave両方がコピー中の場合はmapの右へ
  6. slaveで受けているときはコピーを続けつつmasterのjournalへ書き込む
  7. 最後にjournalをflashする

  8. 通常時はmaster/slaveに書き込んでACK, 非同期でSSDFlash。reptication factor 3だと3台書き込めてからレスポンス。

  9. migration走って容量減った? -> partition mapでslave以下に降格したデータが消える。reprication factorは3 !?
  10. 2TBで3台->4台にしたときに18時間

シェアして頂けると嬉しいです。
参考になったという方がいれば是非お願いしますm(_ _ )m
モチベーション維持の観点で非常に励みになります。

このエントリーをはてなブックマークに追加

NOSQLの基礎知識

NOSQLの基礎知識

データベース徹底攻略 (WEB+DB PRESS plus)

データベース徹底攻略 (WEB+DB PRESS plus)

広告を非表示にする