redis的基本数据类型(一)

redis的基本数据类型

1、redis

1.1、数据库分类

  • 目前数据库分:关系型数据库与非关系型数据库

  • 常用的关系型数据库: Oracle,MySQL,SqlServer,DB2

  • 常用的非关系数据库:Redis,MongoDB,ElasticSearch, Hbase,Neo4j

  • 那啥是非关系数据库呢?此处涉及到新名词:NoSQL

  • NoSQL最常见的解释是"non-relational", "Not Only SQL"也被很多人接受。NoSQL仅仅是一个概念,泛指非关系型的数据库,区别于关系数据库,它们不保证关系数据的ACID特性。

如商城网站中对商品数据频繁查询、对热搜商品的排行统计、订单超时问题、以及微信朋友圈音频、视频存储等相关使用传统的关系型数据库实现就显得非常复杂,虽然能实现相应功能但是在性能上却不是那么乐观。NoSQL这个技术门类的出现,更好的解决了这些问题,它告诉了世界不仅仅是sql。

1.2、NoSQL分类

分类 举例 典型应用场景 数据模型 优点 缺点
键值(key-value)存储数据库 redis 内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等。 通常用HashTable来实现 查找速度快 数据无结构化
列存储数据库 HBase 分布式的文件系统 将同一列数据存在一起 查找速度块,更容易进行分布式扩展 功能相对局限
文档型数据库 MongoDB 查询性能不高,且缺乏统一的查询语法
图形数据库 Infinite Graph 社交网络,专注于构建关系图谱 图结构 利用图数据结构相关算法 对整个图进行计算才能得到需要的信息

1.3、redis简介

redis是以key-value形式存储,和传统的关系型数据库不一样。不一定遵循传统数据库的一些基本要求。

优点:

  • 对数据高并发读写(直接是内存中进行读写的)
  • 对海量数据的高效率存储和访问
  • 对数据的可拓展性和高可用性
  • 单线程操作,每个操作都是原子操作,没有并发相关问题

缺点:

  • 无法做太复杂的关系数据库模型
  • redis(ACID处理非常简单)

redis 定位是缓存,提高数据读写速度,减轻对数据库存储和访问压力。redis是一个内存型的数据库

1.4、redis应用

  • 任务队列,如秒杀、抢购、购票排队等

  • 即时信息查询,如各位排行榜、各类网站访问统计、公交到站信息

  • 为热点数据加速查询(主要场景),如热点商品、热点新闻

  • 消息队列、分布式锁

1.5、如何学习redis

2、redis的安装

2.1、Windows安装

傻瓜式安装,一直下一步就可以了,注意要添加到环境变量中

默认端口:

最大内存

测试是否成功:

  • win+r 输入 redis-cli

2.2.1、客户端redis管理工具

AnotherRedisDesktopManager 工具可以用来可视化管理redis,可以理解为 MySQL的 Sqlyog、Navicat等管理工具。

下载完成后安装即可:

2.2、Linux安装🔥

  1. 进入Linux官网下载最新稳定版本:https://redis.io/download/
  1. 将其上传至 Linux 服务器目录下 /www/server/redis 中,并进行解压。

    我这里使用 wget 命令下载,和上述步骤作用一致

bash 复制代码
# 进入/www/server/redis目录下载
wget https://github.com/redis/redis/archive/7.2.3.tar.gz
http://github.com/redis/redis/archive/7.2.3.tar.gz
# 解压
tar -zxvf 7.2.3.tar.gz
  1. 进入到解压目录,执行编译命令
bash 复制代码
# 进入到解压目录
cd redis-7.2.3/

# 执行编译命令
make
  1. 进行安装
bash 复制代码
# 安装,默认是安装到 /usr/local/bin 目录
make install

共安装了三个组件:redis server服务器、redis-cli客户端与一个性能测试工具 benchmark

  1. 新建一个系统服务文件:
bash 复制代码
vi /etc/systemd/system/redis.service

内容如下:

bash 复制代码
[Unit]
Description=redis-server
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /www/server/redis/redis-7.2.3/redis.conf
PrivateTmp=true

[Install]
WantedBy=multi-user.target
  1. 进入/www/server/redis/redis-7.2.3,先拷贝redis.conf,然后进行修改
bash 复制代码
# 拷贝
cp redis.conf redis.conf.back

修改redis.conf的配置

bash 复制代码
# 允许访问的地址,默认是127.0.0.1,会导致只能在本地访问。修改为0.0.0.0则可以在任意IP访问,生产环境不要设置为0.0.0.0
bind 0.0.0.0
# 守护进程,修改为yes后即可后台运行
daemonize yes 
  1. 然后重载系统服务
bash 复制代码
systemctl daemon-reload
  1. 现在,我们可以用下面这组命令来操作redis了:
bash 复制代码
# 启动
systemctl start redis
# 停止
systemctl stop redis
# 重启
systemctl restart redis
# 查看状态
systemctl status redis
  1. 执行下面的命令,可以让redis开机自启:
