版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zx711166/article/details/82704316
字符串的内部编码
字符串类型的内部编码有3种:
- int:8个字节的长整型
- embstr:小于等于39个字节的字符串
- raw:大于39个字节的字符串
Redis会根据当前值的类型和长度决定使用内部编码实现。
整数类型示例如下:
127.0.0.1:6379> set str 1234567
OK
127.0.0.1:6379> object encoding str
"int"
短字符串示例如下:
127.0.0.1:6379> set str "hello world"
OK
127.0.0.1:6379> object encoding str
"embstr"
长字符串示例如下:
127.0.0.1:6379> set str "Tranquil,unbeatable to the outside. -- yangming" #“凝聚于内,无敌于外。--王阳明”
OK
127.0.0.1:6379> object encoding str
"raw"
字符串类型的使用场景:
- 缓存
- 计数器
- 分布式锁等
字符串类型的相关命令:
get、set、del
- get key:获取key对应的value,时间复杂度O(1)。
- set key:设置key-value,时间复杂度O(1)。
- del key:删除key-value,时间复杂度O(1)。
redis> set hello "world"
OK
redis> get hello
"world"
redis> del hello
1
reids> get hello
nil
incr、decr、incrby、decrby
- incr key:key自增1, 如果key不存在,自增后get(key)=1,时间复杂度O(1)。
- decr key:key自减1,如果key不存在,自减后get(key)=-1,时间复杂度O(1)。
- incrby key k:key自增k,如果key不存在,自增后get(key)=k,时间复杂度O(1)。
- decrby key k:key自减k,如果key不存在,自减后get(key)=-k,时间复杂度O(1)。
redis> get counter
(nil)
reids> incr counter
(integer) 1
redis> get counter
"1"
redis> incrby counter 99
(integer) 100
redis> decr counter
(integer) 99
redis> get counter
"99"
实战
- 实现一下功能:记录网站每个用户个人主页的访问量?
解决:incr userid:pageview(单线程:无竞争;因为单线程,并发执行incr时无竞争问题)。 - 实现一下功能:缓存视频的基本信息(数据源在MySQL中)伪代码?
解决:把视频的id为key,视频信息为value,存入redis中。
//伪代码
public VideoInfo get(long id){
String redis = redisPrefix + id;
//redis中只能取出二进制或者字符串,不能真正返回对象
VideoInfo videoInfo = redis.get(redisKey);
if(videoInfo == null){
videoInfo = mysql.get(id);
if(videoInfo != null){
//序列化
redis.set(redisKey, serialize(videoInfo));
}
}
return videoInfo;
}
- 实现如下功能:分布式id生成器(三个Java Servic,每次获取的id时自增的,三个应用并发获取不会重复)?
解决:redis是单线程的,而且incr这样的命令是可以逐步递增,不会产生新的条件的;所以依然可以使用incr id(原子操作)。
set、setnx、setxx
- set key value:不管key是否存在,都设置,时间复杂度O(1)。
- setnx key value:key不存在,才设置,时间复杂度O(1)。
- set key value xx:key存在,才设置,时间复杂度O(1)。
redis> exists php
(integer) 0
redis> set php good
OK
redis> setnx php bad
(integer) 0
redis> set php best xx
OK
redis> get php
"best"
redis> exists java
(integer) 0
redis> setnx java best
(integer) 1
redis> set java easy xx
OK
redis> get java
"easy"
redis> exists lua
(integer) 0
redis> set lua hehe xx
(nil)
mget、mset
- mget key1 key2 key3 …:批量获取key,原子操作,时间复杂度O(n)。
- mset key1 value1 key2 value2 key3 value3:批量设置key-value,时间复杂度O(n)。
redis> mset hello world java best php good
OK
redis> mget hello java php
"world"
"best"
"good"
注:n次get,1次mget的对比;在网络开销上将大大减少,但是mget也不是无限操作,返回几十万个key不论对于网络开销还是返回的时间都不太友好。
getset、append、strlen
- getset key newvalue:set key newvalue并返回旧的value,原子操作,时间复杂度O(1)。
- append key value:将value追加到旧的value,时间复杂度O(1)。
- strlen key:返回字符串的长度(注意中文),时间复杂度O(1)。
redis> set hello world
OK
redis> getset hello php
"world"
redis> append hello ",java"
(integer) 8
reids> get hello
"php,java"
reids> strlen hello
(integer) 8
redis> set hello "足球"
OK
redis> strlen hello //使用的utf-8编码,每个中文占两个字节
(integet) 4
incrbyfloat、getrange、setrange
- incrbyfloat key 3.5:增加key对应的值3.5,时间复杂度O(1)。
- getrange key start end:获取字符串指定下标所有的值,时间复杂度O(1)。
- setrange key index value:设置指定下标所有对应的值,时间复杂度O(1)。
redis> incr counter
(integer) 1
redis> incrbyfloat counter 1.1
"2.1"
redis> get counter
"2.1"
redis> set hello javabest
OK
redis> getrange hello 0 2
"jav"
redis> setrange hello 4 p
(integer) 8
redis> get hello
"javapest"