Skip to content

REDIS

redis命令速查

排查指令

redis-cli info
cluster node
cluster check

string

命令描述
SET key value设定或覆盖key值
GET key获取key的值
MSET key1 value1 key2 value2 ... keyN valueN同时设置一个或多个 key-value 对。当 key 已经持有值时,MSET 会用新值覆盖旧值。
MGET key1 key2 ... keyN获取所有(一个或多个)给定 key 的值。
GETSET key value将给定 key 的值设为 value ,并返回 key 的旧值(old value)。当 key 存在但不是字符串类型时,返回一个错误。
GETRANGE key start end获取存储在指定 key 中字符串的子字符串。字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。
SETRANGE key offset value用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始。
INCR key将 key 中储存的数字值增一。如果 key 不存在,那么 key 的值会先被初始化为 0,然后再执行 INCR 操作。
DECR key将 key 中储存的数字值减一。如果 key 不存在,那么 key 的值会先被初始化为 0,然后再执行 DECR 操作。
INCRBY key increment将 key 所储存的值加上给定的增量值(increment)。如果 key 不存在,那么 key 的值会先被初始化为 0,然后再执行 INCRBY 操作。
DECRBY key decrement将 key 所储存的值减去给定的减量值(decrement)。如果 key 不存在,那么 key 的值会先被初始化为 0,然后再执行 DECRBY 操作。
APPEND key value如果 key 已经存在并且是一个字符串,APPEND 命令将 value 追加到 key 原来的值的末尾。如果 key 不存在,APPEND 就简单地将给定 key 设为 value,就像执行 SET key value 一样。
STRLEN key返回 key 所储存的字符串值的长度。当 key 不存在时,返回 0。

list

命令描述
LPUSH key value1 [value2 ...]将一个或多个值插入到列表头部。如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。
RPUSH key value1 [value2 ...]将一个或多个值插入到列表尾部。如果 key 不存在,一个空列表会被创建并执行 RPUSH 操作。
LPUSHX key value1 [value2 ...]仅当 key 存在并且是列表类型时,将一个或多个值插入到列表头部。如果 key 不存在或不是列表类型,则不做任何操作。
RPUSHX key value1 [value2 ...]仅当 key 存在并且是列表类型时,将一个或多个值插入到列表尾部。如果 key 不存在或不是列表类型,则不做任何操作。
LPOP key移除并获取列表的第一个元素。如果列表没有元素会返回 nil。如果 key 不存在返回 nil。
RPOP key移除并获取列表的最后一个元素。如果列表没有元素会返回 nil。如果 key 不存在返回 nil。
RPOPLPUSH source destination移除列表的最后一个元素,并将该元素添加到另一个列表的头部。如果 source 不存在,则返回 nil。如果 destination 不存在,则创建一个空列表,执行 LPUSH 操作。如果 destination 不是一个列表,会返回一个错误。
LINDEX key index获取列表指定索引下的元素。索引从 0 开始。如果索引值超出范围,或者 key 不存在,返回 nil。
LRANGE key start stop获取列表指定范围内的元素。start 和 stop 为列表的索引,左闭右开区间。如果 key 不存在,返回空列表。
LTRIM key start stop对一个已存在的列表进行修剪(trim),让列表只保留指定区间内的元素,不在指定区间内的元素都将被删除。如果 key 不存在或不是一个列表,返回一个错误。
`LINSERT key BEFOREAFTER pivot value`
LREM key count value根据参数 count 的值,移除列表中与 value 相等的元素。count 的值可以是大于 0、小于 0 或等于 0,分别表示从头部开始移除、从尾部开始移除或移除所有。
LLEN key返回列表的长度。如果 key 不存在,则长度为 0。如果 key 不是列表类型,返回一个错误。

hash

