☰
Redis使用及数据结构
2026/9/29 18:24:09 网站建设 项目流程

Redis跟Mysql性能比较

Reids是基于内存的非关系性数据,而mysql的数据存在磁盘上,所以redis性能普遍高于mysql。但读写性能还受硬件、配置、数据大小、持久化策略、事务、是否集群、是否锁冲突等影响。普遍的认为单机redis一般支持10万级并发读写,mysql只到万级。对于同一热点数据(同一个key或同一行数据),redis单线程排队而mysql需要加锁阻塞,redis依旧支持万级QPS而mysql只支持几百。

Redis的基本命令

安装Redis后,会同步安装一个客户端(reids-cli),客户端可以只接启动,然后在客户端中对redis数据库进行操作。

key操作:

# 查看key是否存在,返回1存在0不存在 exists key # 删除key,支持多个 del key1 key2 # 设置过期时间(秒)expire key60# 设置过期时间(毫秒)pexpire key60000# 查看剩余过期秒数,-1永不过期,-2已删除 ttl key pttl key # 查看key类型 type key # 模糊匹配key,⚠️生产禁止线上用,会阻塞redis keys user*# 安全遍历key,游标迭代 scan0match user*count100# 重命名key rename oldnew# 持久化:把key从内存刷RDB,不用手动执行

String 字符串(最常用,缓存、计数、分布式锁)

# 设置 set k1 v1 # 设置+过期时间,原子 set k1 v1 ex30# 仅key不存在才设置(分布式锁NX)set k1 v1 nx ex10# 仅key存在才设置 set k1 v1 xx # 获取 get k1 # 批量 mget k1 k2 k3 mset k1 v1 k2 v2 # 数字自增,原子计数 incr num incrby num10decr num decrby num5# 追加字符串 append k1"_suffix"# 获取字符串长度 strlen k1

Hash 哈希(对象存储,user:{id})

# 左边插入(头) lpush list1 a b c # 右边插入(尾) rpush list1 d e # 左边弹出 lpop list1 # 右边弹出 rpop list1 # 阻塞弹出,没有数据就等待秒数,消息队列 blpop list110brpop list110# 指定下标取值,下标从0开始 lindex list10# 区间获取[start,end],-1代表最后一个 lrange list10-1# 裁剪list,只保留区间,用于限流队列 ltrim list1099# list长度 llen list1

Set 集合,无序不重复(去重、交集并集)

# 添加 sadd set1 a b c a # 查询全部元素 smembers set1 # 判断是否存在 sismember set1 a # 删除元素 srem set1 b # 随机取元素 srandmember set12# 随机弹出 spop set1 # 集合运算 sinter set1 set2 # 交集 sunion set1 set2 # 并集 sdiff set1 set2 # 差集 # 元素数量 scard set1

List 列表,双向链表(队列、栈)

# 左边插入(头) lpush list1 a b c # 右边插入(尾) rpush list1 d e # 左边弹出 lpop list1 # 右边弹出 rpop list1 # 阻塞弹出,没有数据就等待秒数,消息队列 blpop list110brpop list110# 指定下标取值,下标从0开始 lindex list10# 区间获取[start,end],-1代表最后一个 lrange list10-1# 裁剪list,只保留区间,用于限流队列 ltrim list1099# list长度 llen list1

ZSet 有序集合,score 权重(排行榜、延时队列)

# 添加 member 带score分数 zadd rank100user195user298user3 # 正序查询[start end],从小到大 zrange rank0-1# 带上分数 zrange rank0-1withscores # 倒序,从大到小(排行榜) zrevrange rank0-1withscores # 根据分数范围查询 zrangebyscore rank90100# 删除成员 zrem rank user1 # 获取成员排名 zrank rank user2 zrevrank rank user2 # 分数自增 zincrby rank5user2 # zset元素总数 zcard rank # 指定分数区间数量 zcount rank90100

全局服务命令