bash 复制代码
systemctl enable redis
  1. 查看 redis 版本
bash 复制代码
# 查看服务端版本
redis-server -v

# 查看客户端版本
redis-cli -v

2.2.1、redis核心文件

/usr/local/bin 目录中,可以看到如下文件:

  • redis-serve : 服务器启动命令
  • redis-cli : 命令行客户端
  • redis-benchmark : redis 性能测试工具
  • redis-check-aof :AOF文件修复工具
  • redis-check-dump :RDB文件检查工具(快照持久化文件)

通过echo $PATH 可以看到,/usr/local/bin 目录是存在于该系统变量中的,这样这些命令就可以在任意目录中执行了,这就是为什么我们在任意目录都可以直接使用redis-cli 进行命令行

2.2.2、启动方式

  • 方式一:前台启动,安装完成后,在任意目录输入redis-server命令即可启动Redis
bash 复制代码
redis-server

这种启动属于前台启动,会阻塞整个会话窗口,窗口关闭或者按下CTRL + C则Redis停止。不推荐使用。

  • 方式二:指定配置文件启动,如果要让Redis以后台方式启动,则必须修改Redis配置文件,就在我们之前解压的redis安装包下(/www/server/redis/redis-7.2.3),名字叫redis.conf

    1. 我们先将这个配置文件备份一份:

      bash 复制代码
      cp redis.conf redis.conf.back
    2. 然后修改redis.conf文件中的一些配置:

      bash 复制代码
      # 允许访问的地址,默认是127.0.0.1,会导致只能在本地访问。修改为0.0.0.0则可以在任意IP访问,生产环境不要设置为0.0.0.0
      bind 0.0.0.0
      # 守护进程,修改为yes后即可后台运行
      daemonize yes 
      # 密码,设置后访问Redis必须输入密码
      requirepass 1234
    3. Redis的其它常见配置:

      bash 复制代码
      # 监听的端口
      port 6379
      # 工作目录,默认是当前目录,也就是运行redis-server时的命令,日志.持久化等文件会保存在这个目录
      dir .
      # 数据库数量,设置为1,代表只使用1个库,默认有16个库,编号0~15
      databases 1
      # 设置redis能够使用的最大内存
      maxmemory 512mb
      # 日志文件,默认为空,不记录日志,可以指定日志文件名
      logfile "redis.log"
    4. 启动Redis:

      bash 复制代码
      # 进入redis安装目录 
      cd /www/server/redis/redis-7.2.3
      # 启动
      redis-server redis.conf
    5. 停止redis

      bash 复制代码
      # 利用redis-cli来执行 shutdown 命令,即可停止 Redis 服务,
      # 因为之前配置了密码,因此需要通过 -u 来指定密码
      redis-cli -u 1234 shutdown
  • 方式三是开机自启,已经在2.2目录进行了设置

当给redis.conf 设置了密码requirepass 1234,则启动时需要auth 1234

2.2.3、redis桌面客户端

1、redis命令行客户端

Redis安装完成后就自带了命令行客户端:redis-cli,使用方式如下:

bash 复制代码
redis-cli [options] [commonds]

其中常见的options有:

  • -h 127.0.0.1:指定要连接的redis节点的IP地址,默认是127.0.0.1
  • -p 6379:指定要连接的redis节点的端口,默认是6379
  • -a 1234:指定redis的访问密码

其中的commonds就是Redis的操作命令,例如:

  • ping:与redis服务端做心跳测试,服务端正常会返回pong
2、图形化桌面客户端

注意:在连接的时候请确保服务器的防火墙端口打开6379,否则会连接不上

3、数据类型

3.1、概况

Redis支持的存储数据类型有很多:

  • 常用:string (字符串),hash (哈希),list (列表),set (集合)及zset(sorted set:有序集合)

  • 不常用:HyperLogLog,Bitmap(位图),Bloom Filter(布隆过滤器),Geospatial(地理位置) ,Module(模块), Streams(流信息)

命令格式

类型命令 key value
set name zhangsan

操作建议

  • Redis操作有点类似Java的Map集合,都是key-value形式存储数据,在学习过程中,可以进行类比。

  • 另外Redis中的key大部分为String类型,value值根据缓存数据结构可以选用:string,hash,list,set,zset等类型。

注意:下面讲的各种类型,表述的是缓存数据的value类型。

3.2、String类型

String类型包含多种类型的特殊类型,并且是二进制安全的,其值可以是数值,可以是字符串,也可以是二进制数据。

3.2.1、常用的命令