命令描述
HSET key field value将哈希表 key 中的字段 field 的值设为 value。如果 key 不存在,一个空哈希表被创建并执行 HSET 操作。如果 field 已经存在于哈希表中,该操作覆盖了旧值。
HGET key field获取存储在哈希表中指定字段的值。如果 key 或 field 不存在,返回 nil。
HMSET key field1 value1 field2 value2 ... fieldN valueN同时将多个 field-value (域-值) 对设置到哈希表 key 中。HMSET 会替换哈希表中已存在的字段。
HMGET key field1 field2 ... fieldN获取所有给定字段的值。如果哈希表不存在,或者指定的字段不存在于哈希表,那么返回一个包含 nil 的列表。
HGETALL key返回哈希表 key 中的所有字段和值。当 key 不存在时,返回一个空列表。
HDEL key field1 field2 ... fieldN删除哈希表 key 中的一个或多个指定字段,不存在的字段将被忽略。
HEXISTS key field查看哈希表 key 中,指定的字段是否存在。
HLEN key返回哈希表 key 中字段的数量。当 key 不存在时,返回 0。
HKEYS key获取哈希表 key 中的所有字段。当 key 不存在时,返回一个空列表。
HVALS key获取哈希表 key 中的所有值。当 key 不存在时,返回一个空列表。
HINCRBY key field increment将哈希表 key 中的指定字段的整数值加上增量 increment。如果 key 不存在,一个新的哈希表被创建并执行 HINCRBY 命令。如果字段 field 不存在,那么在执行命令前,字段的值被初始化为 0。
HINCRBYFLOAT key field increment将哈希表 key 中的指定字段的浮点数值加上增量 increment。如果 key 不存在,一个新的哈希表被创建并执行 HINCRBYFLOAT 命令。如果字段 field 不存在,那么在执行命令前,字段的值被初始化为 0.0。

set

命令描述
SADD key member1 [member2 ...]向集合添加一个或多个成员。如果集合已经存在该成员,则忽略该操作。
SREM key member1 [member2 ...]移除集合中一个或多个成员。如果成员不存在于集合中,则被忽略。
SISMEMBER key member判断成员是否是集合的成员。
SCARD key返回集合的成员数。
SMEMBERS key返回集合的所有成员。
SRANDMEMBER key [count]返回集合中一个或多个随机成员。如果指定了 count 参数,且 count 大于集合成员数,那么返回所有成员。如果 count 是负数,那么命令返回一个不重复的随机成员列表,列表的大小为 abs(count)。
SPOP key [count]随机移除并返回集合中的一个或多个成员。
SREM key [member]删除成员。
SMOVE source destination member将 member 元素从 source 集合移动到 destination 集合。如果 member 在 source 集合中不存在,或者 member 已经存在于 destination 集合,那么操作不执行。
SUNION key1 [key2 ...]返回所有给定集合的并集。
SINTER key1 [key2 ...]返回所有给定集合的交集。
SDIFF key1 [key2 ...]返回存在于第一个集合,但不存在于其他给定集合的差集。

sorted set

命令描述
ZADD key score1 member1 [score2 member2 ...]将一个或多个 member 元素及其 score 值加入到有序集合 key 中。如果某个 member 已经是有序集合的成员,那么更新该 member 的 score 值,并通过重新插入该 member 元素,来保证该 member 在正确的位置上。score 值可以是整数值或双精度浮点数。如果 key 不存在,则创建一个空的有序集合并执行 ZADD 操作。当 key 存在但不是有序集合类型时,返回一个错误。
ZREM key member1 [member2 ...]移除有序集合 key 中的一个或多个成员,不存在的成员将被忽略。当 key 存在但不是有序集合类型时,返回一个错误。
ZINCRBY key increment member为有序集合 key 中的成员 member 的 score 加上增量 increment。如果 member 不是 key 的成员,那么在 key 中添加 member 并设置 member 的 score 为 increment。如果 key 不存在,则创建一个空的有序集合并执行 ZINCRBY 操作。当 key 不是有序集合类型时,返回一个错误。
ZRANK key member返回有序集合 key 中成员 member 的排名。排名以 0 为起始索引,即排名最小的成员的排名为 0。如果 member 元素不是有序集合的成员,返回 nil。当 key 不存在时,返回 nil。
ZREVRANK key member返回有序集合 key 中成员 member 的排名,以降序排列。当 member 是有序集合的成员时,返回成员的排名;如果 member 不是有序集合的成员或 key 不存在,返回 nil。
ZRANGE key start stop [WITHSCORES]返回有序集合 key 中指定区间内的成员。其中成员的位置按 score 值递增(从小到大)来排序。具有相同 score 值的成员按字典序来排列。如果你需要获得成员的 score 值,你需要加上 WITHSCORES 选项。
ZREVRANGE key start stop [WITHSCORES]返回有序集合 key 中指定区间内的成员,通过索引区间来限制范围。成员的位置按 score 值递减(从大到小)来排列。具有相同 score 值的成员按字典序的逆序排列。
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]返回有序集合 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集合成员按 score 值从小到大排列。具有相同 score 值的成员按字典序来排列。
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]返回有序集合 key 中,score 值介于 max 和 min 之间的成员。其中成员的位置按 score 值递减(从大到小)来排列。具有相同 score 值的成员按字典序的逆序排列。
ZCOUNT key min max计算有序集合 key 中,score 值在 min 和 max 之间(包括等于 min 或 max )的成员的数量。
ZCARD key返回有序集合 key 的成员数量。当 key 不存在时,返回 0。
ZSCORE key member返回有序集合 key 中,成员 member 的 score 值。如果 member 元素不是有序集合的成员或者 key 不存在,返回 nil。
ZREMRANGEBYRANK key start stop移除有序集合 key 中,排名在 start 和 stop 之间(包括等于 start 和 stop )的成员。
ZREMRANGEBYSCORE key min max移除有序集合 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。

