Redis学习笔记 | 青训营

199 阅读7分钟

Redis是什么

Redis:REmote DIctionary Server(远程字典服务器) 是完全开源免费的,用C语言编写的,遵守BSD协议,是一个高性能的(key/value)分布式内存数据库,基于内存运行并支持持久化的NoSQL数据库,是当前最热门的NoSql数据库之一,也被人们称为数据结构服务器。 Redis 与其他 key - value 缓存产品有以下三个特点:

  • Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用;
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储;
  • Redis支持数据的备份,即master-slave模式的数据备份;

为什么需要Redis

随着数据量的增长和读写数据压力不断增加,使用mySQL之类的数据库在高QPS的场景下是支撑不住的,所以需要想办法提高数据存取速度。数据存在内存中读取速度很快,所以Redis就应运而生。 热数据即经常访问的数据存放在Redis中,冷数据存储到磁盘中。

Redis基本工作原理

数据存放在内存中会面临一个问题,当服务器重启时,内存中的数据就会丢失。Redis实现了数据持久化。实现原理类似数据库的恢复技术

Redis4.0之后提供了混合持久化方式,也就是:采用RDB快照以一定频率执行保存数据,而在两次快照之间,使用AOF日志记录这期间的所有命令操作。

redis五大数据类型

string

string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value; string类型是二进制安全的。意思是redis的string可以包含任何数据。如jpg图片或者序列化的对象 ; string类型是Redis最基本的数据类型,一个redis中字符串value最多可以是512M;

set/get/del/append/strlen;
Incr/decr/incrby/decrby:一定要是数字才能进行加减;
getrange/setrange:

getrange:获取指定区间范围内的值,类似between and的关系从零到负一表示全部;
setrange:设置指定区间范围内的值,格式是setrange key 位置值 具体值;
setex(set with expire) 键 秒值 值/setnx(set if not exist) 键

setex:设置带过期时间的key,动态设置 : setex 键 秒值 真实值
setnx:只有在 key 不存在时设置 key 的值:setnx 键 值
mset/mget/msetnx

mset:同时设置一个或多个 key-value 对。
mget:获取所有(一个或多个)给定 key 的值。
msetnx:同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在(如果存在key,则都不会操作,因为msetnx是原子性型操作)。
getset:将给定 key 的值设为 value ,并返回 key 的旧值(old value)。简单一句话,先get然后立即set

list

redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)。它的底层实际是个链表。

lpush/rpush/lrange;
lpop/rpop,移除列表key的头/尾元素;
lindex,按照索引下标获得元素(从上到下)(格式:lindex key index);
llen:返回列表 key 的长度(格式:llen key);
lerm:根据参数 count 的值,移除列表中与参数 value 相等的元素(格式: lerm key count value);

count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。
count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。
count = 0 : 移除表中所有与 value 相等的值。
ltrim ,截取指定范围的值后再赋值给key(格式:ltrim key start stop);
rpoplpush,移除列表的最后一个元素,并将该元素添加到另一个列表头部并返回(格式:rpoplpush source—key destination—key);
lset,将列表 key 下标为 index 的元素的值设置为 value(格式:lset key index value);
linsert,(格式:linsert key before|after pivot value)将值 value 插入到列表 key 当中,位于值 pivot 之前或之后;

当 pivot 不存在于列表 key 时,不执行任何操作。
当 key 不存在时, key 被视为空列表,不执行任何操作。
如果 key 不是列表类型,返回一个错误。

set

redis的set是string类型的无序集合。它是通过HashTable实现的。

sadd/smembers/sismember,格式:

sadd key member [member ...]
smembers key
sismember key member
scard:获取集合里面的元素个数(格式:scard key);
srem:删除集合中元素(格式:srem key member [member ...]);
srandmember,(格式:srandmember key [count])(不会修改set集合)

