企业级Redis开发运维从入门到实践 (4)— String数据结构的内部编码及相关命令详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 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"

猜你喜欢

转载自blog.csdn.net/zx711166/article/details/82704316