命令格式 功能 案例 说明
set key value 将key-value缓存redis中 set name qxl 设置name字段为qxl
get key 从redis中获取key对应value值 get name 获取name字段对应的value
incr key 将key对应value值 + 1 incr age 给age字段+1
decr key 将key对应value值-1 decr age 给age字段-1
setex key seconds value 将key-value缓存到redis中,seconds 秒后失效 setex sex 10 man 将sex字段设置为10s的man
ttl key 查看key存活时间 ttl sex 查看sex字段对应的 value 存活时间
del key 从redis中删除key del name 删除name字段
setnx key value 如果key已经存,不做任何操作,如果key不存,直接添加 setnx name xiaofei

普通字符串的基本操作:

bash 复制代码
# 设置 key-value 类型的值
> SET name lin
OK

# 根据 key 获得对应的 value
> GET name
"lin"

# 判断某个 key 是否存在
> EXISTS name
(integer) 1

# 返回 key 所储存的字符串值的长度
> STRLEN name
(integer) 3

# 删除某个 key 对应的值
> DEL name
(integer) 1

3.2.2、非常用命令

命令格式 功能 案例
incrby key increment 给key对应值加increment incrby age 10
mset k1 v1 k2 v2... 批量添加k1v1 k2v2 key value对 mset name dafei age 18
mget k1 k2... 批量获取k1, k2的值 mget name age
append key value 在key对应的value值中拼+value append name yes
setrange key offset value 修改key对应的value值,替换为指定value,冲offset索引位置开始 setrange name 2 xx

批量设置:

bash 复制代码
# 批量设置 key-value 类型的值
> MSET key1 value1 key2 value2 
OK

# 批量获取多个 key 对应的 value
> MGET key1 key2 
1) "value1"
2) "value2"

计数器(字符串的内容为整数的时候可以使用):

bash 复制代码
# 设置 key-value 类型的值
> SET number 0
OK

# 将 key 中储存的数字值增一
> INCR number
(integer) 1

# 将key中存储的数字值加 10
> INCRBY number 10
(integer) 11

# 将 key 中储存的数字值减一
> DECR number
(integer) 10

# 将key中存储的数字值键 10
> DECRBY number 10
(integer) 0

过期(默认为永不过期):

bash 复制代码
# 设置 key 在 60 秒后过期(该方法是针对已经存在的key设置过期时间)
> EXPIRE name  60 
(integer) 1
# 查看数据还有多久过期
> TTL name 
(integer) 51

#设置 key-value 类型的值,并设置该key的过期时间为 60 秒
> SET key  value EX 60
OK
> SETEX key  60 value
OK

不存在就插入:

bash 复制代码
# 不存在就插入(not exists)
>SETNX key value
(integer) 1

3.2.3、应用场景

  1. 缓存对象:使用 String 来缓存对象有两种方式:

    • 直接缓存整个对象的 JSON,命令例子: SET user:1 '{"name":"xiaolin", "age":18}'
    • 采用将 key 进行分离为 user:ID:属性,采用 MSET 存储,用 MGET 获取各属性值,命令例子: MSET user:1:name xiaolin user:1:age 18 user:2:name xiaomei user:2:age 20
  2. 主页高频访问信息显示控制,例如新浪微博大V主页显示粉丝数与微博数量。这就是常规计数,计算访问次数、点赞次数、转发次数等。

  3. 共享session:

    • 通常我们在开发后台管理系统时,会使用 Session 来保存用户的会话(登录)状态,这些 Session 信息会被保存在服务器端,但这只适用于单系统应用,如果是分布式系统此模式将不再适用。

    • 例如用户一的 Session 信息被存储在服务器一,但第二次访问时用户一被分配到服务器二,这个时候服务器并没有用户一的 Session 信息,就会出现需要重复登录的问题,问题在于分布式系统每次会把请求随机分配到不同的服务器。

  • 出于负载均衡的考虑,分布式服务会将用户信息的访问均衡到不同服务器上,用户刷新一次访问可能会需要重新登录,为避免这个问题可以用redis将用户session集中管理, 在这种模式下只要保证redis的高可用和扩展性的,每次获取用户更新或查询登录信息都直接从redis中集中获取。

3.3、Hash类型

Hash 是一个键值对(key - value)集合,其中 value 的形式如: value=[{field1,value1},...{fieldN,valueN}]。Hash类型特别适合存储对象:

类似Java中:Map<String, Map<String, ?>> map

3.3.0、内部实现

Hash 类型的底层数据结构是由压缩列表或哈希表实现的:

  • 如果哈希类型元素个数小于 512 个,所有值小于 64 字节的话,Redis 会使用压缩列表作为 Hash 类型的底层数据结构;
  • 如果哈希类型元素不满足上面条件,Redis 会使用哈希表作为 Hash 类型的 底层数据结构

在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了

3.3.1、常用的命令

