暴走女 發表於 2025-11-26 09:12:37

Redis批量操作的实现示例

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、原生批量命令(MSET)</a></li><li><a href="#_label1">二、Pipeline(管道)</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">1. 命令行操作</a></li><li><a href="#_lab2_1_1">2. 编程语言实现(以Python为例)</a></li></ul><li><a href="#_label2">三、Lua脚本</a></li><ul class="second_class_ul"></ul><li><a href="#_label3">四、Redis事务(MULTI/EXEC)</a></li><ul class="second_class_ul"></ul><li><a href="#_label4">五、Redis集群模式优化</a></li><ul class="second_class_ul"></ul><li><a href="#_label5">六、性能优化建议</a></li><ul class="second_class_ul"></ul><li><a href="#_label6">七、执行方式对比</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、原生批量命令(MSET)</h2>
<p><strong>适用场景</strong>:所有键的过期时间相同或无过期设置,且无需条件判断。 <strong>方法</strong>: 将多个SET命令合并为<code>MSET</code>命令,但需要注意MSET的局限性(无法设置过期时间,且所有键值对必须一次性设置)。</p>
<div class="jb51code"><pre class="brush:sql;">MSET CUSTOMER_STAR:STAFF_20220311161756037_CUS_20240201183046858 1 CUSTOMER_STAR:STAFF_20220311161756037_CUS_20240201182841857 1 ...(其他键值对)</pre></div>
<p><strong>优点</strong>:网络开销最小,一次请求完成所有操作。</p>
<p><strong>缺点</strong>:无法设置过期时间,且要求所有键在同一哈希槽(集群模式下需使用哈希标签<code>{}</code>)。</p>
<p class="maodian"><a name="_label1"></a></p><h2>二、Pipeline(管道)</h2>
<p><strong>适用场景</strong>:需高效批量执行命令且允许非原子性操作。</p>
<p class="maodian"><a name="_lab2_1_0"></a></p><h3>1. 命令行操作</h3>
<p>将命令写入文件后通过管道执行:</p>
<div class="jb51code"><pre class="brush:bash;"># 创建命令文件 commands.txt
echo "SET CUSTOMER_STAR:STAFF_20220311161756037_CUS_20240201183046858 1" &gt;&gt; commands.txt
# 追加其他命令...

# 通过redis-cli执行
cat commands.txt | redis-cli -h &lt;host&gt; -p &lt;port&gt; -a &lt;password&gt; --pipe</pre></div>
<p><strong>优点</strong>:减少网络往返次数,适合大规模批量操作。</p>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>2. 编程语言实现(以Python为例)</h3>
<div class="jb51code"><pre class="brush:py;">import redis

r = redis.Redis(host='localhost', port=6379)
pipe = r.pipeline()

keys = [
    "CUSTOMER_STAR:STAFF_20220311161756037_CUS_20240201183046858",
    "CUSTOMER_STAR:STAFF_20220311161756037_CUS_20240201182841857",
    # ...其他键
]

for key in keys:
    pipe.set(key, 1)

pipe.execute()</pre></div>
<p><strong>优点</strong>:代码灵活,支持扩展(如设置过期时间)</p>
<p class="maodian"><a name="_label2"></a></p><h2>三、Lua脚本</h2>
<p><strong>适用场景</strong>:需原子性执行所有命令。</p>
<div class="jb51code"><pre class="brush:plain;">local keys = {
    'CUSTOMER_STAR:STAFF_20220311161756037_CUS_20240201183046858',
    'CUSTOMER_STAR:STAFF_20220311161756037_CUS_20240201182841857',
    -- 其他键
}

for _, key in ipairs(keys) do
    redis.call('SET', key, 1)
end</pre></div>
<p><strong>执行命令</strong>:</p>
<div class="jb51code"><pre class="brush:sql;">redis-cli -h &lt;host&gt; -p &lt;port&gt; -a &lt;password&gt; EVAL "$(cat script.lua)" 0</pre></div>
<p><strong>优点</strong>:保证原子性,适合对一致性要求高的场景。</p>
<p class="maodian"><a name="_label3"></a></p><h2>四、Redis事务(MULTI/EXEC)</h2>
<p><strong>适用场景</strong>:需保证命令按顺序执行,但非严格原子性(集群模式下需所有键在同一哈希槽)。</p>
<div class="jb51code"><pre class="brush:sql;">MULTI
SET CUSTOMER_STAR:STAFF_20220311161756037_CUS_20240201183046858 1
SET CUSTOMER_STAR:STAFF_20220311161756037_CUS_20240201182841857 1
...
EXEC</pre></div>
<p><strong>优点</strong>:命令顺序执行,支持条件判断(如WATCH)</p>
<p><strong>缺点</strong>:集群模式下需使用哈希标签确保键在同一节点</p>
<p class="maodian"><a name="_label4"></a></p><h2>五、Redis集群模式优化</h2>
<p><strong>问题</strong>:若为集群环境,需确保所有键在同一哈希槽。 <strong>解决方案</strong>:</p>
<ol><li><strong>使用哈希标签</strong>:在键名中使用<code>{}</code>包裹相同部分,例如:
<div class="jb51code"><pre class="brush:sql;">SET CUSTOMER_STAR:{STAFF_20220311161756037}_CUS_20240201183046858 1</pre></div>
<p>所有键的哈希标签<code>{STAFF_20220311161756037}</code>将分配到同一槽</p></li><li><strong>分节点执行</strong>:若无法使用哈希标签,需将命令按哈希槽分组后分别发送到对应节点。</li></ol>
<p class="maodian"><a name="_label5"></a></p><h2>六、性能优化建议</h2>
<ol><li><strong>控制批量大小</strong>:单次Pipeline建议不超过500条命令,避免内存或网络阻塞 。</li><li><strong>错误处理</strong>:Pipeline和Lua脚本需捕获并处理部分失败的情况 。</li><li><strong>网络优化</strong>:优先使用内网连接,减少延迟 。</li></ol>
<p class="maodian"><a name="_label6"></a></p><h2>七、执行方式对比</h2>
<table><thead><tr><th>方法</th><th>原子性</th><th>网络开销</th><th>适用场景</th><th>集群兼容性</th></tr></thead><tbody><tr><td>MSET</td><td>是</td><td>最低</td><td>简单键值批量设置</td><td>需哈希标签</td></tr><tr><td>Pipeline</td><td>否</td><td>低</td><td>高效非原子批量操作</td><td>需哈希标签或分片</td></tr><tr><td>Lua脚本</td><td>是</td><td>中</td><td>复杂逻辑或原子性要求高</td><td>需哈希标签</td></tr><tr><td>事务</td><td>否</td><td>中</td><td>顺序执行且需条件判断</td><td>需哈希标签</td></tr></tbody></table>
<p>选择建议:若无原子性要求,优先使用<strong>Pipeline</strong>;若需原子性且逻辑简单,使用<strong>Lua脚本</strong>。</p>
頁: [1]
查看完整版本: Redis批量操作的实现示例