forked from huangzworks/redis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbitcount.html
341 lines (218 loc) · 16.5 KB
/
bitcount.html
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BITCOUNT key [start] [end] — Redis 命令参考</title>
<script type="text/javascript" src="../_static/js/modernizr.min.js"></script>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'../',
VERSION:'2019',
LANGUAGE:'None',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt'
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<script type="text/javascript" src="../_static/js/theme.js"></script>
<link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="BITPOS key bit [start] [end]" href="bitpos.html" />
<link rel="prev" title="GETBIT key offset" href="getbit.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href="../index.html" class="icon icon-home"> Redis 命令参考
</a>
<div class="version">
2019
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../string/index.html">字符串</a></li>
<li class="toctree-l1"><a class="reference internal" href="../hash/index.html">哈希表</a></li>
<li class="toctree-l1"><a class="reference internal" href="../list/index.html">列表</a></li>
<li class="toctree-l1"><a class="reference internal" href="../set/index.html">集合</a></li>
<li class="toctree-l1"><a class="reference internal" href="../sorted_set/index.html">有序集合</a></li>
<li class="toctree-l1"><a class="reference internal" href="../hyperloglog/index.html">HyperLogLog</a></li>
<li class="toctree-l1"><a class="reference internal" href="../geo/index.html">地理位置</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">位图</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="setbit.html">SETBIT</a></li>
<li class="toctree-l2"><a class="reference internal" href="getbit.html">GETBIT</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">BITCOUNT</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#id1">返回值</a></li>
<li class="toctree-l3"><a class="reference internal" href="#id2">代码示例</a></li>
<li class="toctree-l3"><a class="reference internal" href="#bitmap">模式:使用 bitmap 实现用户上线次数统计</a></li>
<li class="toctree-l3"><a class="reference internal" href="#id3">性能</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="bitpos.html">BITPOS</a></li>
<li class="toctree-l2"><a class="reference internal" href="bitop.html">BITOP</a></li>
<li class="toctree-l2"><a class="reference internal" href="bitfield.html">BITFIELD</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../database/index.html">数据库</a></li>
<li class="toctree-l1"><a class="reference internal" href="../expire/index.html">自动过期</a></li>
<li class="toctree-l1"><a class="reference internal" href="../transaction/index.html">事务</a></li>
<li class="toctree-l1"><a class="reference internal" href="../script/index.html">Lua 脚本</a></li>
<li class="toctree-l1"><a class="reference internal" href="../persistence/index.html">持久化</a></li>
<li class="toctree-l1"><a class="reference internal" href="../pubsub/index.html">发布与订阅</a></li>
<li class="toctree-l1"><a class="reference internal" href="../replication/index.html">复制</a></li>
<li class="toctree-l1"><a class="reference internal" href="../client_and_server/index.html">客户端与服务器</a></li>
<li class="toctree-l1"><a class="reference internal" href="../configure/index.html">配置选项</a></li>
<li class="toctree-l1"><a class="reference internal" href="../debug/index.html">调试</a></li>
<li class="toctree-l1"><a class="reference internal" href="../internal/index.html">内部命令</a></li>
<li class="toctree-l1"><a class="reference internal" href="../topic/index.html">功能文档</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">Redis 命令参考</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html">Docs</a> »</li>
<li><a href="index.html">位图</a> »</li>
<li>BITCOUNT key [start] [end]</li>
<li class="wy-breadcrumbs-aside">
<a href="../_sources/bitmap/bitcount.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="bitcount-key-start-end">
<span id="bitcount"></span><h1>BITCOUNT key [start] [end]<a class="headerlink" href="#bitcount-key-start-end" title="Permalink to this headline">¶</a></h1>
<blockquote>
<div><div class="line-block">
<div class="line">可用版本: >= 2.6.0</div>
<div class="line">时间复杂度: O(N)</div>
</div>
</div></blockquote>
<p>计算给定字符串中,被设置为 <code class="docutils literal"><span class="pre">1</span></code> 的比特位的数量。</p>
<p>一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 <code class="docutils literal"><span class="pre">start</span></code> 或 <code class="docutils literal"><span class="pre">end</span></code> 参数,可以让计数只在特定的位上进行。</p>
<p><code class="docutils literal"><span class="pre">start</span></code> 和 <code class="docutils literal"><span class="pre">end</span></code> 参数的设置和 <a class="reference internal" href="../string/getrange.html#getrange"><span class="std std-ref">GETRANGE key start end</span></a> 命令类似,都可以使用负数值:
比如 <code class="docutils literal"><span class="pre">-1</span></code> 表示最后一个字节, <code class="docutils literal"><span class="pre">-2</span></code> 表示倒数第二个字节,以此类推。</p>
<p>不存在的 <code class="docutils literal"><span class="pre">key</span></code> 被当成是空字符串来处理,因此对一个不存在的 <code class="docutils literal"><span class="pre">key</span></code> 进行 <code class="docutils literal"><span class="pre">BITCOUNT</span></code> 操作,结果为 <code class="docutils literal"><span class="pre">0</span></code> 。</p>
<div class="section" id="id1">
<h2>返回值<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h2>
<p>被设置为 <code class="docutils literal"><span class="pre">1</span></code> 的位的数量。</p>
</div>
<div class="section" id="id2">
<h2>代码示例<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h2>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">redis</span><span class="o">></span> <span class="n">BITCOUNT</span> <span class="n">bits</span>
<span class="p">(</span><span class="n">integer</span><span class="p">)</span> <span class="mi">0</span>
<span class="n">redis</span><span class="o">></span> <span class="n">SETBIT</span> <span class="n">bits</span> <span class="mi">0</span> <span class="mi">1</span> <span class="c1"># 0001</span>
<span class="p">(</span><span class="n">integer</span><span class="p">)</span> <span class="mi">0</span>
<span class="n">redis</span><span class="o">></span> <span class="n">BITCOUNT</span> <span class="n">bits</span>
<span class="p">(</span><span class="n">integer</span><span class="p">)</span> <span class="mi">1</span>
<span class="n">redis</span><span class="o">></span> <span class="n">SETBIT</span> <span class="n">bits</span> <span class="mi">3</span> <span class="mi">1</span> <span class="c1"># 1001</span>
<span class="p">(</span><span class="n">integer</span><span class="p">)</span> <span class="mi">0</span>
<span class="n">redis</span><span class="o">></span> <span class="n">BITCOUNT</span> <span class="n">bits</span>
<span class="p">(</span><span class="n">integer</span><span class="p">)</span> <span class="mi">2</span>
</pre></div>
</div>
</div>
<div class="section" id="bitmap">
<h2>模式:使用 bitmap 实现用户上线次数统计<a class="headerlink" href="#bitmap" title="Permalink to this headline">¶</a></h2>
<p>Bitmap 对于一些特定类型的计算非常有效。</p>
<p>假设现在我们希望记录自己网站上的用户的上线频率,比如说,计算用户 A 上线了多少天,用户 B 上线了多少天,诸如此类,以此作为数据,从而决定让哪些用户参加 beta 测试等活动 —— 这个模式可以使用 <a class="reference internal" href="setbit.html#setbit"><span class="std std-ref">SETBIT key offset value</span></a> 和 <a class="reference internal" href="#bitcount"><span class="std std-ref">BITCOUNT key [start] [end]</span></a> 来实现。</p>
<p>比如说,每当用户在某一天上线的时候,我们就使用 <a class="reference internal" href="setbit.html#setbit"><span class="std std-ref">SETBIT key offset value</span></a> ,以用户名作为 <code class="docutils literal"><span class="pre">key</span></code> ,将那天所代表的网站的上线日作为 <code class="docutils literal"><span class="pre">offset</span></code> 参数,并将这个 <code class="docutils literal"><span class="pre">offset</span></code> 上的为设置为 <code class="docutils literal"><span class="pre">1</span></code> 。</p>
<p>举个例子,如果今天是网站上线的第 100 天,而用户 peter 在今天阅览过网站,那么执行命令 <code class="docutils literal"><span class="pre">SETBIT</span> <span class="pre">peter</span> <span class="pre">100</span> <span class="pre">1</span></code> ;如果明天 peter 也继续阅览网站,那么执行命令 <code class="docutils literal"><span class="pre">SETBIT</span> <span class="pre">peter</span> <span class="pre">101</span> <span class="pre">1</span></code> ,以此类推。</p>
<p>当要计算 peter 总共以来的上线次数时,就使用 <a class="reference internal" href="#bitcount"><span class="std std-ref">BITCOUNT key [start] [end]</span></a> 命令:执行 <code class="docutils literal"><span class="pre">BITCOUNT</span> <span class="pre">peter</span></code> ,得出的结果就是 peter 上线的总天数。</p>
<p>更详细的实现可以参考博文(墙外) <a class="reference external" href="http://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps/">Fast, easy, realtime metrics using Redis bitmaps</a> 。</p>
</div>
<div class="section" id="id3">
<h2>性能<a class="headerlink" href="#id3" title="Permalink to this headline">¶</a></h2>
<p>前面的上线次数统计例子,即使运行 10 年,占用的空间也只是每个用户 10*365 比特位(bit),也即是每个用户 456 字节。对于这种大小的数据来说, <a class="reference internal" href="#bitcount"><span class="std std-ref">BITCOUNT key [start] [end]</span></a> 的处理速度就像 <a class="reference internal" href="../string/get.html#get"><span class="std std-ref">GET key</span></a> 和 <a class="reference internal" href="../string/incr.html#incr"><span class="std std-ref">INCR key</span></a> 这种 O(1) 复杂度的操作一样快。</p>
<p>如果你的 bitmap 数据非常大,那么可以考虑使用以下两种方法:</p>
<ol class="arabic simple">
<li>将一个大的 bitmap 分散到不同的 key 中,作为小的 bitmap 来处理。使用 Lua 脚本可以很方便地完成这一工作。</li>
<li>使用 <a class="reference internal" href="#bitcount"><span class="std std-ref">BITCOUNT key [start] [end]</span></a> 的 <code class="docutils literal"><span class="pre">start</span></code> 和 <code class="docutils literal"><span class="pre">end</span></code> 参数,每次只对所需的部分位进行计算,将位的累积工作(accumulating)放到客户端进行,并且对结果进行缓存 (caching)。</li>
</ol>
</div>
</div>
<div class="section" id="discuss">
<h2>
讨论
<a class="headerlink" href="#discuss" title="永久链接至标题">¶</a>
</h2>
<div id="disqus_thread"></div>
<script type="text/javascript">
/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
var disqus_shortname = 'redis-command-cn'; // required: replace example with your forum shortname
/* * * DON'T EDIT BELOW THIS LINE * * */
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
</div>
<!--
<div id="sponser">
<h2>赞助商</h2>
<p>我们正在寻找赞助商,有意对这个网站进行赞助的朋友请联系 [email protected] 。</p>
</div>
-->
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="bitpos.html" class="btn btn-neutral float-right" title="BITPOS key bit [start] [end]" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right"></span></a>
<a href="getbit.html" class="btn btn-neutral float-left" title="GETBIT key offset" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<p>
© Copyright 2019, Redis
</p>
</div>
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-53959484-7', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>