命令格式 功能 案例 说明
hset key field value 将field value对缓存到redis中hash中,键值为key hset user name dafei 给user中的name字段设置为dafei
hget key field 从key对应hash列表中获取field字段 hget user name 获取user中的name字段
hexists key field 判断key对应的hash列表是否存在 field字段 hexists user age 判断user中是否存在age字段
hdel key field 删除key对应hash列表中field字段 hdel user age 删除user中的age字段
hincrby key field increment 给key对应hash列表中field字段 + increment hincrby user age 10 给user中的age字段+10
hlen key 查看key对应的hash列表field的数量 hlen user 查看user中的所有 key
hkeys key 获取key对应的hash列表所有的field值 hkeys user 获取user中的所有 key
hvals key 获取key对应的hash列表所有的field对应的value值 hvals user 获取user中的所有value
hgetall key 获取key对应的hash列表中所有的field及其对应的value值 hgetall user 获取user中的所有 key 和 value
bash 复制代码
# 存储一个哈希表key的键值
HSET key field value   
# 获取哈希表key对应的field键值
HGET key field

# 在一个哈希表key中存储多个键值对
HMSET key field value [field value...] 
# 批量获取哈希表key中多个field键值
HMGET key field [field ...]       
# 删除哈希表key中的field键值
HDEL key field [field ...]    

# 返回哈希表key中field的数量
HLEN key       
# 返回哈希表key中所有的键值
HGETALL key 

# 为哈希表key中field键的值加上增量n
HINCRBY key field n  

Hash类型数据操作的注意事项:

  • Hash类型下的 value 只能存储字符串,不允许存储其他数据类型
  • Hash设计的初衷不是为了存储大量对象的,切记不可滥用。

3.3.2、应用场景

  • 缓存对象:Hash 类型的 (key,field, value) 的结构与对象的(对象id, 属性, 值)的结构相似,也可以用来存储对象。我们以用户信息为例,它在关系型数据库中的结构是这样的:

    uid name age
    1 Tom 15
    2 Jerry 13

    我们可以使用如下命令,将用户对象的信息存储到 Hash 类型:

    bash 复制代码
    # 存储一个哈希表uid:1的键值
    > HMSET uid:1 name Tom age 15
    2
    # 存储一个哈希表uid:2的键值
    > HMSET uid:2 name Jerry age 13
    2
    # 获取哈希表用户id为1中所有的键值
    > HGETALL uid:1
    1) "name"
    2) "Tom"
    3) "age"
    4) "15

    一般对象用 String + Json 存储,对象中某些频繁变化的属性可以考虑抽出来用 Hash 类型存储。

  • 电商网站购物车设计

    • 以客户id作为key,每位客户创建一个hash存储结构存储对应的购物车信息。将商品编号作为field,购买数量作为value进行存储

      key value
      id { name: dafei field:001 value:3 }
    • 添加购物车:追加全新的field与value

    • 浏览购物车:遍历hash

    • 更改购物车数量:自增/自减,设置value值

    • 删除购物车商品:删除field

    • 清空购物车:删除key

3.4、List类型

  • List类型是一个链表结构的集合,其主要功能有push、pop、获取元素等。
  • 类似Java中:Map<String, List> map

3.4.0、内部实现

  • 如果列表的元素个数小于 512 个,列表每个元素的值都小于 64 字节,Redis 会使用压缩列表作为 List 类型的底层数据结构;
  • 如果列表的元素不满足上面的条件,Redis 会使用双向链表作为 List 类型的底层数据结构

但是在 Redis 3.2 版本之后,List 数据类型底层数据结构就只由 quicklist 实现了,替代了双向链表和压缩列表

3.4.1、常用的命令

命令格式 功能 案例 说明
rpush key value 从右边往key集合中添加value值 rpush hobby java 从右边向 hobby 集合中添加 java 字段
lrange key start stop 从左边开始列表key集合,从start位置开始,stop位置结束 lrange hobby 0 3 lrange hobby 0 -1 从左边开始罗列 hobby 集合下标 0-3 的字段 从左边开始罗列 hobby 集合下所有字段
lpush key value 从左边往key集合中添加value值 lpush hobby c++ 从左边向 hobby 集合中添加 c++ 字段
lpop key 弹出key集合中最左边的数据 lpop hobby 弹出 hobby 集合中最左边的数据
rpop key 弹出key集合中最右边的数据 rpop hobby 弹出 hobby 集合中最右边的数据
llen key 获取列表长度 llen hooby 获取 hobby 集合的长度
bash 复制代码
# 将一个或多个值value插入到key列表的表头(最左边),最后的值在最前面
LPUSH key value [value ...] 
# 将一个或多个值value插入到key列表的表尾(最右边)
RPUSH key value [value ...]
# 移除并返回key列表的头元素
LPOP key     
# 移除并返回key列表的尾元素
RPOP key 

# 返回列表key中指定区间内的元素,区间以偏移量start和stop指定,从0开始
LRANGE key start stop

# 从key列表表头弹出一个元素,没有就阻塞timeout秒,如果timeout=0则一直阻塞
BLPOP key [key ...] timeout
# 从key列表表尾弹出一个元素,没有就阻塞timeout秒,如果timeout=0则一直阻塞
BRPOP key [key ...] timeout

