mixi engineer blog

*** 引っ越しました。最新の情報はこちら → https://medium.com/mixi-developers *** ミクシィ・グループで、実際に開発に携わっているエンジニア達が執筆している公式ブログです。様々なサービスの開発や運用を行っていく際に得た技術情報から採用情報まで、有益な情報を幅広く取り扱っています。

コミュニティランキングでトレンドチェック

こんにちわ、skimuraです。

はじめに

mixi上に存在するコミュニティは、現実社会でのコミュニティの写像のようなものではないかと考られます。つまり図1に示したイメージのように、現実社会で盛り上がった事象は、mixi上のコミュニティでも盛り上がる仕組みになっているのではないかと考えています。今回インディーズ機能でリリースした「コミュニティランキング」はそのような仮説を数値的に明らかにするための試みの一つでもあります。本エントリーではこのような研究の過程で作成された「コミュニティランキング」について解説します。

community_image4.png
図1.現実社会とmixiのコミュニティ

コミュニティランキングとは

コミュニティランキングとは、各コミュニティにおけるトピックでのコメント増加数の推移などを指標としてコミュニティをランキング表示する機能です。コミュニティランキングには「総合ランキング」、「カテゴリー別ランキング」、「トピックランキング」の3種類のランキングがあります。

■ 総合ランキング
すべてのカテゴリーを対象として、上位30位までのコミュニティを表示します。

■ カテゴリー別ランキング
mixiのコミュニティの6つのカテゴリーごとにランキングを作成し、それぞれ上位30位までのコミュニティを表示します。

■ トピックランキング
すべてのコミュニティを対象として、上位30位までのトピックを表示します。

コミュニティランキングを作成した背景

mixiにはコミュニティを探すためのツールとして、「コミュニティ検索」機能があります。コミュニティ検索は通常のウェブ検索エンジンと同様に、キーワードを含むコミュニティを検索結果として得ることができます。したがって、コミュニティ検索では何かしらの自発的に知りたいと思う事柄がなければ新たにコミュニティの情報を得ることがありません。

しかし、mixi上では日々、様々な話題のコミュニティが盛衰をみせています。盛り上がりをみせているようなコミュニティの中には自分では気がつかなかったような潜在的に興味のあるコミュニティや、情報としての価値が高いコミュニティがあります。たとえば、mixiのコミュニティではアーティストのアルバム発売や、コンサートのチケット販売開始などが始まると、それに関するコミュニティのトピックでのコメントが爆発的に増加したりします。しかし、現状の機能ではこのようなコミュニティを発見するのは困難です。これらの情報を可視化し、提供することでmixiをもっと楽しめるのではないかと考えました。

コミュニティランキングの実装

このような盛り上がりを示す仕組みとして、コミュニティをランキング表示する機能をリリースすることとなりました。しかし、何を指標としてランキングを作成するかは単純には決められません。たとえば「参加人数の増減を指標としてランキングを作成してみてはどうか」とか、「トピックの増加数で盛り上がりを見たらどうか」とか、様々な要素を指標としてランキングを作成することができます。このような試行錯誤をした結果、今回はコミュニティのトピックのコメントの増加の推移をメインの指標として用いることにしました。ランキングの指標に関しては、話題になっているコミュニティを上位として抽出できるように、これからもパラメータ調整や新たに指標の要素を追加したりして精度向上に努めなければなりません。

コミュニティランキングの考察

コミュニティランキングは、話題になったニュース、有名人の誕生日、スポーツなど、世の中でも関心が高まっている事柄に関するコミュニティが上位になりやすい傾向にあります。例として2008年11月13日のランキング結果上位3位の例を示します(図2参照)。1位はJリーグクラブチーム、ガンバ大阪に関するコミュニティです。ガンバ大阪は前日12日にアジア・チャンピオンリーグで初のアジアでのクラブ1位になったためコミュニティでの発言が活発になったためだと考えられます。2位には歌手の倖田來未さんに関するコミュニティがランクインしています。11月13日は倖田來未さんの誕生日であるため、コミュニティの発言が活発になったためだと考えられます。このようにコミュニティは何か話題になった事柄の情報を調べるにも役立ちます。それぞれのコミュニティでは話題になった事柄に関して議論されていることが多いので、ニュースとはまた違った質の情報が得られます。今日はどんな日なのか、という大雑把な情報を短時間で収集するのにも便利かと思います。

