Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。对应Java中的:String、 HashMap、LinkedList、 HashSet、 TreeSet
String(字符串)
string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
- 存储的数据:单个数据,最简单的数据存储类型,也是最常用的数据存储类型
- 存储数据的格式:一个存储空间保存一个数据
- 存储内容:通常使用字符串,如果字符串以纯整数的形式展示,可以作为数字操作使用
string 作为数值操作
- string在redis内部存储默认就是一个字符串,当遇到增减类操作incr, decr时会转成数值型进行计算。
- redis所有的操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发
带来的数据影响。 - 注意: 按数值进行操作的数据,如果原始数据不能转成数值,或超越了redis 数值上限范围,将报错。
9223372036854775807( java中long型数据最大值, Long.MAX_VALUE)
基础命令
命令 | 功能 |
---|---|
set key value | 添加/修改数据,set已有的key即为覆盖修改 |
get key | 获取数据 |
del key | 删除数据 |
mset key1 value1 key2 value2 … | 添加/修改多个数据 |
mget key1 key2 … | 获取多个数据 |
strlen key | 获取数据字符个数(字符串长度) |
append key value | 追加信息到原始信息后部(如果原始信息存在就追加,否则新建) |
>SET username chenheng
OK
>get username
"chenheng"
>del username
(integer) 1
>mset a 1 b 2 c 3
OK
>mget a b c
1) "1"
2) "2"
3) "3"
>strlen username
(integer) 8
>append a BCDE
(integer) 5 //追加成功,返回字符总个数
在set/get 单条 和 set/get 多条,在数据较多时,建议使用mset、 mget
扩展命令1
扩展命令 | 功能 |
---|---|
incr key | 数值数据自增1 |
incrby key increment | 设置数值数据增加指定范围的值 |
incrbyfloat key increment | 设置数值数据增加指定范围的小数值 |
decr key | 数值数据自减1 |
decrby key increment | 设置数值数据减少指定范围的值 |
//b=2
>incr b
(integer) 3
>incrby b 10
(integer) 13
>incrbyfloat b 0.5
"13.5"
扩展命令2
命令 | 功能 |
---|---|
setex key seconds value | 设置数据的值,并以秒为单位设置 key 的生存时间 |
psetex key milliseconds value | 设置数据的值,并以毫秒为单位设置 key 的生存时间 |
setnx key value | 将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则 SETNX 不做任何动作。 |
>setex a 5 name
OK
>get a
(nil)
注:在时效性数据存活期间,set 同名的普通数据,时效性数据的时效性就会被消除
应用场景
业务场景1
大型企业级应用中,分表操作是基本操作,使用多张表存储同类型数据,但是对应的主键 id 必须保证统一性
,不能重复。 Oracle 数据库具有 sequence 设定,可以解决该问题,但是 MySQL数据库并不具有类似的机
制,那么如何解决?
解决方案:设置key自增、自减
业务场景2
“最强女生”启动海选投票,只能通过微信投票,每个微信号每 4 小时只能投1票。
电商商家开启热门商品推荐,热门商品不能一直处于热门期,每种商品热门期维持3天, 3天后自动取消热门。
新闻网站会出现热点新闻,热点新闻最大的特征是时效性,如何自动控制热点新闻的时效性?
解决方案:设置数据具有指定的生命周期
业务场景3
主页高频访问信息显示控制,例如新浪微博大V主页显示粉丝数与微博数量
解决方案
在redis中为大V用户设定用户信息,以用户主键和属性值作为key,后台设定定时刷新策略即可
user:id:3506728370:fans → 12210947
user:id:3506728370:blogs → 6164
user:id:3506728370:focuss → 83
在redis中以json格式存储大V用户信息,定时刷新(也可以使用hash类型)
user:id:3506728370 → {"id":3506728370,"name":"春晚","fans":12210862,"blogs":6164, "focus":83}
string的应用
- redis用于控制数据库表主键id,为数据库表主键提供生成策略,保障数据库表的主键唯一性
此方案适用于所有数据库,且支持数据库集群 - redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作
- redis应用于各种结构型和非结构型高热度数据访问加速
- redis 应用于限时按次结算的服务控制
hash
Redis hash 是一个键值(key=>value)对集合。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
对象类数据的存储如果具有较频繁的更新需求操作会显得笨重 :
- 新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息
- 需要的存储结构:一个存储空间保存多个键值对数据
- hash类型:底层使用哈希表结构实现数据存储
- hash存储结构优化
- 如果field数量较少,存储结构优化为类数组结构
- 如果field数量较多,存储结构使用HashMap结构
基本命令
命令 | 功能 |
---|---|
hset key field value | 添加/修改一个字段的数据 |
hget key field | 获取一个字段的数据 |
hgetall key | 获取全部的key及value |
hdel key field1 [field2...] | 删除key |
hmset key field1 value1 [field2 value2 …] | 添加/修改多个字段数据 |
hmget key field1 [field2 …] | 获取多个数据 |
hlen key | 获取哈希表中字段的数量 |
hexists key field | 获取哈希表中是否存在指定的字段 |
> hset user name zhangsan
(integer) 1
> hget user name
"zhangsan"
> hset user age 12
(integer) 1
> hset user grade 3
(integer) 1
> hget user name
"zhangsan"
> hgetall user
1) "name"
2) "zhangsan"
3) "age"
4) "12"
5) "grade"
6) "3"
> hdel user grade
(integer) 1
> hmset user grade 3 class 2
OK
> hmget user grade class
1) "3"
2) "2"
> hlen user
(integer) 4
> hexists user class
(integer) 1
扩展命令
命令 | 功能 |
---|---|
hkeys key | 获取哈希表中所有的字段名 |
hvals key | 获取哈希表中所有的字段值 |
hincrby key field increment | 设置指定字段的数值数据增加指定范围的值 |
hincrbyfloat key field increment | 设置指定字段的数值数据增加指定范围的值 |
hsetnx key field value | 没有指定字段就添加 |
> hkeys user
1) "name"
2) "age"
3) "grade"
4) "class"
> hvals user
1) "zhangsan"
2) "12"
3) "3"
4) "2"
> hincrby user grade 4
(integer) 7
> hincrbyfloat user age 0.5
"12.5"
> hsetnx user age 10
(integer) 0
> hset user house 100
(integer) 1
注意事项
- hash类型下的value只能存储字符串,不允许存储其他数据类型,不存在嵌套现象。如果数据未获取到,
对应的值为( nil) - 每个 hash 可以存储 232 - 1 个键值对
- hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了存
储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用 - hgetall 操作可以获取全部属性,如果内部field过多,遍历整体数据效率就很会低,有可能成为数据访问
瓶颈
应用场景
业务场景1
电商网站购物车设计与实现
业务分析
分析购物车的redis存储模型,添加、浏览、更改数量、删除、清空
解决方案
- 以客户id作为key,每位客户创建一个hash存储结构存储对应的购物车信息
- 将商品编号作为field,购买数量作为value进行存储
- 添加商品:追加全新的field与value
- 浏览:遍历hash
- 更改数量:自增/自减,设置value值
- 删除商品:删除field
- 清空:删除key
为了加速了购物车商品信息的呈现
-
每条购物车中的商品记录保存成两条field
-
field1专用于保存购买数量
命名格式:商品id:nums
保存数据:数值 -
field2专用于保存购物车中显示的信息,包含文字描述,图片地址,所属商家信息等
命名格式:商品id:info
保存数据: json该字段的数据从一个商品信息独立hash中读取
使用
hsetnx key field value
动态创建和扩展独立hash
业务场景2
双11活动日,销售手机充值卡的商家对移动、联通、电信的30元、 50元、 100元商品推出抢购活动,每种商
品抢购上限1000张
解决方案
- 以商家id作为key
- 将参与抢购的商品id作为field
- 将参与抢购的商品数量作为对应的value
- 抢购时使用降值的方式控制产品数量
hash的应用
- redis 应用于购物车数据存储设计
- redis 应用于抢购,限购类、限量发放优惠卷、激活码等业务的数据存储设计
hash和string的比较
string存储:整体性,数据要么一次刚更新,要么一次性读取,主要用户呈现数据
hash: 更新灵活
list
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
- 数据存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分
- 需要的存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序
- list类型:保存多个数据,底层使用双向链表存储结构实现
基本命令
命令 | 功能 |
---|---|
lpush key value1 [value2] …… | 从左边添加/修改数据 |
rpush key value1 [value2] …… | 从右边添加/修改数据 |
lrange key start stop | 获取指定范围的列表数据 |
lindex key index | 获取指定下标的列表元素 |
llen key | 获取列表的长度 |
lpop key | 从左侧获取并移除一个数据 |
rpop key | 从右侧获取并移除一个数据 |
> lpush students zhangsan lisi wangwu
(integer) 3
> lrange students 0 -1
1) "wangwu"
2) "lisi"
3) "zhangsan"
> lindex students 1
"lisi"
> llen students
(integer) 3
> lpop students
"wangwu"
> rpop students
"zhangsan"
扩展命令1
命令 | 功能 |
---|---|
blpop key1 [key2] timeout | 规定时间内从左侧获取并移除一个数据 |
brpop key1 [key2] timeout | 规定时间内从右侧获取并移除一个数据 |
brpoplpush source destination timeout | 从列表中取出最后一个元素,并插入到另外一个列表的头部; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止 |
> blpop students 5
1) "students"
2) "lisi"
lrange list1 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "300"
6) "200"
7) "100"
> lpush list2 d e f g
(integer) 4
> brpoplpush list1 list2 5
"100"
> lrange list2 0 -1
1) "100"
2) "g"
3) "f"
4) "e"
5) "d"
扩展命令2
命令 | 功能 |
---|---|
lrem key count value | 从左侧移除指定数量的指定数据 |
> lrem list1 1 200
(integer) 1
应用场景
业务场景1
微信朋友圈点赞,要求按照点赞顺序显示点赞好友信息,如果取消点赞,移除对应好友信息
解决方案
移除指定数据
业务场景2
twitter、新浪微博、腾讯微博中个人用户的关注列表需要按照用户的关注顺序进行展示,粉丝列表需要将最近关注的粉丝列在前面。
新闻、资讯类网站如何将最新的新闻或资讯按照发生的时间顺序展示?
企业运营过程中,系统将产生出大量的运营数据,如何保障多台服务器操作日志的统一顺序输出?
解决方案
- 依赖list的数据具有顺序的特征对信息进行管理
- 使用队列模型解决多路信息汇总合并的问题
- 使用栈模型解决最新消息的问题
list的应用
- redis 应用于具有操作先后顺序的数据控制
- redis 应用于最新消息展示
注意事项
- list中保存的数据都是string类型的,数据总容量是有限的,最多232 - 1 个元素 (4294967295)。
- list具有索引的概念,但是操作数据时通常以队列的形式进行入队出队操作,或以栈的形式进行入栈出栈操作
- 获取全部数据操作结束索引设置为-1
- list可以对数据进行分页操作,通常第一页的信息来自于list,第2页及更多的信息通过数据库的形式加载
- redis 应用于基于时间顺序的数据操作,而不关注具体时间