3.4.2、非常用命令

命令格式 功能 案例
linsert key before pivot value 操作key集合,在pivot值之前插入value linsert hobby before java c#
linsert key after pivot value 操作key集合,在pivot值之后插入value linsert hobby after java c#
lset key index value 操作key集合,更新索引index位置值为value lset hobby 1 go
lrem key count value 操作key集合,删除 count个 value值 lrem hobby 3 go
ltrim key start stop 操作key集合,从start到stop截取自列表 ltrim hobby 2 4
lindex key index 操作key集合,获取索引为index位置的数据 lindex hobby 1

3.4.3、应用场景

  1. 用户收藏文章列表:
key value
user_favor_article_list [aid1, aid2, aid3...]
  1. 消息队列:小林coding

3.5、Set类型

Set 类型是一个无序并唯一的键值集合,它的存储顺序不会按照插入的先后顺序进行存储。

Set 类型和 List 类型的区别如下:

  • List 可以存储重复元素,Set 只能存储非重复元素;
  • List 是按照元素的先后顺序存储元素的,而 Set 则是无序方式存储元素的。

3.5.0、内部实现

Set 类型的底层数据结构是由哈希表或整数集合实现的:

  • 如果集合中的元素都是整数且元素个数小于 512 (默认值,set-maxintset-entries配置)个,Redis 会使用整数集合作为 Set 类型的底层数据结构;
  • 如果集合中的元素不满足上面条件,则 Redis 使用哈希表作为 Set 类型的底层数据结构。

3.5.1、常用的命令

命令格式 功能 案例 说明
sadd key members [...] 往key 集合中添加member元素 sadd myset a b c 给集合 myset 添加 a b c 元素
smembers key 遍历key集合中所有的元素 smembers myset 遍历集合 myset
srem key members [...] 删除key集合中members元素 srem myset a 删除myset集合中的元素a
spop key count 从key集合中随机弹出count个元素 spop myset 1
bash 复制代码
# 往集合key中存入元素,元素存在则忽略,若key不存在则新建
SADD key member [member ...]
# 从集合key中删除元素
SREM key member [member ...] 
# 获取集合key中所有元素
SMEMBERS key
# 获取集合key中的元素个数
SCARD key

# 判断member元素是否存在于集合key中
SISMEMBER key member

# 从集合key中随机选出count个元素,元素不从key中删除
SRANDMEMBER key [count]
# 从集合key中随机选出count个元素,元素从key中删除
SPOP key [count]

3.5.2、非常用命令

命令格式 功能 案例
sdiff key1 key2 返回key1中特有的元素(差集) sdiff key1 key2
sidiffstore dest key1 key2 返回key1中特有的元素,并将返回值缓存到dest集合中 sidiffstore dest key1 key2
sinter key1 key2 返回key1跟key2集合的交集 sinter key1 key2
sinterstore dest key1 key2 返回key1跟key2集合的交集,并将返回值缓存到dest集合中 sinterstore dest key1 key2
sunion key1 key2 返回key1跟key2集合的并集 sunion key1 key2
sunionstore dest key1 key2 返回key1跟key2集合的并集,并将返回值缓存到dest集合中 sunionstore dest key1 key2
smove source destination member 将source集合中member元素移动到destination集合中 smove key1 key2 aa
sismember key member 判断member元素是否在key集合中 sismember key1 aa
srandmember key count 随机获取set集合中count 个元素 srandmem
bash 复制代码
# 交集运算
SINTER key [key ...]
# 将交集结果存入新集合destination中
SINTERSTORE destination key [key ...]

# 并集运算
SUNION key [key ...]
# 将并集结果存入新集合destination中
SUNIONSTORE destination key [key ...]

# 差集运算
SDIFF key [key ...]
# 将差集结果存入新集合destination中
SDIFFSTORE destination key [key ...]

3.5.4、应用场景

集合的主要几个特性,无序、不可重复、支持并交差等操作。因此 Set 类型比较适合用来数据去重和保障数据的唯一性,还可以用来统计多个集合的交集、错集和并集等,当我们存储的数据是无序并且需要去重的情况下,比较适合使用集合类型进行存储。

Set 的差集、并集和交集的计算复杂度较高,在数据量较大的情况下,如果直接执行这些计算,会导致 Redis 实例阻塞

