Redis是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件MQ。它支持多种类型的数据结构,如 字符串(string),散列(hashes),列表(list),集合(sets),有序集合(sorted sets)与范围查询,bitmaps,hyperloglogs和地理空间(geospatial)索引半径查询。Redis内置了 复制(replocation),LUA脚本(Lua scripting),LRU驱动事件(LRU eviction),事务(transactions)和不同级别的 磁盘持久化(persistence),并通过 Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(high availability)
redis 数据存储格式
set key value
get key
del key
127.0.0.1:6379> set name maomao
OK
127.0.0.1:6379> get name
"maomao"
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> get name
(nil)
mset key1 value1 key2 value2 …
mget key1 key2 …
strlan key
append key value
127.0.0.1:6379> mset k1 a k2 b k3 c
OK
127.0.0.1:6379> mget k1 k2 k3
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> set name maomao
OK
127.0.0.1:6379> strlen name
(integer) 6
127.0.0.1:6379> append hello world
(integer) 5
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> append name zhu
(integer) 9
127.0.0.1:6379> get name
"maomaozhu"
业务场景
解决方案
设置数值数据增加指定范围的值
incr key
incrby key increment
incrbyfloat key increment
设置数值数据减少指定范围的值
decr key
decrby key increment
redis本身就是单线程的,所以可以用这种方式解决分布式ID的问题
127.0.0.1:6379> set num 0
OK
127.0.0.1:6379> incr num # 自增1
(integer) 1
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> get num
"2"
127.0.0.1:6379> decr num # 自减1
(integer) 1
127.0.0.1:6379> decr num
(integer) 0
127.0.0.1:6379> decr num
(integer) -1
127.0.0.1:6379> get num
"-1"
127.0.0.1:6379> incrby num 10 # 可以设置步长 指定增量
(integer) 9
127.0.0.1:6379> incrby num 10
(integer) 19
127.0.0.1:6379> decrby num 9
(integer) 10
127.0.0.1:6379> incrbyfloat num 2.5 # 小数
"12.5"
127.0.0.1:6379> incrby num 3.5 # incrby只能是int类型
(error) ERR value is not an integer or out of range
string 作为数值操作
redis 用于控制数据库表主键id,为数据库表主键提供生成策略,保障数据库表的主键唯一性。适用于所有数据库,且支持数据库集群
业务场景
解决方案
设置数据具有指定的生命周期
setex key seconds value
psetex key milliseconds value
设置独立的数据
setnx key value
127.0.0.1:6379> setex tel 10 '123456789' # 设置一个keys的值为num 10秒后过期
OK
127.0.0.1:6379> ttl tel # 生命周期
(integer) 6
127.0.0.1:6379> get tel
"123456789"
127.0.0.1:6379> ttl tel
(integer) 1
127.0.0.1:6379> get tel
(nil)
127.0.0.1:6379> setnx subject 'redis' # 如果key不存在 则创建相应的
(integer) 1
127.0.0.1:6379> setnx subject 'mongodb' # 如果key存在 则创建失败
(integer) 0
127.0.0.1:6379> get subject
"redis"
127.0.0.1:6379> psetex zhu 5000 'zhuzhu' # 毫秒
OK
127.0.0.1:6379> ttl zhu
(integer) 1
127.0.0.1:6379> get zhu
(nil)
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> msetnx k1 v1 k4 v4 # msetnx 是一个原子性的操作,要么一起成功,要么一起失败
(integer) 0
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> get k1
"v1"
redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作
获取字符串的范围
getrange key start end
替换指定范围的字符串
setrange key offset value
127.0.0.1:6379> set name 'hello,maomao'
OK
127.0.0.1:6379> get name
"hello,maomao"
127.0.0.1:6379> getrange name 0 3
"hell"
127.0.0.1:6379> getrange name 0 -1
"hello,maomao"
127.0.0.1:6379> setrange name 2 mmm
(integer) 12
127.0.0.1:6379> get name
"hemmm,maomao"
127.0.0.1:6379> setrange name 0 ilove
(integer) 12
127.0.0.1:6379> getrange name 0 -1
"ilove,maomao"
getset key value
127.0.0.1:6379> getset db redis # 如果不存在值 则返回 nil
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongoDB # 如果存在值,获取原来的值,并设置新的值
"redis"
127.0.0.1:6379> get db
"mongoDB"
set user:1 {
name:maomao,age:18} # 设置一个user:1 对象 值为 json字符来保存一个对象!
这里的key是一个巧妙地设计:user:{
id}:{
filed} , 如此设计在Redis中完全ok
127.0.0.1:6379> mset user:1:name maomao user:1:age 18 user:1:gender nv
OK
127.0.0.1:6379> mget user:1:name user:1:age user:1:gender
1) "maomao"
2) "18"
3) "nv"
主页高频访问信息显示控制,例如B站up主,主页显示粉丝数与,获赞数,播放数
127.0.0.1:6379> mset user:id:110:fans 2389000 user:id:110:likes 9476000 user:id:110:views 480000000OK
127.0.0.1:6379> mget user:id:110:fans user:id:110:likes user:id:110:views
1) "2389000"
2) "9476000"
3) "480000000"
127.0.0.1:6379> incr user:id:110:fans
(integer) 2389001
127.0.0.1:6379> incr user:id:110:views
(integer) 480000001
127.0.0.1:6379> incr user:id:110:views
(integer) 480000002
127.0.0.1:6379> mget user:id:110:fans user:id:110:likes user:id:110:views
1) "2389001"
2) "9476000"
3) "480000002"
127.0.0.1:6379> set user:id:120 {
id:120,name:wanglaoju,fans:2389000,likes:9476000,views:480000000}OK
127.0.0.1:6379> get user:id:120
"{id:120,name:wanglaoju,fans:2389000,likes:9476000,views:480000000}"
key 的设置约定
hash存储结构优化
添加/修改数据
hset key field value
获取数据
hget key field
hgetall key
删除数据
hdel key field1 [field2]
127.0.0.1:6379> hset user name xiaotian
(integer) 1
127.0.0.1:6379> hset user age 20
(integer) 1
127.0.0.1:6379> hset user gender nan
(integer) 1
127.0.0.1:6379> hgetall user
1) "name"
2) "xiaotian"
3) "age"
4) "20"
5) "gender"
6) "nan"
127.0.0.1:6379> hget user name
"xiaotian"
127.0.0.1:6379> hget user gender
"nan"
127.0.0.1:6379> hdel user gender
(integer) 1
127.0.0.1:6379> hgetall user
1) "name"
2) "xiaotian"
3) "age"
4) "20"
hmset key field1 value1 field2 value2 …
hmget key field1 field2 …
hlen key
hexists key field
127.0.0.1:6379> hmget user name age
1) "xiaotian"
2) "20"
127.0.0.1:6379> hmset user name feifei age 22 weight 46
OK
127.0.0.1:6379> hgetall user
1) "name"
2) "feifei"
3) "age"
4) "22"
5) "weight"
6) "46"
127.0.0.1:6379> hlen user # 获取的是field的数量
(integer) 3
127.0.0.1:6379> hexists user age # 判断是否存在指定字段
(integer) 1
127.0.0.1:6379> hexists user height
(integer) 0
hkeys key
hvals key
hincrby key field increment
hincrbyfloat key field increment
127.0.0.1:6379> hkeys user # 所有的字段名
1) "name"
2) "age"
3) "weight"
127.0.0.1:6379> hvals user # 所有的字段值
1) "feifei"
2) "22"
3) "46"
127.0.0.1:6379> hincrby user age 1
(integer) 23
127.0.0.1:6379> hincrby user weight 10 # 指定增量
(integer) 56
127.0.0.1:6379> hincrby user weight -5 # 指定减量
(integer) 51
解决方案
id:001指用户id
g01 g02 指商品id
127.0.0.1:6379> hmset id:001 g01 100 g02 200
OK
127.0.0.1:6379> hmset id:002 g02 10 g04 8 g05 100
OK
127.0.0.1:6379> hset id:001 g03 5
(integer) 1
127.0.0.1:6379> hgetall id:001
1) "g01"
2) "100"
3) "g02"
4) "200"
5) "g03"
6) "5"
127.0.0.1:6379> hdel id:001 g01
(integer) 1
127.0.0.1:6379> hgetall id:001
1) "g02"
2) "200"
3) "g03"
4) "5"
127.0.0.1:6379> hincrby id:001 g03 3
(integer) 8
127.0.0.1:6379> hgetall id:001
1) "g02"
2) "200"
3) "g03"
4) "8"
但目前这样是不够的,当前仅仅是将数据存储到了redis中,并没有起到加速的作用,商品信息还需要二次查询数据库
解决方案
每条购物车中的商品记录保存成两条field
field1专用于保存购买数量
field2专用于保存购物车中显示的信息,包含文字描述,图片地址,所属商家信息等
127.0.0.1:6379> hmset id:003 g01:nums 100 g01:info {
diannao,8000}
OK
127.0.0.1:6379> hgetall id:003
1) "g01:nums"
2) "100"
3) "g01:info"
4) "{diannao,8000}"
127.0.0.1:6379> hmset id:004 g01:nums 50 g01:info {
diannao,8000}
OK
127.0.0.1:6379> hgetall id:004
1) "g01:nums"
2) "50"
3) "g01:info"
4) "{diannao,8000}"
但这样又出现新的问题 就是g01:info是重复的,因此我们把field2作为独立hash 专门用来保存商品信息的hash
最后再做一个判断 ,如果field有值,则不添加,没有值就添加
hsetnx key field value
127.0.0.1:6379> hset id:004 g01:nums 200
(integer) 0
127.0.0.1:6379> hget id:004 g01:nums
"200"
127.0.0.1:6379> hsetnx id:004 g01:nums 400
(integer) 0
127.0.0.1:6379> hsetnx id:004 g05:nums 400
(integer) 1
127.0.0.1:6379> hgetall id:004
1) "g01:nums"
2) "200"
3) "g01:info"
4) "{diannao,8000}"
5) "g05:nums"
6) "400"
双11活动日,iphone商家对iPhone12,iPad Pro, MacBook Pro的5000元、6000元、10000元商品推出抢购活动,每种商
品抢购上限100台
解决方案
127.0.0.1:6379> hmset shop:001 iphone12 100 ipad 100 macbook 100
OK
127.0.0.1:6379> hincrby shop:001 iphone12 -1
(integer) 99
127.0.0.1:6379> hincrby shop:001 macbook -20
(integer) 80
127.0.0.1:6379> hgetall shop:001
1) "iphone12"
2) "99"
3) "ipad"
4) "100"
5) "macbook"
6) "80"