community_ranking_1113_modify.png
図2.コミュニティランキングの具体例

コミュニティランキングの仕組みに関して

コミュニティランキングのシステム的な話をしたいと思います。コミュニティランキングではmixi上にある約200万以上ものコミュニティのトピックコメント数をカウントしています。このような処理のように、ポイントの重みづけをする時などに、コミュニティIDをKeyとしてデータを何度も引くというような処理がよくあります。このようなディスクアクセスが大量に発生するような処理は、MySQLなどのRDBMSからデータを直接扱うと処理速度が遅くなったり、DBに負荷がかかります。したがって、必要なデータをRDBMSから一度dumpし、ローカルのDBMに保存して使いまわしています。DBMはTokyo Cabinetを用います(図3参照)。Tokyo Cabinetを用いれば、データがメモリ上に乗る容量であればオンメモリで利用できるため高速に処理できますし、Disk I/Oも低減できます。



dbm1.png
図3. コミュニティランキングでTokyo Cabinetを使用箇所の概要図

今回はTokyo Cabinetのhashデータベースを利用しています。hashデータベースを選択した理由は様々なkeyにランダムにアクセスする可能性が高いためです。文末に今回のサービスのランキングデータをTokyo Cabinetに書き込み、読み込みをしている処理のサンプルコード(Perl)を記述しておきます。大量のレコード数がある時には、DBMの設計時にチューニングを施したほうが高速に処理できます。しかし、たいていはサンプルのようにとてもシンプルなコードで高速にデータの読み書きが可能ですので、同じような処理をする場合はぜひご利用してみてはいかかがでしょうか。

まとめ

今回は、インディーズ機能でリリースした「コミュニティランキング」機能に関して紹介しました。本機能はmixiでのコミュニティの盛り上がりを可視化する施策として初めての機能となります。 mixiには検索ではなかなか発見できないようなおもしろい情報がたくさんあります。今後もmixiをより楽しく、便利に使えるようになる機能を開発できるよう努めていきたいと思います。

Tokyo Cabinetを使ったサンプルコード (Perl)

- Tokyo Cabinetのインスタンスを作成するためのサブルーチン
sub open_dbm {
    my $arg      = shift;
    my $dbm_path = $arg->{path};
    my $mode     = $arg->{omode};
    return if !$dbm_path || !$mode;
    my $hdb      = TokyoCabinet::HDB->new();
    if ($mode eq 'truncate') {
        # 新しくDBMを作るモード : すでにDBMが存在したら上書きされます
        $hdb->open($dbm_path, $hdb->OWRITER | $hdb->OCREAT | $hdb->OTRUNC)
            or die "cant open dbm: $dbm_path";
    } elsif ($mode eq 'write') {
        # DBMを追加書き込みするモード
        $hdb->open($dbm_path, $hdb->OWRITER | $hdb->OCREAT)
            or die "cant open dbm: $dbm_path";
    } elsif ($mode eq 'read') {
        # 読み込みのモード : read onlyで書き込みはできません
        $hdb->open($dbm_path, $hdb->OREADER) 
            or die "cant open dbm: $dbm_path";
    } else {
        die "error: open_dbm() mode: truncate || write || read";
    }
    $hdb;
}
- Tokyo Cabinetを使ってデータの読み書きをする処理
#!/usr/bin/perl

use strict;
use warnings;
use TokyoCabinet;

# ランキングなどのデータを作成する(これはdummyデータです)
# key:id  val:point
my %ranking_data = (
    1 => 10,
    2 => 5,
    3 => 15,
    4 => 1,
    5 => 22,
);

# Tokyo Cabinetのdbmインスタンスを作成する
my $hdb = open_dbm({
    path  => 'ranking.hdb', 
    omode => 'truncate',
}) or die "error: cant open dbm";

# ランキングデータをTokyo Cabinetに保存する
while (my ($key, $val) = each %ranking_data) {
    $hdb->put($key, $val);
}
$hdb->close();

# Tokyo Cabinetのdbmをオープンする
$hdb = open_dbm({
    path  => 'ranking.hdb',
    omode => 'read',
}) or die "error: cant oepn dbm";

# dbmのデータをイテレーションする
$hdb->iterinit();
while (my $key = $hdb->iternext()) {
    my $val = $hdb->get($key);
    
    # MySQLにinsertするなどの処理を書く

    print "[finish] id:$key val:$val\n";
}
$hdb->close();

__END__