分布式系统的粗略演化过程:
1.单机架构(应用程序加服务器)
2.数据库和应用分离
应用程序和数据库分别部署到不同主机
3.引入负载均衡:
通过负载均衡器,把请求比较均匀分给集群中每个应用服务器
4.引入读写分离,数据库变为主从结构
一个数据库作为主节点,其他n个数据库作为从节点
主节点负责写数据,从节点负责读数据,主节点需要把修改的数据同步给从节点
5.引入缓存,冷热数据分离
进一步提升服务器对请求的处理能力,可以快速获取使用较多的数据,Redis就是主要在分布式系统中用于缓存
6.引入分库分表,使得数据库进一步扩展存储空间
7.引入微服务,将业务进一步拆分应用服务器
从业务功能角度,把应用服务器拆分为更多功能更加单一,更加简单,更加小的服务器
Redis的作用:
1.把Reids作为数据库,一般数据存储需要考虑存储容量更加大的数据库例如MySQL,但是仍然有一些场景需要获取数据更加"块“的数据库,例如搜索引擎,性能要求高,就可以使用Redis更加迅速。
2.用于缓存系统,将热门数据存储在内存中,提高访问速度,减轻数据库负载。
3.消息队列,Redis的发布订阅功能,可以作为一个轻量级的消息队列,用来发布订阅模式,实时处理消息。
4.分布式锁:Redis的特性可以用来实现分布式锁,确保多个进程与服务之间的数据操作的原子性和一致性。
5.排行榜:Redis的有序集合结构适合用于实现排行榜于排名系统,便于数据排序。
6.计数器:Redis的原子操作与高性能,它非常适合计数器和统计数据的存储,如访问量、点赞数的统计。
总结:Redis是一个使用内存存储数据的中间件,一般用于内存数据库,缓存系统,消息队列使用
缺点是存储在内存中,不能存储大规模的数据。
Redis 通用操作总结(redis‑cli + 通用key命令)
redis‑cli:redis客户端命令行工具,用于连接redis服务执行指令
1. redis‑cli 基础
redis‑cli # 默认本地 127.0.0.1:6379 连接 redis‑cli ‑h ip ‑p 端口 ‑a 密码2. keys 查看key(生产禁止使用)
keys * # 匹配所有key keys user? # ? 匹配任意1个字符 keys u[st]er # []匹配括号内其中一个字符:user、uter keys [^a]user # ^取反,不能是a开头 keys [a‑z]user # ‑范围,a‑z字母区间- 注意:keys会遍历全库,大数据量阻塞redis,生产用
scan替代
3. exists 判断key是否存在
exists key1 [key2...]返回值:存在数量,1存在,0不存在;支持多key传参
因为redis是一个客户端-服务器程序,客户端与服务器之间通过网络通信,分开写会产生更多轮次网络通信,效率更低,成本更高。
4. del 删除key
del key1 [key2...]- 删除成功返回删除个数,key不存在返回0
- 不管什么数据类型,直接删掉整个key
5. expire 设置key过期时间(秒)
expire key 10 # key 10秒后过期- 返回1:设置成功;0:key不存在设置失败
拓展:pexpire 单位毫秒
Redis的key的过期策略
redis有大量的key,有很多key都有过期时间,Redis怎么知道哪些key已经过期,哪些没有
redis策略是定期删除加惰性删除:
1.定期删除:定期抽取一部分检查过期时间,因为redis是单线程,要保证定期抽查不会影响主要任务的进行,所以要保证这个抽查时间足够快速。
2.惰性删除:当一个Key到达过期时间没有被删除,后面访问使用到这个key,就会进行这个key的删除,返回nil
虽然有两种策略结合,还是会很多过期的key没有被删除,redis还提供了一系列内存淘汰机制
常见误区:
redis并没有使用采用基于优先队列或者基于时间轮定时器实现过期策略
介绍一下定时器:
即到达某个时间执行指定任务1.基于优先级队列/堆实现
核心,堆顶放最早到期任务,此时定时器只要分配一个线程去检查队首元素是否过期,队首元素未过期,后续元素一定未过期,不用检查太频繁,新任务添加再次唤醒检查的线程。
2.基于时间轮实现
类比钟表,多个时间槽(bucket),每个槽存放一个任务链表,指针转到哪个槽,就执行该槽内全部到期任务。具体槽的时间与数量根据实际场景灵活调配。
6. ttl 查看剩余过期时间
ttl key返回值说明
- 正数:剩余多少秒过期
-1:key存在,没有设置过期时间,永不过期-2:key不存在
7. type 查看key的数据类型
type key返回:string/list/set/zset/hash/none(key不存在)
Redis的常见数据类型
数据结构与内部编码
type命令的实际返回就是当前键的数据结构类型,它们分别是:string,list,hash,set,zset,但是这些都只是Redis对外的数据结构,实际上Redis针对每种数据结构有自己的底层内部编码实现,会对结构进行优化,达到节省时间与空间效果。
数据结构:redis承诺给你的,也可以称为数据类型
编码方式:redis内部底层实现,redis会根据具体的实际情况选择内部编码,自动适应
| 数据结构 | 内部编码 |
|---|---|
| string(字符串) | raw、int、embstr |
| hash(哈希) | hashtable、ziplist |
| list(列表) | Redis3.2之前:linkedlist、ziplist,Redis3.2之后:quicklist双向链表,链表的每一个节点是 一个ziplist, 折中时间空间。 |
| set(集合) | hashtable、intset |
| fzset(有序集合) | skiplist、ziplist |
string:
1.raw:最基本的字符串,底层是byte数组(java)
2.int:当value是一个整数
3.embstr:针对短字符串进行优化
hash:
1.hashtable:元素个数多或者value比较长,使用redis内部实现的hashtable:最基本的哈希表,并非标准库中的HashTable
2.ziplist:哈希表元素较少或者value比较短时,压缩列表节省空间,使得整体占用内存更加少,但是读写元素,速度比较慢,如果元素个数少不明显,元素过多,慢就会比较严重,所以元素较少使用。
list:
linkedlist:链表
ziplist:压缩列表
quicklist:redis3.2之后引入quicklist,兼顾linkedlist和ziplist优点,既是一个链表,每一个元素又是一个ziplist,空间与效率折中兼顾,Redis7.0+废弃ziplist,替换成listpack。
set:
hashtable
intset:集合都是整数
zset:
skiplist:元素较多使用或者单个元素较大,跳表,也是链表,与普通链表不同是每个节点有多个指针域,巧妙搭配指针域指向,可以使得查询复杂度为O(logn)
ziplist:元素较少使用或者单个元素较小,压缩列表
object encoding key查询key对应value的实际编码方式
单线程架构
redis只使用一个线程,处理命令请求,但是redis内部也是有多个线程处理网络IO
当多个客服端同时请求服务器
宏观:
微观:
redis作为单线程模型,可以保证当前收到多个请求串行执行,即使同时到达也是要在队伍排队,redis服务器一个一个取出命令执行。同时也是因为redis的核心业务时短平快,消耗cpu资源少,能够使用单线程模型。
造成弊端:某个操作占用时间大,会阻塞其他命令执行。
redis虽然是单线程模型,为什么效率高,速度快?
1.Redis的数据存储在内存中,比访问硬盘的数据库更加快;
2.Redis的核心功能逻辑较为简单,只是比较简单是操作内存中的数据结构,而像mysql对于数据插入删除等操作,有复杂功能,要花费更多开销,比如数据库各种约束。
3.单线程模型减少一些不必要线程竞争开销。
3.从网络角度上,Redis使用了IO多路复用,即使用使用一个线程管理多个socket
Redis 采用了 I/O 多路复用机制处理大量的客户端 Socket 请求,IO 多路复用机制是指一个线程处理多个 IO 流,就是我们经常听到的 select/epoll 机制。简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听 Socket 和已连接 Socket。内核会一直监听这些 Socket 上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果,前提是这么多socket大部分时间是静默的,没有数据传输。
String类型
Redis命令
SET 系列
set key value [EX秒][PX毫秒][NX|XX]NX:不存在才设置;XX:已存在才修改
setnx key value:等价 set ... NX,非原子不能带过期setex key 秒 value:设置+秒级过期,3个参数不能少psetex key 毫秒 value:设置+毫秒过期优先用
set组合参数,一条命令原子完成,替代上面三条旧命令ttl key:剩余秒数;过期‑2,永久‑1
mset / mget
mset k1 v1 k2 v2:批量写,原子mget k1 k2:批量读必须进入redis‑cli内执行,shell不能直接跑redis命令
数值操作
incr/decr key:±1,不能传参数,只支持整数incrby/decrby key num:指定整数步长incrbyfloat key num:唯一支持浮点数
append、strlen
append key str:字符串追加,返回总字节strlen key:返回字节数,中文1汉字占3字节redis‑cli --raw:正常显示中文;普通cli输出转义十六进制
getrange / setrange
getrange key start end:截取,‑1代表最后一个字节setrange key offset value:从字节偏移处覆盖写入,返回总字节长度重点:key不存在,offset>0,前面自动填充
0x00空字节;--raw模式空字节看不见,用strlen验证真实长度。offset=0不会填充。
典型使用场景
1.缓存功能:
典型缓存使用场景,redis作为缓冲层,MySQL作为存储层,绝大部分请求从Redis中获取,Redis具有高并发特性,所以缓存可以起到加速读,和降低后端压力作用。
读请求优先查 Redis,命中直接返回;未命中就查询 MySQL,把数据回写到缓存,再返回结果。
2.记录视频播放次数
许多应用使用Redis作为计数的基本工具,实现快速计数,查询缓存功能,同时可以实现异步处理,落地到其他数据源,例如网站视频播放次数可以使用Redis实现,利用incr命令播放一次,数量加1。
3.共享会话
一个分布式Web服务器将用户Session信息保存到各自服务器,因为负载均衡的考虑会造成无法将用户每次请求均衡到同一台服务器,这样用户刷新一次可能需要重新登陆。
就可以使用Redis集中管理Session信息,只要保证Redis是高可用,扩展性的,无论均衡到哪一台Web服务器,都集中从Redis查询,更新Session信息。
4.手机验证码
Hash类型
字符串和哈希存储对比:
redis命令
| 命令 | 作用 | 时间复杂度 |
|---|---|---|
hset key field value | 设置 hash 中 field‑value,可同时设置多个 field;返回本次新增字段数量 | O (k),k 为设置的字段个数 |
hget key field | 获取 hash 中指定 field 字段对应的值 | O(1) |
hdel key field1 [field2...] | 删除 hash 内一个 / 多个字段,返回成功删除的字段数 | O (k),k 为删除字段数量 |
hlen key | 获取 hash 里面 field 字段总个数 | O(1) |
hexists key field | 判断 hash 中某个 field 字段是否存在,1 存在,0 不存在 | O(1) |
hmget key field1 [field2...] | 批量获取多个 field 的值 | O (k),k 为查询字段数量 |
hmset key f1 v1 f2 v2 | 批量设置多个字段(Redis4.0 后 hset 已经支持多参数,hmset 逐步废弃) | O (k),k 为设置字段数 |
hgetall key | 获取 hash 全部字段和对应的值 | O (n),n 为 hash 内所有字段总数 |
hkeys key | 只获取 hash 中所有的字段名 field | O (n),n 为 hash 字段总数 |
hvals key | 只获取 hash 中所有字段对应 value 值 | O (n),n 为 hash 字段总数 |
hsetnx key field value | 只有 field不存在才设置,存在不做修改;1 设置成功,0 失败 | O(1) |
hincrby key field increment | 给 hash 字段的数字做整数增量(hincr,完整命令 hincrby) | O(1) |
hincrbyfloat key field increment | 给 hash 字段浮点数值增加(hincrfloat 简写,完整 hincrbyfloat) | O(1) |
hstrlen key field | 获取 hash 中指定 field 对应的 value 字符串字节长度 | O(1) |
使用场景:
1.缓存
根据上面的内容,能够使用三种方式缓存用户信息1.原生字符串类型-每个属性一个键set user:1:name lisi set user:1age 23
优点:实现简单,针对个别属性变更也很灵活。缺点:占⽤过多的键,内存占⽤量较⼤,同时⽤⼾信息在 Redis 中⽐较分散,缺少内聚性,所以这种,⽅案基本没有实⽤性高内聚:把关联的东西放在一起低耦合:让不同模块之间关联尽量小,关联大可能牵一发动全身,关联小,可能一个模块出问题,其他模块没有影响。
2.序列化字符串例如JSONset user:1经过序列化后的⽤⼾对象字符串优点:针对总是以整体操作的信息比较合适,简单,序列化方案合适的话,内存使用效率比较高。缺点:序列化和反序列化需要一定开销,操作个别属性不灵活。
3.哈希类型hmset user:1 name lisi age 13优点:灵活,简单,直观缺点:需要控制哈希在ziplist和hashtable两种编码转换,可能造成内存较大消耗。与关系型数据库不同点:
- 哈希类型是稀疏的,关系型数据库是完全结构化的,比如哈希类型每个键可以有不同值,但是关系型数据库,必须有值即使为null
- 关系型数据库可以做复杂查询,如联合查询,聚合查询,Redis去模拟关系型复杂查询,几乎不可能成本高。
List类型
redis命令
lpush:从头插入元素
rpush:从尾插入元素
lrange key start end :获取start到end下标的元素
lpushx:只能在已经存在的列表头插入元素
rpushx:只能在已经存在的列表尾插入元素
lpop:在头取出元素
rpop:在尾取出元素
lindex key index :获取列表key的index下标的值
linsert key (before|after) pivot element:在列表基准值(之前|之后)插入元素
llen key :获取列表长度
lrem key count element:>0从头开始删除count个element,<0从尾开始删除count个element;=0删除所有element
ltrim key start stop :保留start和stop之间的元素
lset key index element :根据下标,修改元素
blpop,brpop:如果list存在元素,就与lpop,rpop作用相同,blpop key[key...] timeout如果为空就会阻塞
| 命令 | 作用 | 时间复杂度 | |
|---|---|---|---|
lpush key element [element...] | 头部(左边)插入一个或多个元素,key 不存在自动创建 list | O (k),k 为插入元素数量 | |
rpush key element [element...] | 尾部(右边)插入一个或多个元素,key 不存在自动创建 list | O (k),k 为插入元素数量 | |
lpushx key element | 仅当key列表已经存在,才在头部插入元素;key 不存在不做任何操作 | O(1) | |
rpushx key element | 仅当key列表已经存在,才在尾部插入元素;key 不存在不做任何操作 | O(1) | |
lpop key | 移除并返回列表头部第一个元素 | O(1) | |
rpop key | 移除并返回列表尾部最后一个元素 | O(1) | |
blpop key [key ...] timeout | 阻塞版 lpop。多个 key 依次检查,有数据直接弹出头部;全部无数据则阻塞等待 timeout 秒,timeout=0 无限阻塞 | O(1) | |
brpop key [key ...] timeout | 阻塞版 rpop。多个 key 依次检查,有数据直接弹出尾部;全部无数据则阻塞等待 timeout 秒,timeout=0 无限阻塞 | O(1) | |
lrange key start end | 获取指定下标区间元素;end=-1代表取全部;下标从 0 开始 | O (s+n),s 偏移量,n 返回元素个数 | |
lindex key index | 根据下标获取元素,支持负数下标,-1取最后一个元素 | O (n),下标离头部越远开销越大 | |
llen key | 获取列表长度,key 不存在返回 0 | O(1) | |
| `linsert key BEFORE | AFTER pivot element` | 在列表中基准值 pivot的前面 / 后面插入新元素;找不到 pivot 不执行;只匹配第一个 pivot | O(n) |
lrem key count element | 删除列表中匹配 element 的元素count>0:从头删 count 个count<0:从尾部删 count 个count=0:删除全部匹配 element | O(n) | |
ltrim key start stop | 截取列表,只保留 [start,stop] 区间内元素,其余全部删掉,实现裁剪 | O(n) | |
lset key index element | 根据下标修改对应位置元素;下标越界直接报错 | O(n) | |
rpoplpush source destination | (补充高频)source 尾部弹出,插入 destination 头部;可做消息队列、循环列表 | O(1) |
使用场景:
1.消息队列:Reidis可以使用lpush+brpop命令组合实现经典阻塞式生产者-消费者模型队列,多个消费者客户端使用brpop命令阻塞式地从队列中争抢队首元素,通过多个客户端来保证消费的负载均衡和高可用性。
2.分频道阻塞消息队列
使用lpush + brpop实现分频道阻塞消息队列。通过不同的 List key 模拟不同频道,生产者调用lpush向对应 key 写入消息;消费者使用brpop阻塞监听指定 key,只消费该频道消息。 举例:视频业务,可以设计不同频道,分别处理视频资源、弹幕、评论、点赞
3.微博Timeline
每个用户都有之自己的微博列表,需要分页展示文章列表,可以考虑使用列表,因为列表不但有序,同时支持按照索引范围获取元素,使用命令lrange。
Set集合
redis命令
| 命令 | 作用 | 时间复杂度 |
|---|---|---|
| sadd key member1 member2… | 向集合添加一个或多个成员,重复元素自动去重 | O (N),N 为添加元素个数 |
| smembers key | 返回集合中全部的元素 | O (N),N 为集合元素数量 |
| scard key | 获取集合的元素个数(集合基数) | O(1) |
| sismember key member | 判断某个元素是否存在集合中,存在返回 1,不存在返回 0 | O(1) |
| srandmember key [count] | 随机返回 count 个元素,不会删除原数据;count>0 不重复,count<0 允许重复 | O(count) |
| spop key [count] | 随机取出 count 个元素,取出后从集合删除 | O(count) |
| sinter key1 key2 … | 求多个集合的交集,返回交集结果,不修改原集合 | O (N*M),N 为最小集合元素数,M 集合数量 |
| sinterstore dest key1 key2… | 求多个集合交集,并把结果存入 dest 目标集合,覆盖 dest 原有数据 | O(N*M) |
| sunion key1 key2 … | 求多个集合的并集,返回结果,不修改原集合 | O (N),N 所有集合总元素 |
| sunionstore dest key1 key2… | 求多个集合并集,结果存入 dest 目标集合 | O(N) |
| sdiff key1 key2 … | 求集合差集(key1 有,其他集合没有),返回结果,不改原集合 | O (N),N 全部集合总元素 |
| sdiffstore dest key1 key2… | 求差集,把差集结果存入 dest 目标集合 | O(N) |
使用场景
1.使用Set保存用户标签,了解用户喜好
2.基于集合求交集,使用Set计算用户之间好友,进行好友推荐
3.使用Set统计UA,使用去重
PV、UV 概念
PV (Page View):页面访问量,每一次页面请求就算 1 次 PV,同一个用户多次访问会重复累加。
UV (User View):独立访客数,按用户去重,同一个用户无论访问多少次,UV 只算 1 次。
Set 集合天然去重,非常适合统计 UV。
Zset有序集合
特点:有序且唯一
引入一个浮点类型的属性score,排序时按照score进行升序排列
Zset的member是唯一的,score可以重复,与键值对不同的是既可以通过member找到score,又可以通过score找到member。
redis命令
| 命令 | 作用 | 时间复杂度 | 重要备注 |
|---|---|---|---|
ZADD key [NX|XX][GT|LT][CH][INCR] score member... | 添加 / 更新 zset 元素NX:仅新增;XX:仅更新GT/LT:分数条件更新CH:变更计数;INCR:自增分数 | O(k×log n) | k 为添加元素个数;成员存在直接更新 score |
ZSCORE key member | 根据 member 获取分数 | O(1) | 查询哈希 dict,不走跳表;不存在返回 nil |
ZRANK key member | 获取成员升序排名,下标从 0 开始 | O(log n) | 跳表查询;分数小排名靠前 |
ZREVRANK key member | 获取成员降序排名,下标从 0 开始 | O(log n) | 分数大排名靠前 |
ZINCRBY key increment member | 给成员分数增加指定增量 | O(log n) | 修改分数后跳表重排序 |
ZCARD key | 获取有序集合总元素数量 | O(1) | 直接读取内部计数器 |
ZREM key member [member...] | 删除一个或多个指定成员 | O(k×log n) | k 为删除的元素个数 |
ZPOPMAX key [count] | 删除并返回分数最高 count 个元素 | O(M×log n) | M 是弹出元素数量 |
ZPOPMIN key [count] | 删除并返回分数最低 count 个元素 | O(M×log n) | M 是弹出元素数量 |
ZRANGE key start end [WITHSCORES] | 按下标排名升序获取数据 | O(k+log n) | k 返回条数;0 -1返回全部;WITHSCORES 同时输出分数 |
ZREVRANGE key start end [WITHSCORES] | 按下标排名降序获取数据 | O(k+log n) | 从集合尾部向前取 |
ZRANGEBYSCORE key min max [WITHSCORES][LIMIT] | 按分数区间升序查询 | O(k+log n) | (代表开区间;支持 LIMIT 分页 |
ZREVRANGEBYSCORE key max min [WITHSCORES] | 按分数区间降序查询 | O(k+log n) | 注意参数顺序 max 在前、min 在后 |
ZCOUNT key min max | 统计分数区间内元素个数 | O(log n) | 只计数,不返回数据,无 k 系数;支持开区间 |
ZREMRANGEBYRANK key start end | 删除指定排名区间的元素 | O(k+log n) | k 为删除元素数量 |
ZREMRANGEBYSCORE key min max | 删除指定分数区间的元素 | O(k+log n) | k 为删除元素数量 |
ZINTERSTORE dest numkeys key1 key2... [WEIGHTS][AGGREGATE SUM|MIN|MAX] | 多个 zset 做交集,结果存入 dest | O(n×k)+O(m×log m) | 仅保留两边同时存在的 member;先乘权重再聚合;大数据量性能差 |
ZUNIONSTORE dest numkeys key1 key2... [WEIGHTS][AGGREGATE SUM|MIN|MAX] | 多个 zset 做并集,结果存入 dest | O(n)+O(m×log m) | 只要任意一个集合存在就保留;SUM 为默认聚合策略 |
使用场景:
1.排行榜系统
用来高效实时排行,只需要把信息以及对应的分数放到有序集合,形成一个排行榜,
可以随时按照下标,分数进行范围查询,分数变化可以zincrby修改分数,排序实时调整(logN)
对于复杂的排行,还可以设置权重,借助zinterstore/zunionstore按照加权方式处理
Redis其他数据类型
stream
Redis流是一种数据结构,它类似于仅追加日志,但还实现了多种操作以克服典型仅追加日志的一些限制。这些操作包括O(1)时间的随机访问和复杂的消费策略,例如消费者组。您可以使用流来实时记录和同步事件。Redis流的使用场景包括:
• 事件溯源(例如,跟踪用户操作、点击等)
• 传感器监控(例如,现场设备的读数)
• 通知(例如,在单独的流中存储每个用户的通知记录)stream就是一个阻塞队列,是Reis作为消息队列的主要支撑
Redis geospatial
用来存储坐标,存储一些点后,可以让用户定位一个坐标,去刚刚存储的点查找(按照圆半径,矩形区域)
Redis HyperLogLog
用来估算元素个数,相对于Set计数,HyperLogLog不存储元素具体内容,而是记录元素的特征,能够新增元素判断是否存在,能够节省空间,但会有一定误差,误差概率81%。
Redis bitmaps
用bit来表示整数,,也是主要用于存储元素个数,属于Set类型针对整数版本,能够节省空间,相比于HyperLogLog能够存储数据,但只能存储整数。
Redis bitfileds
位域,与 C语言的位域很像,可以理解成一串二进制序号(字节数组),可以把这个字节数组中,中某几位赋予特定的含义,进行读取、修改、算术运算等待,相比于String、hash,节省空间。
渐进式遍历
keys *,可以一次性获取redis所有的key,但是容易阻塞服务器
渐进式遍历,既能获取所有key,又不会卡死服务器,可以进行多次操作,每次执行命令只会获取一小部分,保证操作不会卡。
代表命令:scan
SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]cursor:光标,指向当前遍历的位置,0就是从头开始,cursor并不是像下标一样递增的整数,就是一个 字符串,只有redis服务器本身知道,光标对应的元素位置。
match:匹配模式仅返回与给定通配符样式模式相匹配的键。
count:计数数量每次迭代返回键数量的提示值。默认值为 10。
type:类型类型仅返回指定类型的键,例如字符串、列表或集合。
实际返回的key个数不一定与写入的count一样,每次会返回下次scan的位置,cursor回到0说明遍历结束。
这里的渐进式遍历,不会在服务器存储任何状态信息,遍历可以随时终止,不会产生副作用。
注意:scan虽然解决阻塞问题,但是在遍历期间进行变化(增加,删除,修改),可能导致遍历时键的重复遍历或者遗漏,开发时还是要注意是否真的需要遍历所有redis的key。
数据库管理
mysql一个服务器可以有很多database,一个database可以有很多表,可以创建、删除数据库,redis也有数据库但是不能像mysql一样随意,数据库是现成的,而且不能删除数据库,默认提供16(0-15)个数据库,默认使用的是0,数据库之间不会相互影响。
Redis Java 集成到 Spring Boot
引入依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>spring: data: redis: host: 127.0.0.1 port: 8888 #使用ssh映射测试:
@RestController public class RedisTestController { @Autowired private RedisTemplate<String,Object> redisTemplate; @GetMapping("/testHash") public String testHash(){ //你的hash测试代码 return "ok"; } }