在主从集群中,为了避免主库因为 Set 做聚合计算(交集、差集、并集)时导致主库被阻塞,我们可以选择一个从库完成聚合统计,或者把数据返回给客户端,由客户端来完成聚合统计。

  1. 点赞场景:Set 类型可以保证一个用户只能点一个赞,这里举例子一个场景,key 是文章id,value 是用户id。

    bash 复制代码
    # uid:1 、uid:2、uid:3 三个用户分别对 article:1 文章点赞了
    # uid:1 用户对文章 article:1 点赞
    > SADD article:1 uid:1
    (integer) 1
    # uid:2 用户对文章 article:1 点赞
    > SADD article:1 uid:2
    (integer) 1
    # uid:3 用户对文章 article:1 点赞
    > SADD article:1 uid:3
    (integer) 1
    bash 复制代码
    # uid:1 取消了对 article:1 文章点赞。
    > SREM article:1 uid:1
    (integer) 1
    
    # 获取 article:1 文章所有点赞用户 
    > SMEMBERS article:1
    1) "uid:3"
    2) "uid:2"
    
    # 获取 article:1 文章的点赞用户数量
    > SCARD article:1
    (integer) 2
    
    # 判断用户 uid:1 是否对文章 article:1 点赞了
    > SISMEMBER article:1 uid:1
    (integer) 0  # 返回0说明没点赞,返回1则说明点赞了
  2. 共同关注:Set 类型支持交集运算,所以可以用来计算共同关注的好友、公众号等

    bash 复制代码
    # key 可以是用户id,value 则是已关注的公众号的id。
    # uid:1 用户关注公众号 id 为 5、6、7、8、9,uid:2 用户关注公众号 id 为 7、8、9、10、11
    
    # uid:1 用户关注公众号 id 为 5、6、7、8、9
    > SADD uid:1 5 6 7 8 9
    (integer) 5
    # uid:2  用户关注公众号 id 为 7、8、9、10、11
    > SADD uid:2 7 8 9 10 11
    (integer) 5
    
    # 获取共同关注
    > SINTER uid:1 uid:2
    1) "7"
    2) "8"
    3) "9"
    
    # 给 uid:2 推荐 uid:1 关注的公众号
    > SDIFF uid:1 uid:2
    1) "5"
    2) "6"
    
    # 验证某个公众号是否同时被 uid:1 或 uid:2 关注:
    > SISMEMBER uid:1 5
    (integer) 1 # 返回0,说明关注了
    > SISMEMBER uid:2 5
    (integer) 0 # 返回0,说明没关注
  3. 抽奖活动:存储某活动中中奖的用户名 ,Set 类型因为有去重功能,可以保证同一个用户不会中奖两次

    bash 复制代码
    # key为抽奖活动名,value为员工名称,把所有员工名称放入抽奖箱
    >SADD lucky Tom Jerry John Sean Marry Lindy Sary Mark
    (integer) 5
    
    # 如果允许重复中奖,可以使用 SRANDMEMBER 命令
    # 抽取 1 个一等奖:
    > SRANDMEMBER lucky 1
    1) "Tom"
    # 抽取 2 个二等奖:
    > SRANDMEMBER lucky 2
    1) "Mark"
    2) "Jerry"
    # 抽取 3 个三等奖:
    > SRANDMEMBER lucky 3
    1) "Sary"
    2) "Tom"
    3) "Jerry"

    如果不允许重复中奖,可以使用 SPOP 命令

    bash 复制代码
    # 抽取一等奖1个
    > SPOP lucky 1
    1) "Sary"
    # 抽取二等奖2个
    > SPOP lucky 2
    1) "Jerry"
    2) "Mark"
    # 抽取三等奖3个
    > SPOP lucky 3
    1) "John"
    2) "Sean"
    3) "Lindy"

3.6、Zset类型

  • Zset 类型(有序集合类型)相比于 Set 类型多了一个排序属性 score(分值),对于有序集合 ZSet 来说,每个存储元素相当于有两个值组成的,一个是有序集合的元素值,一个是排序值。
  • 有序集合保留了集合不能有重复成员的特性(分值可以重复),但不同的是,有序集合中的元素可以排序。

3.6.1、内部实现

Zset 类型的底层数据结构是由压缩列表或跳表实现的:

  • 如果有序集合的元素个数小于 128 个,并且每个元素的值小于 64 字节时,Redis 会使用压缩列表作为 Zset 类型的底层数据结构;
  • 如果有序集合的元素不满足上面的条件,Redis 会使用跳表作为 Zset 类型的底层数据结构;

在 Redis 7.0 中,压缩列表数据结构已经废弃了,交由 listpack 数据结构来实现了。

3.6.1、常用的命令

命令格式 功能 案例 说明
zadd key score member 往key集合中添加member元素,分数为score zadd players 100 a 向players集合添加a元素,分数为100
zincrby key increment member 将key集合中的member元素 分数 + increment zadd players 100 a 向players集合的a元素分数+100
zrange key start stop [withscores] 将key集合中的元素按分数升序排列 [显式分数] zrange players 0 -1 withscores
zrevrange key start stop [withscores] 将key集合中的元素按分数降序排列 [显式分数] zrevrange players 0 -1 withscores
zrank key member 返回member元素在key结合中的正序排名 zrank players a 返回players集合中a元素的正序排名
zrevrank key member 返回member元素在key结合中的倒序排名 zrevrank players a
zcard key 返回key集合元素个数 zcard players
bash 复制代码
# 往有序集合key中加入带分值元素
ZADD key score member [[score member]...]   
# 往有序集合key中删除元素
ZREM key member [member...]                 
# 返回有序集合key中元素member的分值
ZSCORE key member
# 返回有序集合key中元素个数
ZCARD key 

