【SSDB】【python】删除千万级zset大key

背景

最近接到需求,要删除ssdb中一个8000+w个member的zset。
该SSDB架构为双主模式+Keepalived构建的高可用。
处理时长要求在一天内完成。

相关SSDB-API

  • zrange:zrange name offset limit,根据下标索引区间 [offset, offset + limit) 获取 key-score 对, 下标从 0 开始. zrrange 是反向顺序获取.(注意! 本方法在 offset 越来越大时, 会越慢!)

  • zkeys:zkeys name key_start score_start score_end limit,列出 zset 中的 key 列表

  • zscan:zscan name key_start score_start score_end limit,列出 zset 中处于区间 (key_start+score_start, score_end] 的 key-score 列表. 如果 key_start 为空, 那么对应权重值大于或者等于 score_start 的 key 将被返回. 如果 key_start 不为空, 那么对应权重值大于 score_start 的 key, 或者大于 key_start 且对应权重值等于 score_start 的 key 将被返回.也就是说, 返回的 key 在 (key.score == score_start && key > key_start || key.score > score_start), 并且key.score <= score_end 区间. 先判断 score_start, score_end, 然后判断 key_start._,("", “”] 表示整个区间.

  • zclear:zclear name,删除 zset 中的所有 key.

  • zremrangebyscore:zremrangebyscore name start end,删除权重处于区间 [start,end] 的元素.

  • zremrangebyrank:zremrangebyrank name start end,删除位置处于区间 [start,end] 的元素.

  • zdel:zdel name key,获取 zset 中的指定 key.

  • multi_zdel :multi_zdel name key1 key2 …,批量删除 zset 中的 key.

Redis与SSDB命令映射表

在这里插入图片描述

解决思路

  • 思路1:通过zclear直接删key

  • 思路2:遍历zset的member(zkeys、zrange、zscan),然后删除member(zdel)

  • 思路3:通过删除排名的方式进行删除(zremrangebyrank)

最终方案

使用思路3,但是为了记录删除数据,使用了zrange+zdel+pipeline的方法,具体实现如下。
在从库中进行操作。

demo

#encoding: utf-8
import redis

def del_big_zset(rip, rport, passwd, key)
	rpool = redis.ConnectionPool(host = rip, port = rport, db = 0, password = passwd)
	r = redis.Redis(connection_pool=rpool)
	pipeline = r.pipeline(transaction=False)
	count  = 0
	key_size = r.zcard(key)
	start = 0
	end = 1000
	while(key_size > 1):
		member_list = r.zrange(name=key,start=start,end=end)
		for member in member_list:
			print "%s" % (member)
			pipeline.zrem(key, member)
		result = pipeline.execute()
		key_size = r.zcard(key)

效果

每秒清除速度是5k左右,最终预计5小时内完成清理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章