geo

命令描述
GEOADD key longitude latitude member将指定的地理空间位置(纬度、经度、成员)添加到指定的 key。支持批量添加。
GEODIST key member1 member2 [unit]返回两个给定位置之间的距离。默认单位为米,可以使用 mkmmift 作为单位参数。
GEOHASH key member [member ...]返回一个或多个位置对象的 Geohash 表示。
GEOPOS key member [member ...]返回指定成员的地理位置(纬度和经度)。
`GEORADIUS key longitude latitude radius mkm
`GEORADIUSBYMEMBER key member radius mkm
`GEORADIUS key longitude latitude radius mkm
`GEORADIUS key longitude latitude radius mkm
`GEORADIUS key longitude latitude radius mkm
`GEORADIUSBYMEMBER key member radius mkm
`GEORADIUSBYMEMBER key member radius mkm
`GEORADIUSBYMEMBER key member radius mkm

stream

命令描述
XADD key [MAXLEN ~ N] ID field value [field value ...]向指定流添加条目,返回条目ID。可选参数MAXLEN ~ N表示限制流的长度。
XTRIM key MAXLEN ~ N修剪流以保留最近的N个条目。
XLEN key返回流中条目的数量。
XRANGE key start end [COUNT count]返回指定范围内的流条目,包含startend。可选参数COUNT限制返回条目数量。
XREVRANGE key end start [COUNT count]返回指定范围内的流条目,顺序与XRANGE相反。可选参数COUNT限制返回条目数量。
XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...]从一个或多个流中读取数据,阻塞或非阻塞方式。
`XGROUP CREATE key groupname id$ [MKSTREAM]`
`XGROUP SETID key groupname id$`
XGROUP DESTROY key groupname删除消费者组。
XGROUP DELCONSUMER key groupname consumername从消费者组中删除消费者。
XREADGROUP GROUP groupname consumer [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...]从消费者组读取数据。
XACK key groupname id [id ...]确认一个或多个已处理的条目。
XCLAIM key groupname consumer min-idle-time id [id ...] [IDLE milliseconds] [TIME milliseconds] [RETRYCOUNT count] [FORCE] [JUSTID]将待处理条目分配给其他消费者。
XPENDING key groupname [start end count] [consumer]返回有关消费者组待处理条目的信息。
XINFO STREAM key返回有关流的信息。
XINFO GROUPS key返回有关消费者组的信息。
XINFO CONSUMERS key groupname返回有关消费者的信息。

redis为什么快

使用内存来读写,比磁盘快,读写速度能达到10W次每秒;

高效的数据结构,底层使用了,sds,hash表,跳表等结构;

单线程执行命令,不需要上下文切换和线程切换;

多路io复用,epoll

为什么用redis?好处?介绍redis?

Redis 作为一种高性能的键值对数据库,被广泛应用于各种场景中。以下是 Redis 的一些主要优点:

  1. 高性能:Redis 是基于内存的存储系统,所有的读写操作都是在内存中完成的,所以 Redis 的性能非常高,读写速度可以达到 10 万次/秒以上。
  1. 丰富的数据类型:Redis 支持多种数据类型,如字符串、列表、集合、有序集合、哈希、BitMap、HyperLogLog、流和地理位置等。这些丰富的数据类型可以更好地支持各种复杂的应用场景。
  1. 数据持久化:Redis 支持 RDB 和 AOF 两种数据持久化方式,可以将内存中的数据持久化到磁盘中,防止数据丢失。
  1. 支持事务:Redis 支持事务操作,可以保证一组命令的原子性。
  1. 发布订阅模式:Redis 支持发布订阅模式,可以用于构建实时消息系统。
  1. 内置 Lua 脚本执行环境:Redis 内置了 Lua 脚本执行环境,可以使用 Lua 脚本来完成复杂的逻辑操作。
  1. 主从复制和哨兵模式:Redis 支持主从复制和哨兵模式,可以提高系统的可用性。
  1. 高级特性:Redis 提供了一些高级特性,如 LRU 缓存淘汰、位图操作、HyperLogLog、地理位置操作等。