# 为有序集合key中元素member的分值加上increment
ZINCRBY key increment member 

# 正序获取有序集合key从start下标到stop下标的元素
ZRANGE key start stop [WITHSCORES]
# 倒序获取有序集合key从start下标到stop下标的元素
ZREVRANGE key start stop [WITHSCORES]

# 返回有序集合中指定分数区间内的成员,分数由低到高排序。
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

# 返回指定成员区间内的成员,按字典正序排列, 分数必须相同。
ZRANGEBYLEX key min max [LIMIT offset count]
# 返回指定成员区间内的成员,按字典倒序排列, 分数必须相同
ZREVRANGEBYLEX key max min [LIMIT offset count]

Zset 运算操作(相比于 Set 类型,ZSet 类型没有支持差集运算):

bash 复制代码
# 并集计算(相同元素分值相加),numberkeys一共多少个key,WEIGHTS每个key对应的分值乘积
ZUNIONSTORE destkey numberkeys key [key...] 
# 交集计算(相同元素分值相加),numberkeys一共多少个key,WEIGHTS每个key对应的分值乘积
ZINTERSTORE destkey numberkeys key [key...]

3.6.2、非常用命令

命令格式 功能 案例
zrangebyscore key min max [withscores] 按[min, max) 分数范围返回key集合中元素(正序) zrangebyscore players 200 300 withscores
zrevrangebyscore key min max [withscores] 按[min, max) 分数范围返回key集合中元素(倒序) zrevrangebyscore players 200 300 withscores
zrem key member 删除key集合中member元素与分数 zrem players a
zremrangebyscore key min max withscores 按[min, max) 分数范围删除key集合中元素 zremrangebyscore players 200 300 withscores
zremrangebyrank key start stop 删除key集合正序排名落在[start, stop) 范围元素 zremrangebyrank players 10 20
zcount key min max 按照分数范围[min, max]统计key集合中元素个数 zcount players 100 300

3.6.4、应用场景

​ Zset 类型(Sorted Set,有序集合) 可以根据元素的权重来排序,我们可以自己来决定每个元素的权重值。比如说,我们可以根据元素插入 Sorted Set 的时间确定权重值,先插入的元素权重小,后插入的元素权重大。

​ 在面对需要展示最新列表、排行榜等场景时,如果数据更新频繁或者需要分页显示,可以优先考虑使用 Sorted Set。

  1. 排行榜:我们以博文点赞排名为例,小林发表了五篇博文,分别获得赞为 200、40、100、50、150。

    bash 复制代码
    # arcticle:1 文章获得了200个赞
    > ZADD user:xiaolin:ranking 200 arcticle:1
    (integer) 1
    # arcticle:2 文章获得了40个赞
    > ZADD user:xiaolin:ranking 40 arcticle:2
    (integer) 1
    # arcticle:3 文章获得了100个赞
    > ZADD user:xiaolin:ranking 100 arcticle:3
    (integer) 1
    # arcticle:4 文章获得了50个赞
    > ZADD user:xiaolin:ranking 50 arcticle:4
    (integer) 1
    # arcticle:5 文章获得了150个赞
    > ZADD user:xiaolin:ranking 150 arcticle:5
    (integer) 1

    文章 arcticle:4 新增一个赞,可以使用 ZINCRBY 命令(为有序集合key中元素member的分值加上increment):

    bash 复制代码
    > ZINCRBY user:xiaolin:ranking 1 arcticle:4
    "51"

    查看某篇文章的赞数,可以使用 ZSCORE 命令(返回有序集合key中元素个数):

    bash 复制代码
    > ZSCORE user:xiaolin:ranking arcticle:4
    "50"

    获取小林文章赞数最多的 3 篇文章,可以使用 ZREVRANGE 命令(倒序获取有序集合 key 从start下标到stop下标的元素):

    bash 复制代码
    # WITHSCORES 表示把 score 也显示出来
    > ZREVRANGE user:xiaolin:ranking 0 2 WITHSCORES
    1) "arcticle:1"
    2) "200"
    3) "arcticle:5"
    4) "150"
    5) "arcticle:3"
    6) "100"

    获取小林 100 赞到 200 赞的文章,可以使用 ZRANGEBYSCORE 命令(返回有序集合中指定分数区间内的成员,分数由低到高排序):

    bash 复制代码
    > ZRANGEBYSCORE user:xiaolin:ranking 100 200 WITHSCORES
    1) "arcticle:3"
    2) "100"
    3) "arcticle:5"
    4) "150"
    5) "arcticle:1"
    6) "200"

4、Key的设计