如果命令执行时,只提供了 key 参数,那么返回集合中的一个随机元素;
如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合;
如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值;
spop,移除并返回集合中的一个随机元素(格式:spop key);
smove,(格式:smove source destination member)将 member 元素从 source 集合移动到 destination 集合;
数学集合类

差集:sdiff(格式:sdiff key [key ...])
交集:sinter(格式:sinter key [key ...])
并集:sunion(格式:sunion key [key ...])

hash

redis的hash 是一个键值对集合; redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象; 类似Java里面的Map<String,Object>;

hset/hget/hmset/hmget/hgetall/hdel,格式:

hset key field value:将哈希表 key 中的域 field 的值设为 value ;
hget key field:返回哈希表 key 中给定域 field 的值;
hmset key field value [field value ...]:同时将多个 field-value (域-值)对设置到哈希表 key 中;
hmget key field [field ...]:返回哈希表 key 中,一个或多个给定域的值;
hgetall key:返回哈希表 key 中,所有的域和值;
hdel key field [field ...]:删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略;
hlen,返回哈希表 key 中域的数量(格式:hlen key);
hexists,查看哈希表 key 中,给定域 field 是否存在(格式:hexists key field);
hkeys/hvals,格式:

hkeys key:返回哈希表 key 中的所有域;
hvals key:返回哈希表 key 中所有域的值;
hincrby/hincrbyfloat,格式:

hincrby key field increment:为哈希表 key 中的域 field 的值加上增量 increment;
hincrbyfloat key field increment:为哈希表 key 中的域 field 加上浮点数增量 increment ;
hsetnx,将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在(格式:hsetnx key field value)

zset(sorted set)

redis的zset 和 set 一样也是string类型元素的集合,且不允许重复的成员; 不同的是每个元素都会关联一个double类型的分数; redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复;

zadd/zrange,格式:

zadd key score member [[score member] [score member] ...]:将一个或多个 member 元素及其 score 值加入到有序集 key 当中;
zrange key start stop [WITHSCORES]:返回有序集 key 中,指定区间内的成员,其中成员的位置按 score 值递增(从小到大)来排列;
zrangebyscore:(格式:zrangebuscore key min max [WITHSCORES] [LIMIT offset count]),返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员;
zrem:移除有序集 key 中的一个或多个成员,不存在的成员将被忽略(格式:zrem key member [member ...]);
zcard/zcount /zrank/zscore,格式:

zcard key:返回有序集 key 的基数;
zcount key min max:返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量;
zrank key member:返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列,排名以 0 为底,也就是说, score 值最小的成员排名为 0 ;
zscore key member:返回有序集 key 中,成员 member 的 score 值;
zrevrank:返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递减(从大到小)排序,排名以 0 为底,也就是说, score 值最大的成员排名为 0 (格式:zrevrank key member);
zrevrange:返回有序集 key 中,指定区间内的成员,其中成员的位置按 score 值递减(从大到小)来排列(格式:zrevrange key start stop [WITHSCORES]);
zrevrangebyscore:返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列(格式:zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]);

Redis应用案例

连续签到

key为用户ID,value为连续签到天数,利用Redis中的过期机制,设置expireAt:后天的0点,这样就会在指定的时间过期,过期后就会归零

消息通知

使用list作为消息队列,监听消息队列的头,有数据就取出来推送到ES。生成端使用lpush,消费端使用rpop逐条消费队列中的信息

计数

一个用户有多项计数需求,可通过hash结构存储

image.png

排行榜

积分变化时,排名要实时变更。使用zskiplist快速查找

限流

要求一秒内放行的请求为N,超过N则禁止访问

Key: comment_freq_limit_1671356046 对这个Key调用incr,超过限制N则禁止访问 1671356046 是当前时间戳

分布式锁

并发场景,要求一次只能有一个协程执行,执行完成后,其他等待中的协程才能执行。

可以使用redis的setnx实现,利用了两个特性

  • redis时单线程执行命令
  • setnx只有未设置过才能执行成功