结论:Redis本身没有传统数据库的二级索引,但通过Hash、Sorted Set、List等数据结构巧妙模拟索引,能极大提升查询效率。实战技巧:1.用Hash存储对象,HGET快速查单条;2.Sorted Set按score排序,ZREVRANGE分页;3.复合键如user:uid:field避key爆炸;4.GEO用GEORADIUS查附近;5.结合Lua脚本原子操作防并发。示例代码:
redis.call('HSET', 'user:1001', 'name', '张三', 'age', 25)
redis.call('ZADD', 'user:score', 95, '1001')
local users = redis.call('ZREVRANGE', 'user:score', 0, 9, 'WITHSCORES')这样查询从O(n)降到O(log n),实战中用户搜索延迟从500ms降到20ms。来源1
在Redis中,索引策略的核心是选择合适的数据结构。 对于频繁精确查找的场景,使用Hash结构是最优选择。例如,用户信息存储在hash中,键为user:{id},字段为name、age等,通过HGET或HMGET可以O(1)时间获取。实战中,我们为电商订单系统设计了order:{orderId}的hash,包含status、userId等字段,查询订单详情只需一条命令,效率远超JSON字符串解析。
来源2
Sorted Set是实现排序索引的神器。以用户积分排行为例,ZADD user:rank {score} {userId},然后ZREVRANGE 0 99 WITHSCORES即可获取前100名。注意score要设计为时间戳+积分,避免重复。我们的游戏系统中,这个策略支撑了百万级在线玩家的实时排行,峰值QPS达10w+。
来源3
复合索引键设计至关重要。单纯用user:name张三会key爆炸,改为user:name:张三:uid:123能唯一标识。List用于时间线索引,如user:feed:{uid} LPUSH tweetId,实现朋友圈倒序加载。结合EXPIRE设置TTL,内存自动清理。
来源4
GEO索引实战:ZADD china:city:beijing 116.40 39.90 "location1",然后GEORADIUS china:city:beijing 116.40 39.90 10000 km查10km内位置。外卖平台用此实现商家附近搜索,结合ZREVRANGEBYSCORE按距离排序,响应时间稳定在50ms内。
来源5
二级索引模拟:用Set维护反向索引,如article:tag:tech → {art1,art2},tag:tech:art1 → {tagId}双向关联。搜索时SINTER取交集。博客系统用此,标签搜索准确率100%,比全文搜索快10倍。但Set内存大,要评估规模。
来源6
分页查询技巧:避免SCAN全遍历,用Sorted Set的ZRANGE 0 9、10 19分段。Lua脚本封装:
local page = ARGV[1]
local size = ARGV[2]
local start = (page-1)*size
return redis.call('ZRANGE', KEYS[1], start, start+size-1)商城商品列表用此,百万数据下第100页查询也只需1ms。来源7
缓存穿透&雪崩防范索引:用布隆过滤器模拟存在索引,BloomFilter.add(key),exists(key)预判。结合索引键的TTL随机化,实战中Redis压力降80%。
FAQ
Q: Redis Hash字段上限是多少?
A: 2^32-1个字段,够用,但建议单hash不超过100字段防内存碎片。
Q: Sorted Set适合模糊查询吗?
A: 不适合,ZSCAN支持但慢,用外部ES结合Redis。
Q: 如何处理高并发更新索引?
A: Lua脚本原子执行,或pipeline批量提交。
Q: GEO精度如何?
A: 经纬度double精度,误差米级,城市级应用足够。
Q: 索引key命名规范?
A: 业务:类型:唯一id,如user:profile:12345。