# 本节要点 - 认识什么是Redis - 为什么要用Redis - 理解非结构化数据 - window和linux下Redis安装和配置 - 五大数据类型与使用场景 # 一、什么是redis https://redis.io/ !\[image-20260130095358889\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20260130095359006.png) !\[image-20251011221939828\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/java/daiwei/20251011221939908.png) 就是一个数据库 - 基于内存访问的数据库 - 非机构化,NoSql - 支持多种数据结构(string ,hash,list,set,zset,graph,空间数据,ai向量...) \*\*一句话:Redis是一个基于内存、支持持久化的键值(KV)数据库,它提供多种数据结构,并广泛用于缓存、消息队列等场景。\*\* # 二、为什么要用redis - 数据库连接资源很宝贵,不让大量的查询请求打在数据库上 - 内存访问速度快 - 提供了多种数据结构,直接使用 - 分布式系统,分布式锁 # 三、和传统数据库的区别 \| \| SQL \| NoSQL \| \| -------- \| ------------------------ \| ---------------------------- \| \| 数据结构 \| 结构化 \| 非结构化 (json) \| \| 数据关系 \| 强关联性 \| 非强关联 \| \| 查询方式 \| SQL \| 非sql \| \| 事务 \| ACID \| BASE \| \| 使用场景 \| 数据结构固定,数据安全高 \| 数据结构不固定,对性能要求高 \| # !\[image-20260130103710409\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20260130103710471.png) # 四、使用场景(重点) 1、因为redis是内存范围读,速度非常快;并且可以持久化;非结构化存储方式;\*\*在高并发的时候,不让大量的请求直接打在数据库上,避免数据库宕机。\*\* 2、redis可以有分布式锁,在高并发、高可用、高性能的数据安全和一致性。 3、redis里有很多的数据结构,可以直接使用 # 五、redis安装 - \*\*linux\*\* https://download.redis.io/releases/下载 !\[image-20251204163833477\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251204163833548.png) 解压 \`\`\` tar -xzvf redis-6.2.20.tar.gz \`\`\` 进入redis目录编译,主要目的生成可以执行的启动文件 \`\`\` make \`\`\` 修改配置redis.conf \`\`\` bind 0.0.0.0 port 6379 daemonize yes #代表是否后台启动,如果是yes,控制台就没有日志,会把日志打印到文件里 databases 16 requirepass 123456woniu \`\`\` 启动 \`\`\` ./redis-server ../redis.conf \`\`\` 连接 \`\`\` ./redis-cli -h localhost -p 6379 -a 密码 \`\`\` 看看是否zhengchang \`\`\` ping //会返回pong \`\`\` 查看一下服务器情况 \`\`\` Info server \`\`\` - \*\*window\*\* https://github.com/redis-windows/redis-windows/releases !\[image-20251012114342237\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/java/daiwei/20251012114349418.png) - 配置文件redis.conf !\[\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/java/daiwei/20251012114454609.png) !\[image-20251012114829275\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/java/daiwei/20251012114829352.png) - 开启所有ip都可以连接 \`\`\` bind 127.0.0.1 -::1 改为 bind 0.0.0.0 \`\`\` - 数据库配置 !\[image-20251014102250177\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251014102250223.png) - 端口 !\[image-20251014102353168\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251014102353205.png) - 开启后台启动 !\[image-20251012114952730\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/java/daiwei/20251012114952800.png) - 添加密码 !\[image-20251012115249487\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/java/daiwei/20251012115249585.png) - 启动 \`\`\` redis-server.exe redis.conf \`\`\` !\[image-20251012115913553\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/java/daiwei/20251012115913689.png) 测试连接 \`\`\` redis-cli.exe -h localhost -p 6379 -a 123456 //-h 代表的主机地址 -p代表的是端口 -a 代表的是密码 auth \`\`\` !\[image-20260130102225798\](C:\\Users\\daiwei\\AppData\\Roaming\\Typora\\typora-user-images\\image-20260130102225798.png) # 六、Redis常用数据结构(重点) \| 类型 \| 说明 \| \| \| --------------- \| -------------------------- \| ---- \| \| 字符(String) \| 存储字符串 \| \| \| 哈希(hash) \| 存储字段对应值的映射 \| \| \| 列表(list) \| 有序的列表 \| \| \| 集合(sets) \| 不重复的集合 \| \| \| 有序集合(zsets) \| 比集合多了一个分数用于排序 \| \| Graph bitmap stream GEO Vector ## 1、字符串String K=name V=值 \*\*常见指令\*\* - SET:添加或者修改已经存在的一个 String 类型的键值对 \`\`\` set username daiwei username ,value是 daiwei \`\`\` - GET:根据 key 获取 String 类型的 value \`\`\` get username 获取key是session的值 \`\`\` - MSET:批量添加多个 String 类型的键值对 \`\`\` mset user1 daiwei user2 liuxianrong user3 maguilin \`\`\` - MGET:根据多个 key 获取多个 String 类型的 value \`\`\` mget user1 user2 user3 \`\`\` - INCR:让一个整型的 key 自增 1 \`\`\` set num 1 \`\`\` \`\`\` INCR num \`\`\` - INCRBY: 让一个整型的 key 自增并指定步长,例如:incrby num 2 让 num 值自增 2 \`\`\` INCRBY num 10 \`\`\` - INCRBYFLOAT:让一个浮点类型的数字自增并指定步长 \`\`\` INCRBYFLOAT floatnum 9.9 \`\`\` - SETNX:添加一个 String 类型的键值对,前提是这个 key 不存在,否则不执行 \`\`\` SETNX lock lock \`\`\` - SETEX:添加一个 String 类型的键值时,并且指定有效期 \`\`\` SETEX procut_name 30 apple17 \`\`\` - EXPIRE:单独设置过期时间 EXPIRE key time \`\`\` EXPIRE lock 15 #设置过期时间 \`\`\` - TTL:查看过期时间 TTL key \`\`\` TTL lock 查看时间 \`\`\` \*\*使用场景\*\* !\[image-20251205101812194\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205101812270.png) 存储token、分布式锁、记数... \*\*问题\*\* 同样的key,如何避免重复? 可以用和业务贴切的目录结构来定义key 比如 :com:woniu:user:1 woniu !\[image-20251014101350098\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251014101350150.png) ## 2、哈希Hash 说明:hash散列,\*\*无序列\*\*,类似java的hashmap com:douyin:user:1000 app17 1 !\[image-20251011233834832\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/java/daiwei/20251011233834943.png) \*\*使用场景\*\* \*\*购物车、商品信息、用户信息...\*\* \*\*常见命令\*\* - HSET key field value:添加或者修改 hash 类型 key 的 field 的值 \`\`\` hset com:woniu:user:1000 name daiwei 代表存放的 主KEY是com:woniu:user:1000,name代表的是字段 ,daiwei是值 \`\`\` - HGET key field:获取一个 hash 类型 key 的 field 的值 \`\`\` hget com:woniu:user:1000 name 获取主KEY里的,某一个属性(字段) \`\`\` - HMSET:批量添加多个 hash 类型 key 的 field 的值 \`\`\` hmset com:woniu:user:1001 name woniu age 18 mobile 1388888 email xx@qq.com \`\`\` - HMGET:批量获取多个 hash 类型 key 的 field 的值 \`\`\` hmget com:woniu:user:1001 name age mobile email \`\`\` !\[image-20251205122754373\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205122754416.png) - HGETALL:获取一个 hash 类型的 key 中的所有的 field 和 value \`\`\` hgetall com:woniu:user:100 返回这个key所有的数据 \`\`\` !\[image-20251205110120880\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205110120927.png) - HKEYS:获取一个 hash 类型的 key 中的所有的 field \`\`\` hkeys com:woniu:user:1000 只返回 name \`\`\` !\[image-20251205122011011\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205122011055.png) - HVALS:获取一个 hash 类型的 key 中的所有的 value \`\`\` hvals com:woniu:user:1000 返回value \`\`\` !\[image-20251205122016569\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205122016612.png) - HINCRBY:让一个 hash 类型 key 的字段值自增并指定步长 \`\`\` HINCRBY com:woniu:user:1000 age 1 把年龄加1 \`\`\` !\[image-20251205122109343\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205122109379.png) - HSETNX:添加一个 hash 类型的 key 的 field 值,前提是这个 field 不存在(返回1),否则不执行(返回0) ## 3、List链表队列 说明:redis里的list是一个双向链表 !\[image-20251011233553529\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/java/daiwei/20251011233553622.png) 队列-\>先进先出 栈-\>先进后出 - LPUSH key element ...:向列表左侧插入一个或多个元素 \`\`\` LPUSH newlist title_1 title_2 title3 title_4 #把一些文章的推送放在链表里面 \`\`\` - LPOP key:移除并返回列表左侧的第一个元素,没有则返回 nil \`\`\` LPOP newlist #左移除 \`\`\` !\[image-20251205123042497\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205123042543.png) - LRANGE key star end:返回一段角标范围内的所有元素 \`\`\` LRANGE newlist 0 -1 \`\`\` !\[image-20251205123015855\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205123015901.png) - RPUSH key element ...:向列表右侧插入一个或多个元素 \`\`\` RPUSH right_newlist video_1 video_2 video_3 video_4 #把一些视频的推送放在链表里面 \`\`\` !\[image-20251205123210771\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205123210814.png) - RPOP key:移除并返回列表右侧的第一个元素 \`\`\` RPOP right_newlist \`\`\` !\[image-20251205123315336\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205123315384.png) - BLPOP 和 BRPOP:与 LPOP 和 RPOP 类似,只不过在没有元素时等待指定时间,而不是直接返回 nil ## 4、集合SET Set里的数据是唯一的,\*\*无序不重复\*\*,java里的HashSet相似 !\[image-20251011235954054\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/java/daiwei/20251011235954136.png) \*\*使用场景:\*\* 用户抽奖、存放不重复的数据... \*\*常见命令\*\* - SADD key member ...:向 set 中添加一个或多个元素 \`\`\` sadd com:woniu:friend aaa bbb ccc ddd 把朋友加入集合(不重复) \`\`\` !\[image-20251205123423945\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205123423994.png) - SREM key member ...:移除 set 中的指定元素 \`\`\` srem com:woniu:friend ccc \`\`\` !\[image-20251205123417657\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205123417696.png) - SCARD key:返回 set 中元素的个数 \`\`\` scard com:woniu:friend #3个 \`\`\` !\[image-20251205123445846\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205123445888.png) - SISMEMBER key member:判断一个元素是否存在于 set 中 \`\`\` SISMEMBER com:woniu:friend aaa "1" SISMEMBER com:woniu:friend ccc "0" \`\`\` !\[image-20251205123557804\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205123557856.png) - SMEMBERS:获取 set 中的所有元素 SMEMBERS com:woniu:friend !\[\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205123637913.png) - SINTER:key1 key2 交集 \`\`\` sadd com:woniu:friend_a ddd eee fff 再创建一个 com:woniu:friend_a 包含 ddd eee fff \`\`\` 求一下交际,两个人共同的朋友 \`\`\` sinter com:woniu:friend com:woniu:friend_a \`\`\` !\[image-20251205124005847\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205124005898.png) - SUNION key1 key2 并集 \`\`\` sunion com:woniu:friend com:woniu:friend_a \`\`\` !\[image-20251205124039158\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205124039203.png) - SDIFF : key1 key2 (key1有的key2没有的) \`\`\` sdiff com:woniu:friend com:woniu:friend_a \`\`\` - SPOP key 随机移除 \`\`\` spop com:woniu:friend \`\`\` ## 5、ZSET 可排序的数据类型,\*\*有一个score值\*\*,可以设置这个值 \*\*常用命令\*\* - ZADD key score member:添加一个或多个元素到 sorted set,如果已经存在则更新其 score 值 \`\`\` zadd top10 50 xiaoming 60 zhangsan 70 wangwu 20 lisi 90 zz 85 dw \`\`\` - ZREM key member:删除 sorted set 中的一个指定元素 \`\`\` zrem top10 dw \`\`\` - ZSCORE key member:获取 sorted set 中的指定元素的 score 值 \`\`\` zscore top10 zz \`\`\` !\[image-20251205124322535\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205124322588.png) - ZRANK key member:获取 sorted set 中的指定元素的排名 \`\`\` zrank top10 zz \`\`\` !\[image-20251205124354139\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205124354188.png) - ZCARD key:获取 sorted set 中的元素个数 \`\`\` zcard top10 \`\`\` !\[image-20251205124412928\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205124412975.png) - ZRANGE key min max:按照 score 排序后,获取指定排名范围内的元素 下表0代表第一个元素(score从底到高) \`\`\` zrange top10 0 -1 #-1代表全部 注意下表从0开始的 \`\`\` !\[image-20251205124433766\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205124433807.png) - ZREVRANGE key min max: 通过索引区间返回有序集合成指定区间内的成员(score 从高到低) withscores \`\`\` ZREVRANGE top10 0 -1 withscores #加上 withscores展示分数,确认排序是否正确 \`\`\` !\[image-20251205124556644\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251205124556703.png) - zunionstore zsetkey num set1 set 2 setn ... zunionstore 可以把日排行,整合成周排行, zsetkey代表的是生成周榜的key num代表有多少个日榜来生成周榜 set1 \~setn 代表 和 num匹配的日榜集合 范例如下: \`\`\` zadd day1top10 1 a 2 b 3 c 4 d 5 e zadd day2top10 10 a 26 b 3 c 4 d 5 e zadd day3top10 66 a 32 b 1 c 14 d 5 e zunionstore week1top10 3 day1top10 day2top10 day3top10 \`\`\` \*\*使用场景\*\* 各种排行榜... # 七、Redis常用命令 ## 1、keys 慎用!阻塞! \`\`\` keys \* 查询所有的key \`\`\` !\[image-20251012001403966\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/java/daiwei/20251012001404031.png) 模糊查询 \`\`\` keys \*x\* \`\`\` scan - \`0\`:起始游标。 - \`MATCH user:session:\*\`:匹配模式,与 \`KEYS\` 相同。 - \`COUNT 10\`:\*\*建议\*\*每次返回的键数量。这只是一个\*\*提示\*\*,Redis可能会返回更多或更少的元素,但大体上会遵循这个数量级。 \`\`\` # 开始一次迭代,游标从0开始 127.0.0.1:6379\> SCAN 0 MATCH user:session:\* COUNT 10 1) "17" # 下一个迭代的游标 2) 1) "user:session:12345" 2) "user:session:67890" # 使用返回的游标 "17" 继续迭代 127.0.0.1:6379\> SCAN 17 MATCH user:session:\* COUNT 10 1) "0" # 游标为0,表示迭代结束 2) 1) "user:session:abcde" 2) "user:session:fghij" \`\`\` ## 2、DEL删除 1代表删除成功,0代表失败或没有 \`\`\` del num \`\`\` ## 3、EXISTS是否存在 0表示没有,1表示有 \`\`\` exists num \`\`\` ## 4、EXPIRE设置过期时间 \`\`\` EXPIRE num 30 \`\`\` ## 5、TTL查看过期时间 \`\`\` TTL num \`\`\` ## 6、事务 \`\`\` MULTi开启事务 EXEC执行事务 DISCARD 取消 \`\`\` ## 7、发布 / 订阅(Pub/Sub) 实现简单的mq功能 SUBSCRIBE:订阅给定的一个或多个频道的信息。 \`\`\` SUBSCRIBE xxx \`\`\` PUBLISH:将信息发送到指定的频道。 \`\`\` PUBLISH xxx content \`\`\` ## 8、备份命令 \`\`\` # 保存 RDB 快照(如果配置了) 127.0.0.1:6379\> SAVE # 或者后台保存 127.0.0.1:6379\> BGSAVE \`\`\` ## 9、切换数据库 \`\`\` SELECT 1 \`\`\` ## 10、分布式锁 \`\`\` SET lock:order:123 "Thread10000" NX PX 30000 \`\`\` 解释: NX 保证了锁的互斥性,确保只有一个客户端能设置成功; PX 设置了过期时间防止死锁(默认毫秒) ## 11、lua脚本解锁 不能直接用DEL 因为可能导致被其恶意删除 \`\`\` DEL lock:order:123 \`\`\` 需要用lua脚本,写法如下: \*\*原型性\*\* \`\`\` EVAL "if redis.call('GET', KEYS\[1\]) == ARGV\[1\] then return redis.call('DEL', KEYS\[1\]) else return 0 end" 1 lock:order:123 Thread10000 \`\`\` 1、自己上锁,自己接锁,避免其他线程误操作,导致同步锁失效 2、保证释放的时候原子性。
03-3阶内容-1.5.2-redis介绍与基本命令
https://xiaochenblog.icu/archives/093a2042-5780-4efc-9a09-a0a21cf7c16b
评论