# 选择数据库0‑15,默认db0 select1# 清空当前库,危险 flushdb # 清空全部库,非常危险 flushall # 查看信息,cpu、内存、持久化、客户端 info info memory info stats # 查看当前连接客户端 client list # 持久化触发 bgsave # 后台生成RDBbgrewriteaof #AOF重写 # 测试连通 ping

info命令查看持久化相关信息命令:info persistence
返回示例:

#Persistenceloading:0rdb_changes_since_last_save:0# 上次RDB之后改动key数量 rdb_bgsave_in_progress:0rdb_last_save_time:1756234000# 上次成功bgsave的时间戳 rdb_last_bgsave_status:ok # ok代表RDB成功 rdb_last_bgsave_time_sec:0rdb_current_bgsave_time_sec:-1rdb_enabled:1#RDB功能是否开启(save配置是否存在) aof_enabled:0#0=AOF关闭;1=AOF开启 aof_rewrite_in_progress:0aof_rewrite_scheduled:0aof_last_rewrite_time_sec:-1aof_current_rewrite_time_sec:-1aof_last_bgrewrite_status:ok aof_last_write_status:ok aof_last_fsync:everysec # appendfsync策略:everysec/always/no

查看rdb持久化规则:config get save

127.0.0.1:6379>config get save1)"save"2)"900 1 300 10 60 10000"# 表示900s内改动key至少为1个 或300s内至少10个 或60s内至少10000个 则触发rdb持久化

若返回""则表示RDB 自动快照关闭,不会自动 bgsave;但你依然可以手动执行bgsave生成 rdb 文件。

Redis Bitmap(位图)

Bitmap 不是独立数据类型,底层就是String 字符串,按 bit(位)操作。一个 key 的字符串最多 512MB,对应2^32个 bit,约 42.9 亿位。

1 byte = 8 bit;100 万用户只需要~125KB 内存。
典型场景:用户签到、日活统计、是否访问、布尔标记、去重。

以统计用户签到为例,一个二进制位代表一个用户,每个日期存一个bitmap,统计当前日期已签到用户,已签到对应二进制位存1否则存0。若用户id已满足自增可直接使用用户id,若用户ID非自增或偏移量较大(如ID从1000000开始),可以考虑通过hashcode方式映射,但hash映射方式可能出现hash冲突导致统计异常。要想统计准确可以单独添加用户id和自增id的映射表,保证用ID从1开始。

核心命令

1. setbit 设置位

# setbit key offset value # offset:位下标,从0开始;value只能0/1setbit sign:202609011001

含义:把offset=100的位设置为 1,代表 id=100 用户今天签到。

offset 可以非常大,中间未设置的位默认是 0。

2. getbit 获取某一位

getbit sign:20260901100

返回0/1;判断用户 100 是否签到。

3. bitcount 统计为 1 的总数(统计签到人数)

# 统计整个key里面值为1的bit总数 bitcount sign:20260901# 按字节范围统计,start、end 是**字节偏移**,不是bit! bitcount sign:202609010100

⚠️注意:start end 单位是字节 (byte),不是 bit,不要搞错。

4. bitop 位图运算(与、或、异或、非)

做多天签到合并、多日活跃用户统计

# bitop op destkey key1 key2...# op:AND(与)OR(或)XOR(异或)NOT(非)#OR:任意一天签到过的用户,结果存入 sign:all bitopORsign:all sign:20260901sign:20260902sign:20260903#AND:三天全部都签到的用户 bitopANDsign:all sign:20260901sign:20260902sign:20260903

bitop 会生成新 key,运算量大,大 bitmap 会阻塞 redis,线上谨慎。

5. bitpos 查找第一个 0/1 的位置

# 找第一个值为1的bit下标 bitpos sign:202609011# 找第一个0bitpos sign:202609010

HyperLogLog

HyperLogLog(简称 HLL)是 Redis 用来做基数统计的数据结构。

基数:集合中不重复元素的个数。例如集合{1,2,2,3},基数 = 3。