Redis 之所以快,主要是因为它是基于内存的,所有的操作都在内存中完成,而内存的读写速度远高于磁盘。此外,Redis 采用了高效的事件处理模型,可以处理大量的并发连接。同时,Redis 的数据结构设计和算法优化也对其高性能有所贡献。

REDIS的缺点

尽管 Redis 有很多优点,但它也有一些潜在的缺点,如下:

  1. 内存限制:因为 Redis 是基于内存的存储系统,所以它的存储能力受到物理内存的限制。如果要存储的数据超过了内存大小,就需要考虑使用数据淘汰策略或者分片等方案。
  1. 数据安全性:虽然 Redis 提供了持久化机制,但如果在写入数据到磁盘的过程中出现问题,可能会导致数据丢失。另外,Redis 的 AOF 持久化机制在写入大量数据时可能会影响性能。
  1. 单线程模型:Redis 使用单线程模型处理客户端的请求,这意味着在一次只能处理一个客户端的请求,不能充分利用多核 CPU。
  1. 复杂的数据一致性问题:在使用主从复制和分片等高级特性时,可能会出现数据一致性的问题。
  1. 缺乏查询语言:Redis 不像 SQL 数据库那样有一个丰富的查询语言,这可能会限制它在某些复杂查询场景的应用。

REDIS数据类型有哪些?使用场景?

string:缓存(啥都能用的那种),比如存储验证码、短链接、会话,计数器等;
list:适合做消息队列,如微博的关注列表和粉丝列表,游戏排行榜等;
hash:存储对象 HashMap数据(那种经常要查某一段的数据,比如 user{id:1,name:小明},经常要查name)的这种
set:适合做好友关系、共同好友、共同喜欢的电影等功能,也可以存储访问过的网页 URL、防止网页爬虫重复爬取。不重复的数据:比如:抽奖,点赞,
sorted set:可排序的不重复的数据,比如:排行榜,
stream(redis5.0):适合做实时消息队列,日志收集和消息广播等。
bitmap:连续的二进制数字(0,1),省空间,签到,统计流量,统计;适合做统计和过滤操作,比如统计在线用户、用户签到等。
hyperloglog:主要用来做基数统计,特别适合做网站的 UV 统计;
GEO:适合做地理位置相关的应用,比如附近的人、商家、地点搜索等。

redis淘汰策略?内存满了怎么办?什么情况下用哪种策略?

Redis 提供了多种数据淘汰策略来处理内存满的情况,以下是一些常见的淘汰策略和适用情况:

  1. volatile-lru:从设置了过期时间的键中选择最近最少使用的键来淘汰。这种策略适合在键值对有过期时间且你希望保留最近使用的键值对的情况。
  1. volatile-ttl:从设置了过期时间的键中选择剩余时间最短的键来淘汰。这种策略适合在键值对有过期时间且你希望保留剩余时间最长的键值对的情况。
  1. volatile-random:从设置了过期时间的键中随机选择键来淘汰。这种策略适合在键值对有过期时间且你无特别偏好哪个键值对保留的情况。
  1. allkeys-lru:从所有的键中选择最近最少使用的键来淘汰。这种策略适合在你希望保留最近使用的键值对的情况,不论键值对是否有过期时间。
  1. allkeys-random:从所有的键中随机选择键来淘汰。这种策略适合在你无特别偏好哪个键值对保留的情况,不论键值对是否有过期时间。
  1. noeviction:不淘汰任何键,只返回一个错误。这种策略适合在你不能接受任何数据丢失的情况,但这种情况下如果内存满了,Redis 将无法继续写入数据。

如果 Redis 的内存满了,它会根据配置的淘汰策略来淘汰一些键,以释放内存空间。如果没有设置淘汰策略,或者设置的淘汰策略是 "noeviction",那么当内存满了之后,Redis 就不再接受写入操作,只能接受读操作和删除操作。

