五大数据类型
字符串(string)
描述
是redis中最基本的数据类型,一个key对应一个value,可以包含任何数据(如文本,数字)
操作
命令 | 详细描述 |
Set key value | 设置key的值为value。如果key已经存在,其值会被覆盖 |
Get key | 获取key的值。如果key不存在,则返回nil |
Mset key1 value1 key2 value2 ... | 批量添加键值对 |
Mget key1 key2 | 获取所有给定key的value |
Append key value | 将value追加到键key的当前值后。如果key不存在,则会创建一个 |
Strlen key | 查看字符串的长度 |
Getrange key startindex endindex | 获取[startindex,endindex]范围的子串 |
Setnx key value | 仅在key不存在时,添加一个键值对 |
Set key value xx | 仅在key已存在时,修改一个键值对 |
Getset key valu | 修改一个键值对并返回原值,原值不存在则返回nil |
Incr key | 按key使value增加1 |
Incrby key 数值 | 按key使value增加给定数值 |
Decr key | 按key使value减小1 |
Decrby key 数值 | 按key使value减少给定数值 |
Expire key 秒数 | 设定一个生存时间 |
ttl key | 查看生存时间的剩余秒数(如果key不存在返回-2,永久键值对返回-1) |
Pexpire key 毫秒数 | 设定一个毫秒值的生存时间 |
Pttl key | 毫秒版ttl |
Persist key | 持久化(取消生存时间) |
Setex key 秒数 value | 为key加一个指定的生存时间 |
Psetex key 毫秒数 value | 为key加一个指定的毫秒数的生存时间 |
Set key value exat unix秒 | 设置一个unix秒的过期时刻 |
Set key value keepttl | Set时不重置ttl |
应用场景
适用于缓存、计数器、简单的键值存储等场景。
注意
大小限制:redis中字符串的最大长度为512MB,这在绝大多数情况下足够,但需要避免同时存储过大的字符串,以免影响性能。
类型混淆:字符串可以保存任何类型的数据(包括对象、数组等),当在获取时需要自己对类型进行转换和处理,确保正确使用
哈希(hash)
描述
哈希是一种键值对集合,适合存储对象的信息。每个哈希都可以包含多个字段和对应的值
操作
命令 | 详细描述 |
Hset key field1 value1 f2 v2... | 添加一个键与一至多对字段和值 |
Hget key field | 按key和field(字段)获取一对value |
Hmget key field1 f2 | 按key和field获取一至多对value |
Hgetall key | 按key获取全部的field-value |
Hdel key field1 f2 | 删除一至多对field-value |
Hsetnx key field value | 仅在field不存在时添加一对field-value |
Hkeys key | 查看一个散列表中所有的field |
Hvals key | 查看一个散列表中所有的value |
Hlen key | 统计一个散列表中有多少对field-value |
Hexists key field | 查看一个field是否存在 |
Hstrlen key field | 按key和field查看value的长度 |
Hincrby key field 整数值 | 按key和field使value增长给定整数值 |
Hincrbyfloat key field 小数值 | 按key和field使value增长给定小数值 |
应用场景
适用于存储用户信息、商品属性等需要将多个字段集合在一起的情况
注意
字段数量:虽然哈希表理论上可以容纳大量的字段,但如果字段数过多(特别是在某个字段的值较大时),会影响命令执行性能和内存使用
数据结构设计:使用哈希时要合理设计字段,以避免哈希命令高频率操作导致的内存和cpu使用高峰
列表(list)
描述
列表是有序的字符串集合,可以存储多个元素,并且支持从两端插入和删除元素
操作
命令 | 详细描述 |
Rpush key value0 v1... | 在列表右侧推入1至多个值 |
Lpush key ...value1 v0 | 在列表左侧推入1至多个值 |
Rpop key[数量] | 从列表右侧弹出(指定数量的)值 |
Lpop key[数量] | 从列表左侧弹出(指定数量的)值 |
Rpushx key value0 v1... | 仅当列表存在时,在列表右侧推入1至多个值 |
Lpushx key ...value1 v0 | 仅当列表存在时,在列表左侧推入1至多个值 |
Lset key *index value | 修改指定位置的值 |
Linsert key before/after 定位 value v | 在定位value前/后插入一个值 |
Lindex key *index | 按索引查看值 |
Lrange key *startindex *endindex | 查看给定范围的值 |
Llen key | 查看队列长度 |
Lrem key 数量 value | 删除指定值(数量为正代表从左侧开始删,为负代表从右侧开始删) |
Lrem key *startindex *endindex | 将列表修剪到给定范围 |
应用场景
适用于消息队列、历史记录、最新消息等需要顺序存储的场景
注意
列表长度:列表可以容纳大量的元素,但如果列表非常长,lrange命令等操作会导致性能下降。需要控制列表的长度,有时可以使用lrem来修剪长列表
顺序性:列表是有序的,使用时要注意索引的变化(插入会改变索引)
集合(set)
描述
集合是无序且唯一的字符串集合,适合用于存储不重复的元素
操作
命令 | 详细描述 |
Sadd key stringX stringY... | 添加1至多个成员 |
Srem key stringX stringY... | 删除1至多个成员 |
Scard key | 返回成员数量 |
Sismember key string | 查看是否存在指定成员 |
Smismember key stringX stringY... | 批量查看是否存在指定成员 |
Smembers key | 查看集合中所有成员 |
Srandmember key [数量] | 随机查看指定数量的成员 |
Spop key [数量] | 随机取出指定数量的成员 |
Smove key1 key2 string | 将指定成员从集合1移至集合2 |
Sinter key1 k2... | 查看给定集合的交集 |
Sintrerstore newkey key1 k2... | 存储给定集合的交集 |
Sunion key1 k2... | 查看给定集合的并集 |
Sunionstore newkey key1 k2... | 存储给定集合的并集 |
Sdiff key1 k2 | 查看给定集合的差集 |
Sdiffstroe newkey key1 k2... | 存储给定集合的差集 |
应用场景
适用于标签系统、社交网络中的好友关系、去重操作等场景
注意
性能问题:虽然集合操作具有较好的性能,集合的大小如果不断增长,可能会导致内存使用攀升,从而影响redis的整体性能
无序性:集合中的元素是无序的,不能保证元素的顺序,如果需要顺序操作,考虑使用有序集合
有序集合(Sorted Set)
描述
有序集合是带有评分(score)的字符串集合。其中每个成员都有一个关联的分数,通过分数来为集合中的元素排序
操作
命令 | 详细描述 |
Zadd key nx score1 stringX s2 strY | 仅当成员不存在时添加一至多个成员 |
Zadd key xx score1 stringX s2 strY | 仅当成员存在时修改成员 |
Zadd key gt score1 stringX s2 strY | 仅当分数高于原有分数时才更新分数 |
Zadd key lt score1 stringX s2 strY | 仅当分数低于原有分数时才更新分数 |
Zadd key ch score1 stringX s2 strY | 返回变更的成员数量 |
Zadd key incr score1 stringX s2 strY | 累加分数(只能操作一个分数-成员对) |
Zrem key stringX strY | 删除一至多个成员 |
Zcount key minscore maxscore | 返回指定分数区间内的成员数量(开区间:分数前加”(”,无穷大:”-inf”负无穷大,”+inf”正无穷大) |
Zscore key string | 查看成员分数(成员不存在时返回nil) |
Zmscore key stringX strY | 批量查看成员分数(成员不存在时返回nil) |
Zcard key | 查看成员数量 |
Zincard key 数值 string | 将指定成员的分数增加给定数值 |
Zrange key start end [byscore/bylex] [rev] [limit 偏移量 查看数量] [withscores] | 查看指定分数区间内的成员 Byscore:按分数升序排序 Bylex:分数相同时按成员字符排序(需要指定区间,”-”表示开始,”+”表示结束) Rev:反转 Limit:指定查看范围 Withscore:带分数 |
Zrangestore newkey key start end[byscore/bylex] [rev] [limit 偏移量 查看数量] | 存储指定分数区间内的成员 |
Zlexcount key startstring endstring | 查看指定字符串区间内的成员数量 |
Zremrangebylex key startstring endstring | 删除指定字符串区间内的成员 |
Zremrangebyscore key minscore maxscore | 删除指定分数区间内的成员 |
Zrank key string | 查看成员升序排名(从第0名开始) |
Zrevrank key string | 查看成员降序排名 |
Zremrangebyrank key startrank endrank | 删除指定排名区间内的成员(从第0名开始,-n表示倒数第n名) |
Zinter key的数量 key1 k2...[weights 权重1 权重2...] [aggregate sum|min|max] [withscores] | 查看给定集合的交集 Weights:依次为每个集合的分数设置权重(权重默认为1) Aggregate:新分数的计算方法(默认为sum) 新分数=Aggregate(集合1中该成员的分数*权重1,集合2中该成员的分数*权重2) |
Zinterstore newkey key的数量 key1 k2...[weights 权重1 权重2...] [aggregate sum|min|max] | 存储给定集合的交集 |
Zunion key的数量 key1 k2...[weights 权重1 权重2...] [aggregate sum|min|max] [withscores] | 查看给定集合的并集 |
Zunionstore newkey key的数量 key1 k2...[weights 权重1 权重2...] [aggregate sum|min|max] [withscores] | 存储给定集合的并集 |
Zdiff key的数量 key1 k2... [withscores] | 查看给定集合的差集 |
Zdiffstore newkey key的数量 key1 k2... | 存储给定集合的差集 |
应用场景
适用于排行榜、优先级队列、评分系统等需要排序和唯一性的场景。
注意
内存使用:每个成员都携带一个分数,随着集合规模增大,内存占用会很高。在选择使用有序集合时,要考虑应用的性能和内存要求
重复成员:有序集合中的成员是唯一的,如果在已存在的成员中再次添加,会导致旧成员的分数被更新,这可能会导致一些不必要的逻辑错误。
三大缓存问题
为什么要使用缓存
1.提高性能
缓存可以显著提高数据访问的速度。将频繁访问的数据存储在内存中,避免每次都去访问慢速的后端存储(如数据库),从而减少延迟。
2.减轻数据库负担
通过缓存热点数据,可以减少对数据库的访问频率,降低数据库的负载,从而提高整个应用系统的性能和可扩展性。
3.提高响应速度
缓存能够快速返回数据,提升用户体验。尤其在高并发场景下,使用Redis缓存能够有效提高请求的处理速度。
4.支持分布式应用
Redis支持分布式架构,可以作为多个应用的共享缓存层,便于多服务之间共享数据,提高数据访问效率。
5.灵活的数据过期机制
Redis提供了丰富的过期策略,可以根据需求对缓存数据进行有效管理,避免数据过时。
6.减少网络流量
通过使用缓存,可以减少与后端数据库的交互次数,从而降低网络流量和延迟。
缓存穿透
出现场景
缓存穿透通常发生在缓存和数据库间的数据一致性管理不当的情况下。当用户请求一个根本不存在的数据时,该请求直接穿透了缓存,直接访问后端数据库,这让数据库受到极大的压力,可能会导致服务响应变慢,甚至服务中断。
解决方法
1.过期时间随机化:
通过为每个缓存项设置一个随机的过期时间,避免大量缓存同时过期,减少数据库的瞬时压力。
2.使用多级缓存:
构建多级缓存,如本地缓存+远程缓存,利用本地缓存的高速度和远程缓存的大容量,分担请求压力,提高系统的稳定性和可用性。
3.缓存预热:
缓存预热是指在系统启动或在预期的高峰访问时段之前,提前将热点数据加载到缓存中,以减少数据库的访问压力,这可以避免在系统启动初期或负载高峰期,因缓存未准备好而导致的数据库压力激增。
4.加互斥锁:
在缓存失效时,为了避免多个请求同时重建缓存,可以使用互斥锁来确保同一时间只有一个请求能够进入数据库获取数据并更新缓存,其他请求则等待锁释放后从缓存中获取数据。
缓存击穿
出现场景:
缓存击穿是指当某个热点数据在缓存失效时,大量请求同时到达后端数据库,导致数据库瞬间承受高负债。这种情况通常发生在某个特定的缓存key在失效时,恰好有大量请求到达。
解决方法:
1.加互斥锁:
保证同一时间只有一个请求去数据库获取数据并更新缓存,其他请求则等待锁释放后从缓存中读取数据。
2.永久缓存热点数据:
对于热点数据,可以不设置过期时间,这样只要数据不被显式地删除或替换,就一直存在于缓存中,避免了过期问题。
缓存雪崩
出现场景:
缓存雪崩通常出现在在高访问量的情况下,多个缓存同时到期,引发大量请求直接落到数据库上,增加了数据库的负担。
解决方法:
1.防止非法请求:
通过检查请求的有效性,如对请求的参数进行验证,对于疑似非法的请求,可以记录IP地址或用户ID,并在一段时间内对其进行封禁。
2.缓存空值:
当查询到数据库中不存在的数据时,将空值缓存起来,设置一个合理的过期时间,这样下次相同的查询就可以直接从缓存中返回,不再需要访问数据库。
3.使用布隆过滤器:
布隆过滤器是一种空间效率极高的概率型数据结构,可以用来判断一个元素是否在一个集合中,虽然可能存在一定的误判率,当可以有效地过滤掉不存在的数据请求,避免它们直接到达数据库。