核心特性

  1. 不存储原始数据,只存概率统计估算值;
  2. 空间极小:每个 HLL key 只占用约12KB内存,最多统计 264个元素;
  3. 结果是估算值,有误差:标准误差 0.81%;
  4. 适合大数据量去重计数,不适合要拿到原始元素的场景。

使用场景

  1. 统计页面 UV、每日独立访客(海量用户,不需要精确值,容忍小误差)
  2. 直播观看人数、活动去重访问量
  3. 多维度去重统计合并(PFMERGE合并多天、多渠道)

数据结构

整体结构 =HLL 头(hllhdr) + 寄存器数据区,寄存器区有两种编码:稀疏编码 (Sparse)、密集编码 (Dense),Redis 自动动态转换

struct hllhdr{charmagic[4];// 魔术标记 "HYLL",标识这是HLL结构uint8_t encoding;// 编码:0=DENSE密集,1=SPARSE稀疏uint8_t notused[3];// 保留3字节,预留扩展,恒为0uint8_t card[8];// 基数缓存,小端序;最高1bit标记缓存是否有效,低63bit存上次PFCOUNT结果uint8_t registers[];// 柔性数组:寄存器数据区};

参数常量:

  • HLL_P =14→ 桶数量 (M=214=16384) 个寄存器(桶)
  • HLL_BITS=6:每个寄存器占6bit,最大存 63,足够保存最多 50 位哈希的前导零最大值。

总大小:

(16384 ×6bit ÷8 =12288字节 =12KB)
加上头部 16 字节,完整对象约12KB+

编码切换时机

  • 初始化:默认稀疏编码
  • 触发转密集:
    1. PFADD 导致某个寄存器值 > 32
    2. 稀疏编码自身占用超过阈值

底层原理简要

HyperLogLog 基于伯努利试验+ 调和平均数估算基数:

  1. 对输入元素做 hash,得到 64bit 哈希值;
  2. 低 14 位用来选桶(Redis HLL 一共 16384 个桶,(214=16384));
  3. 剩余高位计算前导 0 的个数,每个桶记录该桶出现过最大前导 0 数量,(前导0越多,表明出现该数的概率越小,基数就越多。相同基数由于hash一样,选择的桶一样,前导0的个数也一样所以总的基数不会更新);
  4. 最后对 16384 个桶的值做调和平均,修正偏差,估算出总基数。
  • 桶数量固定 16384,所以内存固定约 12KB;
  • 误差来源是概率估算,标准误差 0.81%;
  • Redis HLL 内部有稀疏、稠密两种编码:数据少时用稀疏编码占用更小,超过阈值自动转为稠密(12KB)。

使用示例

统计某个页面每天的访问次数

# 添加访问用户idPFADDuv:20260902user1 user2 user3 user2 user1 # 统计今日UV(去重用户数)PFCOUNTuv:20260902# 合并两天UV到新keyPFMERGEuv:total uv:20260901uv:20260902PFCOUNTuv:total

GEO

Redis 3.2 新增 GEO,用于存储经纬度、计算距离、查询附近点位;底层没有新数据结构,基于 ZSet(有序集合)+ GeoHash 算法实现

典型业务场景

  1. LBS 业务:附近门店、附近商家、附近的人;
  2. 配送业务:骑手、车辆位置,计算两点距离;
  3. 简单地理围栏(小数据量)。

核心命令

1. GEOADD 添加点位

# key 经度 纬度 member GEOADD shop:geo 104.06 30.67 shop‑001 104.07 30.68 shop‑002

2. GEOPOS 获取 member 的经纬度

GEOPOS shop:geo shop‑001 shop‑002

3. GEODIST 计算两点球面距离

单位:m米 (默认)、km千米、mi英里、ft英尺

GEODIST shop:geo shop‑001 shop‑002 km

4. GEOHASH 获取 geohash 字符串

GEOHASH shop:geo shop‑001

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询