Redis 的key 设计讲究4个性:

4.1、唯一性

Redis 类似Map集合,key必须保证唯一,缓存同一个key时,后者会覆盖前者,所以必须要求唯一,那如何保证唯一呢?最常用的方式:使用缓存数据的主键作为key

比如:缓存员工信息

key value
1 员工1
2 员工2

其中的1, 2 是员工的id

4.2、可读性

可读性是保证Redis的key能做到见名知意,上面的员工id1, 员工id2 虽说能保证key唯一,但可读性非常差,维护key时,无法从1, 2中快速判断该key对应value值。所以一一般在保证key唯一的前提下,给key加上前缀:

key value
employee_info:id1 员工1
employee_info:id2 员工2

employee_info:id1employee_info:id2 这样子设计key,可读性就好多了。

  • 通用玩法:业务模块名:业务逻辑含义:其他:value类型
key value
employee :base.info:id1:hash 员工对象信息

业务模块名:表示该key属于哪个功能模块

业务逻辑含义段 :这里可以使用 . 分开, 具体业务逻辑表示

  • 比如:缓存员工权限:employee:auth.permission:id1:set 员工权限集合

其他:一般设置唯一标识,比如主键

value类型:key对应value类型值,提高可读性。

4.3、时效性

redis key一定要设置过期时间。要跟自己的业务场景,需要对key设置合理的过期时间。可以在写入key时,就要追加过期时间;也可以在按照需要动态设置。

这里要注意:

  • 不设置过期时间,这种key为永久key,会一直占用内存不释放,时间久了,数量一多,就容易达到服务器的内存上限,导致宕机,开发时一般配合Key过期策略使用哦。
  • key的时效性设置,必须根据业务场景进行评估,设置合理有效期;

4.4、灵活性

这个难介绍,一般key保证唯一时,可以使用主键,有的使用一个主键不能表达出全部意思,可以使用联合主键。

比如:id为1的朋友圈下id为A的评论。

key value
post:1:reply:A 评论内容
post:1:reply:B 评论内容

5、设置密码

下面我们将介绍两种常用的方法来为Redis设置密码:

5.1、通过配置文件设置密码

在Redis的配置文件redis.conf中,可以通过以下步骤来设置密码:

  1. 打开redis.conf文件(我的是在./www/server/redis/redis-7.2.3目录下)
  2. 找到并取消注释requirepass
  1. requirepass后面添加你想要设置的密码,如requirepass 1234

  2. 保存并关闭配置文件。

  3. 重新启动Redis服务器,使密码生效。

5.2、通过命令行设置密码

除了通过配置文件,还可以直接通过命令行来为Redis设置密码。打开终端并输入以下命令:

bash 复制代码
redis-cli

接着,在命令行中输入以下命令来设置密码:

bash 复制代码
config set requirepass mypassword

运行上述命令后,Redis将返回OK表示密码设置成功。

验证:

  • 在redis命令行中,使用auth mypassword来验证密码
  • 如果密码正确,Redis将返回OK,表示密码验证成功。

5.3、更改密码

  1. 在redis命令行中更改
bash 复制代码
config set requirepass newpassword

替换newpassword为你想要设置的新密码。

5.4、取消密码

  1. 在redis命令行中更改
bash 复制代码
config set requirepass ""

运行上述命令后,Redis将返回OK,表示密码已成功取消。

多,就容易达到服务器的内存上限,导致宕机,开发时一般配合Key过期策略使用哦。

  • key的时效性设置,必须根据业务场景进行评估,设置合理有效期;

4.4、灵活性

这个难介绍,一般key保证唯一时,可以使用主键,有的使用一个主键不能表达出全部意思,可以使用联合主键。

比如:id为1的朋友圈下id为A的评论。

key value
post:1:reply:A 评论内容
post:1:reply:B 评论内容
相关推荐
yuenblue42 分钟前
什么是ondelete cascade以及使用sqlite演示ondelete cascade使用案例
数据库·sqlite
howard_shooter1 小时前
Oracle Managed Files(OMF)
数据库·oracle
yangfeipancc1 小时前
数据库-用户管理
android·数据库
两点王爷3 小时前
Java读取csv文件内容,保存到sqlite数据库中
java·数据库·sqlite·csv
凡人的AI工具箱4 小时前
每天40分玩转Django:Django部署概述
开发语言·数据库·后端·python·django
2401_871213305 小时前
mysql之MHA
数据库·mysql
言之。5 小时前
【MySQL】事务
数据库·mysql
潇湘秦5 小时前
Oracle 11G还有新BUG?ORACLE 表空间迷案!
数据库·oracle
凡人的AI工具箱6 小时前
每天40分玩转Django:Django Email
数据库·人工智能·后端·python·django·sqlite
后端转全栈_小伵6 小时前
SQLite本地数据库的简介和适用场景——集成SpringBoot的图文说明
数据库·spring boot·后端·sqlite·学习方法