另一种解决内存满的问题的方法是使用 Redis 的分片功能,将数据分布在多个 Redis 实例上,这样可以扩大总的可用内存空间。

redis持久化?服务重启,数据不就没了?

AOF:appendfsync always(每次改都追加),everysec(每秒同步一次),no(关闭时刷入),存储指令,文件大
RDB:二进制快照文件,占用空间小,恢复速度快
RDB是默认的持久化方式,在指定的间隔内将内存中的数据集以快照的形式写入磁盘的二进制文件,产生的就是dump.rdb,恢复是直接将数据读到内存
AOF是以日志的形式来记录每个写的操作,太大后重写瘦身(BGREWRITEAOF)

redis事务

mulit(开始),exec(执行),discard(取消),watch(监听) 开始事务(mulit),mulit和exec之间的命令入队列,然后执行(exec)或取消(discard) watch监听一个键,调用exec时,这个键被改,整个队列都不执行 不支持回滚,

热key问题

热点key,又称为热键,指的是在Redis中被频繁访问的键。当某个键的请求量巨大,可能会导致服务器资源不足,甚至导致服务中断。这种情况常见于用户消费的数据远大于生产的数据的场景,例如秒杀活动、热点新闻等读多写少的场景,或者请求分片过于集中,超过单个Redis服务器的性能。

识别热键的方法有:

  1. 根据经验判断哪些可能是热键。
  2. 通过客户端进行统计并上报。
  3. 通过服务代理层上报。

解决热键问题的策略包括:

  1. Redis集群扩容:通过增加分片副本,均衡读流量。
  2. 键分散:将热键分散到不同的服务器中,避免单一服务器的压力过大。
  3. 使用二级缓存:例如使用JVM本地缓存,这可以减少对Redis的读请求,降低Redis服务器的负载。

缓存穿透,缓存击穿,缓存雪崩 问题如何解决?

缓存穿透缓存击穿,和缓存雪崩是在缓存系统设计中需要特别考虑的三个问题。以下是这三个问题的解决方法:

1. 缓存穿透:缓存穿透是指查询一个不存在的数据,由于缓存没有命中,于是请求会穿透缓存直接请求数据库,如果有大量此类请求,数据库可能会短时间内压力剧增。解决方法:

  • 对查询条件进行校验,比如用户ID或商品ID在查询前就判断一下是否存在。
  • 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

2. 缓存击穿:缓存击穿是指一个热点key在失效的瞬间,大量的请求就像穿透一样,同时请求数据库中的这条数据。解决方法:

  • 在热点key即将失效时,手动进行续期操作。
  • 设置热点数据永不过期。
  • 采用互斥锁,即在缓存失效的时候不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则就重试整个get缓存的方法。

3. 缓存雪崩:缓存雪崩是指在某一个时间段内,大量的key同时过期,导致大量的请求同时涌向数据库,可能会导致数据库瞬时压力过大甚至宕机。解决方法:

  • 设置不同的过期时间,让缓存失效的时间点尽可能均匀。
  • 采用数据预热,将可能的访问压力提前分摊到平时。
  • 使用高可用的缓存解决方案,比如使用多级缓存结构(Redis+本地缓存),以及分布式缓存(Memcached集群,Redis集群),保证即便某一机器宕机,整体缓存服务依然可用。
  • 对可能的大量key设置热点保护,即对一些热点数据进行特殊处理(比如永不过期)。

缓存和数据库如何保持一致性?

在使用缓存的时候,缓存和数据库保持一致性是一个很重要的问题。下面是一些常用的策略:

1. 读取时更新缓存(Lazy Loading):这种策略是最常见的,当需要读取一个数据时,先去缓存中查找,如果找到了就直接返回,如果没找到就去数据库中查找,找到后先更新缓存,然后再返回数据。

2. 更新时删除缓存(Write/Through or Write/Beside):当数据发生变更时,更新数据库,然后删除缓存。下次请求这个数据时,由于在缓存中找不到,就会去数据库中查找,并更新到缓存中。

3. 更新时更新缓存(Write/Back or Write/Behind):当数据发生变更时,同时更新数据库和缓存。这种方式需要处理更新失败的情况,比如数据库更新成功但缓存更新失败等。

4. 使用队列:为了解决并发下的数据一致性问题,可以使用队列。所有的更新操作都先写入队列,然后有一个后台任务负责从队列中取出操作并执行,这样就能保证操作的顺序性,避免并发下的数据不一致问题。

