Redis详解

📅 发布时间:2026/7/3 19:51:36 👁️ 浏览次数:
Redis详解
1.redis入门1redis的基本概念redis是一种开源的基于内存的和C/S高性能的键值型NoSQL的基本数据库。可以用作数据库缓存和消息中间的组件。端口号是6379。2关系型数据库非关系型关系型数据库 用 “表格” 存数据像 Excel 一样核心特点数据存在表table里表有固定的列字段结构必须提前定义支持SQL 语言查询强调事务、一致性、安全钱、订单、用户信息必须用它表和表之间可以关联外键典型代表MySQLOracleSQL ServerPostgreSQL优点数据安全、严谨、不会乱支持复杂查询、事务ACID适合存结构化数据用户、订单、商品缺点扩展性差大数据高并发吃力表结构改起来麻烦不适合存海量非结构化数据非关系型数据库 不用表格存灵活、快、高并发NoSQL Not Only SQL不仅仅是 SQL核心特点没有固定表结构想存什么存什么不强调严格关系追求快、高并发、海量存储数据模型灵活key-value、文档、列、图四大类你课件里也讲了KV 键值型Redis、Memcached文档型MongoDB列存储HBase图数据库Neo4j社交关系优点速度极快Redis 纯内存高并发轻松扛水平扩展强大数据轻松应对结构灵活随时加字段缺点事务、一致性不如关系型数据库不适合存特别严谨的数据如金融交易3redis的基本操作Redis默认有16个数据库默认使用的是第0个数据库可以通过select切换数据库。select切换数据库 格式select index127.2.2.16379 select 3 #切换数据库 OKdbsize查看数据的大小格式dbsize127.0.0.1:6379[3] DBSIZE # 查看数据库的大小 (integer) 0 127.0.0.1:6379[3] set name wangold OK 127.0.0.1:6379[3] set age 28 OK 127.0.0.1:6379[3] DBSIZE (integer) 2keys查看所有的 key格式keys *127.0.0.1:6379[3] KEYS * #查看所有的key 1) name 2) ageflushdb flushall清空当前数据库和清空所有的数据127.0.0.1:6379[3] FLUSHDB #清空当前数据库 OK 127.0.0.1:6379[3] KEYS * (empty array) 127.0.0.1:6379[3] FLUSHALL #清空所有的数据库 OK4为什么redis是单线程的redis是很快的官方标识redis是基于内存操作的cpu不是redis的性能瓶颈redis的瓶颈就是根据机器的内存和网络宽带既然可以使用单线程实现就使用单线程了。Redis为什么单线程还这么快误区1 高性能的服务器一定是多线程的误区2 多线程CPU上下文切换一定比单线程效率高核心 Redis是将所有的数据全部放在内存中的所以说使用单线程去操作效率就是最高的相比多线程减少了CPU上下文切换的耗时。对于内存系统来说没有上下文切换效率就是最高的多次读写都是在一个CPU上的。2.redis五个基本类型redis—key一、字符串String定义最基础类型key 字符串value 字符串 / 数字 / 二进制最大 512MB。1. 基础操作# 1. 设置键值对 SET name 张三 # 2. 获取值 GET name # 返回 张三 # 3. 不存在才设置分布式锁核心 SETNX lock 1 # 成功返回1失败返回0 # 4. 设置并指定过期时间秒 SETEX code 60 1234 # 60秒后自动删除 # 5. 批量设置/批量获取 MSET k1 v1 k2 v2 k3 v3 MGET k1 k2 k3 # 返回 v1 v2 v3 # 6. 删除键 DEL name2. 数值操作原子性高并发安全SET num 10 # 自增1 INCR num # 11 # 自减1 DECR num # 10 # 自增指定数字 INCRBY num 5 # 15 # 自减指定数字 DECRBY num 5 # 103. 高级操作# 追加字符串 APPEND name 李四 # name 变成 张三李四 # 获取字符串长度 STRLEN name # 覆盖指定位置字符串 SETRANGE name 2 666二、列表List定义有序、可重复、双向链表支持左右两边插入 / 弹出。1. 添加元素# 1. 左边插入头插 LPUSH fruits apple banana # 2. 右边插入尾插 RPUSH fruits orange grape # 3. 插入到某个元素前/后 LINSERT fruits before orange pear2. 查询元素# 1. 获取全部元素0开始-1最后 LRANGE fruits 0 -1 # 2. 获取列表长度 LLEN fruits # 3. 获取指定下标元素 LINDEX fruits 13. 删除 / 弹出元素# 1. 左边弹出删除第一个 LPOP fruits # 2. 右边弹出删除最后一个 RPOP fruits # 3. 删除指定个数的元素 LREM fruits 2 apple # 删除2个apple # 4. 保留指定区间其余删除 LTRIM fruits 0 24. 高级操作# 右边弹出并左边插入到另一个列表 RPOPLPUSH list1 list2三、哈希Hash定义keyfield-value 结构适合存对象用户、商品。1. 添加 / 修改字段# 1. 设置单个字段 HSET user:1001 name 张三 age 20 # 2. 批量设置 HMSET user:1001 phone 13800138000 sex 男2. 查询字段# 1. 获取单个字段 HGET user:1001 name # 2. 批量获取字段 HMGET user:1001 age phone # 3. 获取所有字段值 HGETALL user:1001 # 4. 获取所有字段名 HKEYS user:1001 # 5. 获取所有值 HVALS user:1001 # 6. 获取字段数量 HLEN user:10013. 删除 / 判断# 1. 删除指定字段 HDEL user:1001 sex # 2. 判断字段是否存在 HEXISTS user:1001 name # 3. 字段数值自增 HINCRBY user:1001 age 1四、集合Set定义无序、不可重复、自动去重支持交集 / 并集 / 差集。1. 添加 / 删除# 1. 添加元素 SADD tags java python redis # 2. 删除元素 SREM tags java # 3. 随机弹出一个元素 SPOP tags2. 查询元素# 1. 查看所有元素 SMEMBERS tags # 2. 判断元素是否存在 SISMEMBER tags python # 3. 集合大小 SCARD tags # 4. 随机获取元素不删除 SRANDMEMBER tags 23. 集合运算最强大功能SADD set1 a b c SADD set2 c d e # 1. 交集共同拥有 SINTER set1 set2 # c # 2. 并集合并去重 SUNION set1 set2 # a b c d e # 3. 差集set1有set2没有 SDIFF set1 set2 # a b五、有序集合Sorted Set / ZSet定义按 score 自动排序、不重复专门做排行榜。1. 添加 / 修改# 1. 添加元素score 在前value 在后 ZADD rank 95 张三 98 李四 88 王五 # 2. 修改分数 ZINCRBY rank 2 张三 # 952972. 排序查询核心# 1. 正序查询分数从低到高 ZRANGE rank 0 -1 WITHSCORES # 2. 倒序查询分数从高到低排行榜专用 ZREVRANGE rank 0 -1 WITHSCORES # 3. 获取元素分数 ZSCORE rank 李四 # 4. 获取元素排名正序/倒序 ZRANK rank 张三 # 正序排名 ZREVRANK rank 张三 # 倒序排名3. 统计 / 删除# 1. 删除元素 ZREM rank 王五 # 2. 统计分数区间数量 ZCOUNT rank 90 100 # 3. 删除指定排名区间元素 ZREMRANGEBYRANK rank 0 1 # 4. 删除指定分数区间元素 ZREMRANGEBYSCORE rank 80 903.redis的三种特殊类型一、Geospatial地理空间类型1. 核心定义专门用来存储地理位置信息经纬度并支持计算两地距离、查找指定范围内的地点等地理计算。底层原理本质是用ZSet有序集合实现的把经纬度编码成一个分数存储。2. 核心命令# 1. 添加地理位置经度、纬度、名称 GEOADD key 经度 纬度 名称 [经度 纬度 名称 ...] # 示例添加北京、上海、广州的坐标 GEOADD city 116.40 39.90 beijing 121.47 31.23 shanghai 113.27 23.13 guangzhou # 2. 计算两个地点之间的距离单位m/km/mi/ft GEODIST key 名称1 名称2 [单位] # 示例计算北京到上海的距离公里 GEODIST city beijing shanghai km # 3. 查找以某个坐标为中心指定半径内的所有地点 GEORADIUS key 经度 纬度 半径 单位 [WITHDIST] [WITHCOORD] # 示例查找以北京为中心1000公里内的城市 GEORADIUS city 116.40 39.90 1000 km # 4. 获取指定地点的经纬度 GEOPOS key 名称3. 适用场景附近的人、附近的门店美团 / 饿了么、微信附近的人打车软件计算司机与乘客距离地理围栏、位置推荐二、HyperLogLog基数统计类型1. 核心定义专门用来做基数统计统计一组数据中不重复元素的个数占用内存极小仅 12KB支持海量数据统计。特点有极小误差约 0.81%不存储原始数据只存统计结构适合不需要精确值的场景。2. 核心命令# 1. 添加元素 PFADD key 元素1 元素2 ... # 示例统计网站UV添加用户ID PFADD uv:20260331 user1 user2 user3 user1 # 2. 统计基数不重复元素数量 PFCOUNT key # 示例查询今日独立访客数 PFCOUNT uv:20260331 # 3. 合并多个HyperLogLog统计多天总UV PFMERGE destKey sourceKey1 sourceKey2 ... # 示例合并3天UV PFMERGE uv:total uv:20260330 uv:202603313. 适用场景统计网站 / APP独立访客UV统计页面日活、月活海量数据去重计数不要求 100% 精确三、Bitmap位图类型1. 核心定义本质是String 类型的特殊用法把字符串当成二进制位bit数组来用极致节省内存。1 个 Byte 8bit1MB 可以存储838 万 个 bit 位适合存储二状态数据是 / 否、0/1。2. 核心命令# 1. 设置指定位置的bit值0或1 SETBIT key offset value # 示例记录用户1001今日签到offset用户ID1已签到 SETBIT sign:20260331 1001 1 # 2. 获取指定位置的bit值 GETBIT key offset # 示例查询用户1001是否签到 GETBIT sign:20260331 1001 # 3. 统计key中bit为1的数量 BITCOUNT key [start end] # 示例统计今日总签到人数 BITCOUNT sign:202603313. 适用场景用户签到、打卡统计用户是否在线、是否已读黑名单 / 白名单快速判断海量用户状态标记4.事务一、Redis 事务核心特性一次性顺序性排他性执行一系列的命令MySQL 中的事务要么同时成功要么同时失败必须保证原子性Redis 单条命令是保证原子性的但是 Redis 的事务不保证原子性Redis 事务是没有隔离级别的概念1、Redis 的事务机制事务使用过程Redis 的事务使用分为三步开启事务 --multi命令入队 -- ......执行事务 --exec所有的命令在事务中并没有直接被执行只有发起执行命令的时候才会执行正常执行事务127.0.0.1:6379 multi # 开启事务 OK 127.0.0.1:6379 set k1 v1 # 命令入队 QUEUED 127.0.0.1:6379 set k2 v2 # 命令入队 QUEUED 127.0.0.1:6379 get k2 # 命令入队 QUEUED 127.0.0.1:6379 set k3 v3 # 命令入队 QUEUED 127.0.0.1:6379 exec # 执行事务 1) OK 2) OK 3) v2 4) OK放弃事务 discard127.0.0.1:6379 multi OK 127.0.0.1:6379 set k1 v1 QUEUED 127.0.0.1:6379 set k2 v2 QUEUED 127.0.0.1:6379 set k4 v4 QUEUED 127.0.0.1:6379 discard # 放弃事务 OK 127.0.0.1:6379 get k4 # 事务队列中的命令都不会执行 (nil)编译型异常命令有错事务中所有的命令都不会被执行127.0.0.1:6379 keys * (empty array) 127.0.0.1:6379 multi OK 127.0.0.1:6379 set k1 v1 QUEUED 127.0.0.1:6379 getset k2 # 命令不正确 (error) ERR wrong number of arguments for getset command 127.0.0.1:6379 set k3 v3 QUEUED 127.0.0.1:6379 exec # 执行事务时其他命令也不会执行 (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379 get k1 (nil) 127.0.0.1:6379 get k3 (nil)执行时异常如果事务队列中存在语法性错误执行命令的时候其他命令可以正常执行错误命令抛出异常127.0.0.1:6379 keys * (empty array) 127.0.0.1:6379 set k1 v1 OK 127.0.0.1:6379 multi OK 127.0.0.1:6379 incr k1 # 会执行的时候失败 QUEUED 127.0.0.1:6379 set k2 v2 QUEUED 127.0.0.1:6379 set k3 v3 QUEUED 127.0.0.1:6379 get k2 QUEUED 127.0.0.1:6379 exec # 执行事务是第一个命令执行出错其他命令依旧会执行 1) (error) ERR value is not an integer or out of range 2) OK 3) OK 4) v2 127.0.0.1:6379 get k2 v22、Redis 的乐观锁 Watch悲观锁 乐观锁悲观锁很悲观认为什么时候都会出问题无论做什么都会加锁但是影响效率乐观锁很乐观认为什么时候都不会出问题所以不会加锁更新数据时去判断一下在此期间是否有人修改过这个数据MySQL 的 version 的使用先获取 version更新数据时比较 version看 version 是否被修改Redis 的监视测试1、正常执行成功127.0.0.1:6379 set money 100 OK 127.0.0.1:6379 set out 0 OK 127.0.0.1:6379 watch money #监视money对象 OK 127.0.0.1:6379 multi #事务正常结束数据期间没有发生变动这个时候就正常执行成功 OK 127.0.0.1:6379 decrby money 20 QUEUED 127.0.0.1:6379 incrby out 20 QUEUED 127.0.0.1:6379 exec 1) (integer) 80 2) (integer) 202、多线程修改值使用 watch 可以当做 Redis 的乐观锁操作A 客户端执行命令集合127.0.0.1:6379 get money 80 127.0.0.1:6379 set money 1000 OKB 客户端执行命令集合127.0.0.1:6379 watch money OK 127.0.0.1:6379 multi OK 127.0.0.1:6379 DECRBY money 10 QUEUED 127.0.0.1:6379 INCRBY out 10 QUEUED 127.0.0.1:6379 exec # 在该命令执行之前A客户端执行了set命令修改了money的值就会导致事务执行失败 (nil)watch 监视下的事务执行失败后可以 unwatch 解锁在重新开始监视127.0.0.1:6379 UNWATCH #事务执行失败先解锁 OK 127.0.0.1:6379 WATCH money #获取最新的值再次监视 OK 127.0.0.1:6379 multi OK 127.0.0.1:6379 DECRBY money 10 QUEUED 127.0.0.1:6379 INCRBY out 10 QUEUED 127.0.0.1:6379 exec # 比对监视的值是否发生变化如果没有变化可以执行成功如果变量被修改了执行失败 1) (integer) 990 2) (integer) 30