![f095b0f807bc5d7b99fa6f907a2920f1.png](https://img-blog.csdnimg.cn/img_convert/f095b0f807bc5d7b99fa6f907a2920f1.png)
4.3 String数据类型详解
4.3.1 自增减及长度
String命令拓展
append 增加key的值,类似于Java中的String里面的拼接字符串
strlen 查询当前key的长度,类似于Java中String里面的length方法
##增加一个Key
127.0.0.1:6379> set key1 v1
OK
##判断key
127.0.0.1:6379> exists key1
(integer) 1
##获取key
127.0.0.1:6379> get key1
"v1"
##获取key的类型
127.0.0.1:6379> type key1
string
##拼接key的值,如果当前key不存在,就相当于set一个key
127.0.0.1:6379> append key1 append
(integer) 8
##获取key
127.0.0.1:6379> get key1
"v1append"
##查看key的长度
127.0.0.1:6379> strlen key1
(integer) 8
接下来基于一个实际场景,来解释一个类似于**Java中的i++**命令,incr命令!
我们平常看到的微信文章浏览量,视频播放量 …只要每一个用户点击这篇文章或者进入这个视频,那么相对应的浏览量就会增加,这个数据是每时每刻都在变化的!能不能直接从数据库里面读取呢?,答案是不能的!这样对于整个系统来说,数据库层面的访问压力太大了!
我们可以使用Redis作为缓存中间件,让这个浏览量…数据都是从redis里面读取,然后设置合适的时间在把这个数据进行持久化操作! 这样对于整个系统来说,每当用户访问时,首先从redis缓存中读取,或没有才去访问数据库层,系统的数据库层面的压力将会大大减小
比如这边我设置一个key,来存放浏览量…,在使用redis的incr方法实现自增,每当一个用户访问时,后面我们就会学到Jedis,在Redis中使用的的命令方式,在Java中就调用相应的方法即可!
##新增一个key
127.0.0.1:6379> set num 1
OK
##设置这个key自增,类似于java中的i++
127.0.0.1:6379> incr num
(integer) 2
##获取这个key的值
127.0.0.1:6379> get num
"2"
##设置这个key自增,类似于java中的i++
127.0.0.1:6379> incr num
(integer) 3
##获取这个key的值
127.0.0.1:6379> get num
"3"
浏览量如果减一呢?
##设置这个Key自减
127.0.0.1:6379> decr num
(integer) 2
##设置这个Key自减
127.0.0.1:6379> get num
"2"
##设置这个Key自减
127.0.0.1:6379> decr num
(integer) 1
##设置这个Key自减
127.0.0.1:6379> get num
"1"
如果一下子想要增加10,或者更多呢?
##设置key增加到步长
127.0.0.1:6379> incrby num 10
(integer) 11
##获取key
127.0.0.1:6379> get num
"11"
##设置key减少的步长
127.0.0.1:6379> decrby num 10
(integer) 1
##获取key
127.0.0.1:6379> get num
"1"
4.3.2 范围获取值
Java中String工具包下有一个获取字符串的范围,range,思想都是相通的! Redis中也是有的!
Redis中: getrange
##新增一个key
127.0.0.1:6379> set key1 "This a Value"
OK
##获取一个key
127.0.0.1:6379> get key1
"This a Value"
##获取这个key [0,-1]范围的值
127.0.0.1:6379> getrange key1 0 -1
"This a Value"
##获取这个key [0,9]范围的值
127.0.0.1:6379> getrange key1 0 9
"This a Val"
##获取这个key [0,11]范围的值
127.0.0.1:6379> getrange key1 0 11
"This a Value"
##获取这个key [0,3]范围的值
127.0.0.1:6379> getrange key1 0 3
"This"
Java中还有一个方法,可以替换某一个范围的值!Redis中有没有呢?也是有的
Redis中: setrange
##清空
127.0.0.1:6379> clear
##获取get的值
127.0.0.1:6379> get key1
"This a Value"
##替换指定index的值
127.0.0.1:6379> setrange key1 6 xxx
(integer) 12
##获取key的值
127.0.0.1:6379> get key1
"This axxxlue"
4.3.3 设置key的过期时间
能不能再新增key的时候设置过期时间呢?
之前是利用exprie来设置的!
setex 设置过期时间
setnx 设置过期时间,如果不存在怎么怎么样
##新增key1的时候设置过期时间为30秒
127.0.0.1:6379> setex key1 30 v1
OK
##查看key的过期时间
127.0.0.1:6379> ttl key1
(integer) 25
##获取Key
127.0.0.1:6379> get key1
"v1"
##查看key的过期时间
127.0.0.1:6379> ttl key1
(integer) 16
##设置key,如果这个key不存在,则新增成功,
##若存在则新增失败,并不会覆盖当前key的值
127.0.0.1:6379> setnx key2 v2
(integer) 1
##获取Key
127.0.0.1:6379> get key2
"v2"
##设置key,如果这个key不存在,则新增成功,
##若存在则新增失败,并不会覆盖当前key的值
127.0.0.1:6379> setnx key2 v22
(integer) 0
##查看key的过期时间,-2代表已经过期
127.0.0.1:6379> ttl key1
(integer) -2
4.3.4 批量添加与获取
那这样一个一个的设置Key有点麻烦,能不能批量设置呢?
mset 批量设置key
mget 批量获取key
msetnx 批量设置key 这个key不存在则设置成功,如果存在则设置失败
为一个原子性的操作
##批量设置Key
127.0.0.1:6379> mset k1 v1 k2 v1
OK
##批量获取key
127.0.0.1:6379> mget k1 k2
1) "v1"
2) "v1"
##查看当前数据库中的所有key
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
##批量设置key 这个key不存在则设置成功,如果存在则设置失败
127.0.0.1:6379> msetnx k1 v1 k4 v4
(integer) 0
##批量设置key 这个key不存在则设置成功,如果存在则设置失败
127.0.0.1:6379> msetnx k4 v1 k1 v1
(integer) 0
##批量设置key 这个key不存在则设置成功,如果存在则设置失败
127.0.0.1:6379> msetnx k4 v1
(integer) 1
4.3.5 基于实际场景使用
考虑一下项目,如果我们要往redis中存一个对象,一般情况下,怎么存?
通常做法:
set user:1 {name: zhangsan,age: 3} 设置一个User对象的值为一个JSON字符串,来保存一个对象
127.0.0.1:6379> set user:1 "{name: zhangsan,age: 6}"
OK
127.0.0.1:6379> get user:1
"{name: zhangsan,age: 6}"
127.0.0.1:6379>
其实还有一种方法:
这种写法就类似于YML中的层级关系
##这种写法 key是为一个特殊的key
##user:{id}:{field}
##user:{id} 就可以实现复用
127.0.0.1:6379> mset user:1:name zhnagsan user:1:age 6
OK
127.0.0.1:6379> mget user:1
1) "age:6"
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhnagsan"
2) "6"
127.0.0.1:6379> keys *
1) "k2"
2) "user:1"
3) "k4"
4) "k1"
5) "user:1:name"
6) "user:1:age"
127.0.0.1:6379>
举个例子
我们一篇微信公众号的文章,不仅仅是有浏览量吧?还有再看,转发等等属性,这个微信文章是有一个固定的Id的,这些再看,点赞数,转发数,都是实时的更新的,那么我们可以把这些封装为一个对象,存放再redis中,如何设计呢?
mset wenzhang:{id}:{field}
mset wenzhang:10:dainzan 1 wenzhang:10:zaikan 1 wenzhang:10:zhuanfa 1
mget wenzhang:10:zaikan wenzhang:10:zaikan wenzhang:10:zhuanfa
127.0.0.1:6379> mset wenzhang:10:dainzan 1 wenzhang:10:zaikan 1 wenzhang:10:zhuanfa 1
OK
127.0.0.1:6379> keys *
1) "wenzhang:10:zhuanfa"
2) "wenzhang:10:zaikan"
3) "wenzhang:10:dainzan"
127.0.0.1:6379> mget wenzhang:10:zaikan wenzhang:10:zaikan wenzhang:10:zhuanfa
1) "1"
2) "1"
3) "1"
127.0.0.1:6379>
4.3.6 getset方法介绍
还有一个方法为getset
先get,再set
##当前查询是没有的!
127.0.0.1:6379> keys *
(empty array)
##如果这个key不存在,则返回null,接着再去新增这个key
127.0.0.1:6379> getset k1 v1
(nil)
##现在已经可以获取到这个key
127.0.0.1:6379> getset k1 v1
"v1"
##现在给这个key一个新的值,先get出现在的Key的值,
##再去set新的值给这个key
127.0.0.1:6379> getset k1 v2
"v1"
##现在获取到的已经是新的key
127.0.0.1:6379> getset k1 v2
"v2"
127.0.0.1:6379>
4.3.7 使用场景
String的使用场景:
Value可以是字符串,也可以是数字
可以在项目中当作
- 计数器
- 统计多单位的数量
- 粉丝数
- 对象缓存时间