Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
A Redis compatible HLL implementation in Java
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Okada Haruki
August 02, 2019
Programming
360
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
A Redis compatible HLL implementation in Java
https://github.com/ocadaruma/pfutil
Okada Haruki
August 02, 2019
More Decks by Okada Haruki
See All by Okada Haruki
HyperLogLog feature of ClickHouse
ocadaruma
0
1.5k
HyperLogLog is interesting
ocadaruma
3
900
sbt-uglifier
ocadaruma
0
1.3k
Sparkが社内で流行ってきた話
ocadaruma
4
970
Other Decks in Programming
See All in Programming
FDEが実現するAI駆動経営の現在地
gonta
2
230
AI時代、エンジニアはどう育つのか -未経験エンジニアの成長を間近で見て考えたこと-
thasu0123
0
190
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
360
生成AI導入の「期待外れ」を乗り越える ー 開発フロー改革が目指す、真の組織変革
starfish719
0
2.6k
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
3
170
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
160
信頼性について考えてみる(SRE NEXT 2026 miniLT)
hayama17
0
220
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
550
全PRの83%がAIレビューだけでマージできるようになった開発組織はその後どうなったか
athug
0
540
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
1
260
数百円から始めるRuby電子工作
tarosay
0
110
今さら聞けない .NET CLI
htkym
0
140
Featured
See All Featured
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
270
Ethics towards AI in product and experience design
skipperchong
2
330
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
320
Raft: Consensus for Rubyists
vanstee
141
7.6k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
400
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.4k
The Spectacular Lies of Maps
axbom
PRO
1
870
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.8k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.6k
Transcript
Redis 互換なHyperLogLog の Java 実装を作った話 @ocadaruma
HyperLogLog ユニークカウントを高速・省メモリに推定する確 率的データ構造 Redis にも標準で入ってる
原理の直感的な説明 64bit int を一様ランダムに選んだとき、「左から 数えて1 が最初に立つのがk bit 目」である確率は 1/2^k
原理の直感的な説明 いいかえると、2^k 個ランダムに選ばないと「左端 の1 がk bit 目」であるような数が現れない つまりあるデータセットの要素を64bit hash にか
けて「左端の1 のbit 番号」だけ記録すれば、そのデ ータセットのユニークカウントを推定できる もちろんこれだけだと2^k 単位でしか近似できない し精度も悪いので、hash 関数をm 個使ってその平 均を取る、とか色々やる 実際は別々のhash 関数を用意するんじゃなくて もっと頭のいい方法でやる
HyperLogLog on Redis $ for i in `seq 1000`; rediscli
PFADD key $i > /dev/null $ rediscli PFCOUNT key (integer) 1001 $ for i in `seq 1000`; rediscli PFADD key $i > /dev/null $ rediscli PFCOUNT key (integer) 1001 $ for i in `seq 100`; rediscli PFADD foo a$i > /dev/null $ rediscli PFCOUNT foo (integer) 99 $ rediscli PFMERGE merged key foo OK $ rediscli PFCOUNT merged (integer) 1103
利用例 page やドメイン単位でUU 数をリアルタイムにレポ ートするシステム
PFMERGE は比較的遅い Redis 上で重い操作はあんまりしたくない
HyperLogLog の内部表現 普通に内部表現をGET できる 公式doc にもちゃんと書いてある https://redis.io/commands/pfcount rediscli> PFADD key
elem1 elem2 (integer) 1 rediscli> GET key "HYLL\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80i\xe1\x80N\ The HyperLogLog, being a Redis string,can be retrieved with GET and restored with SET. “ “
Java 側で操作できれば便利では? PFMERGE みたいな重い操作をRedis 上でやらず、 アプリケーション側に内部表現を持ってきて、 Java 上でやれると便利
pfutil https://github.com/ocadaruma/pfutil Redis v4 とv5 ではアルゴリズムがちょっと違う 内部表現は同じ どっちのアルゴリズムにも対応
例 $ amm > import $ivy.`com.mayreh:pfutil:0.1.1` > import com.mayreh.pfutil.v4.HllV4 >
val hll = HllV4.newBuilder().build() > (1 to 1000).foreach(i => hll.pfAdd(s"$i".getBytes)) > hll.pfCount() res4: Long = 1001L > val hll2 = HllV4.newBuilder().build() > (1 to 100).foreach(i => hll2.pfAdd(s"a$i".getBytes)) > hll2.pfCount() res7: Long = 99L > hll.pfMerge(hll2).pfcount() res8: Long = 1103L
まとめ 確率的データ構造面白くて便利!