5. 分布式锁:在更新数据时,通过获取分布式锁,保证同时只有一个操作能对数据进行修改,从而保证数据的一致性。

在使用上述策略的时候,需要考虑数据的特性和应用的需求,比如是否能容忍短时间的数据不一致,更新操作的频率等。

REDIS变慢了?如何排查?

当Redis运行变慢时,以下是一些排查问题的方法:

1. 检查Redis慢日志:通过使用slowlog get命令,我们可以查看Redis的慢查询日志,看是否存在过于复杂或耗时的命令,如SUNIONZUNIONSTORE等。

2. 检查返回数据量:如果Redis的某个操作返回的数据量过大,也可能影响到Redis的性能。你可以检查你的应用是否存在这种情况。

3. 检查是否存在大key:大key在Redis中分配内存时会比较耗时,释放内存也同样耗时。通过scan命令配合strlenllenhlenzcardscard等命令,可以帮助我们找出大key。

4. 检查是否存在集中过期的情况:如果Redis中存在大量的键在同一时间过期,可能会导致Redis变慢。你可以通过查看Redis的过期键统计信息来确认这个问题。

5. 检查Redis内存使用情况:如果Redis的内存使用达到上限,每次写入都需要先进行内存淘汰,这会影响Redis的性能。你可以通过info memory命令查看Redis的内存使用情况。

6. 检查持久化配置:如果你使用了AOF持久化,并且配置为appendfsync always,这会导致Redis频繁地进行磁盘I/O操作,从而影响性能。你可以考虑修改AOF的配置,或者使用RDB持久化来改善这个问题。

7. 检查网络状况:如果网络带宽过载,也会影响Redis的性能。你可以通过ping命令或者相关的网络监控工具来检查网络状况。

8. 检查系统资源使用情况:如果Redis所在的服务器资源被其他程序占用过多,也可能导致Redis运行变慢。你可以通过系统的资源监控工具(如topiostat等)来检查系统资源的使用情况。

参考文章
Redis为什么变慢了?万字长文讲透如何排查Redis性能问题

redis数据结构底层原理?

Redis的数据结构底层实现原理主要包括以下几种:

  1. 字符串(String):在Redis中,字符串采用简单动态字符串(Simple Dynamic String, SDS)来实现。SDS是一个可以修改的字符串,用len表示字符串长度,free表示未使用的空间,buf是实际的字符串数组。
  1. 列表(List):Redis的列表数据结构在数据量小的时候使用压缩列表(ziplist)这种更节省空间的数据结构,数据量大的时候会使用双向链表。双向链表使得列表可以提供从两头压入和弹出元素的功能,同时也可以按索引进行读取。
  1. 集合(Set):Redis的集合数据结构在元素数量较少和所有元素都是整数的情况下,使用整数集合(intset)来实现。当元素数量增多或者有非整数元素时,Redis会使用哈希表来实现。
  1. 哈希(Hash):Redis的哈希数据结构在字段和值的数量较少的情况下,会使用压缩列表(ziplist)进行存储,当字段和值的数量增多时,会转为使用哈希表来存储。
  1. 有序集合(ZSet):Redis的有序集合在元素数量较少的时候,使用压缩列表(ziplist)来存储,当元素数量增多时,会转为使用跳跃列表(skiplist)和哈希表的结合体来存储。
  1. 位图(Bitmap):位图实际上是一个特殊的字符串,它的每一个bit可以独立的表示一个信息。
  1. HyperLogLog:HyperLogLog是用来做基数统计的算法,Redis提供了相应的数据结构和命令来使用这个算法。
  1. GEO:Redis的GEO是基于ZSet实现的,它会将地理坐标转换为一个52位的整数,然后保存在ZSet中。
  1. 流(Stream):Redis的流是一种持久化的、插入顺序的、可重复读的数据类型,它是基于列表和哈希的混合体来实现的。

redis如何保证原子性

1.单线程执行

2.lua脚本

3.事务

4.原子操作命令,比如,incr,decr,setNx等

分布式锁

NX:不存在才set PX:毫秒, EX:秒

上锁:SET 锁名 随机值 NX PX 毫秒过期时间

解锁:if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end

红锁算法:多个节点,一半以上锁成功才算成功;

https://redis.io/docs/latest/develop/use/patterns/distributed-locks/