redis(4):数据结构-String字符串

reids 中共计5种数据类型,字符串类型、散列类型、列表类型、集合类型、有序集合类型;从本文开始依次弄懂他们!!!


一、介绍

字符串类型是 Redis 中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据。你可以用其存储用户的邮箱、JSON化的对象甚至是一张图片。一个字符串类型键允许 存储的数据的最大容量是512 MB

字符串类型是其他4种数据类型的基础,其他数据类型和字符串类型的差别从某种角度 来说只是组织字符串的形式不同。例如,列表类型是以列表的形式组织字符串,而集合类型是以集合的形式组织字符串。

string表示的是一个可变的字节数组,我们初始化字符串的内容、可以拿到字符串的长度,可以获取string的子串,可以覆盖string的子串内容,可以追加子串。
在这里插入图片描述

Redis的字符串是动态字符串,是可以修改的字符串,内部结构实现上类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配,如图中所示,内部为当前字符串实际分配的空间capacity一般要高于实际字符串长度len。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。需要注意的是字符串最大长度为512M。


二、命令

1. 赋值 SET key value和 取值 GET key

SET和GET是Redis中最简单的两个命令,它们实现的功能和编程语言中的读写变量相 似,如 key = "hello"在Redis中是这样表示的:

 redis> SET key hello 
 OK
 想要读取键值则更简单: 
 redis> GET key 
 "hello" 
 当键不存在时会返回空结果。

在这里插入图片描述

2.递增数字 incr key

前面说过字符串类型可以存储任何形式的字符串,当存储的字符串是整数形式时, Redis 提供了一个实用的命令 INCR,其作用是让当前键值递增,并返回递增后的值,用法 为:

redis> INCR num 
(integer) 1
 redis> INCR num 
 (integer) 2 

当要操作的键不存在时会默认键值为0,所以第一次递增后的结果是1。当键值不是整数 时Redis会提示错误:

redis> SET foo lorem OK
redis> INCR foo
(error) ERR value is not an integer or out of range

思考: 如果 Redis 同时只连接了一个客户端,那么上面的代码没有任何问题。可当同一时间有多个客户端连接到Redis时,则有可能出现竞态条件(race condition)。

例如有两个客户端A和B 都要执行我们自己实现的 incr 函数并准备将同一个键的键值递增,当它们恰好同时执行到代码第二行时二者读取到的 键值是一样的,如“5”,而后它们各自将该值递增到“6”并使用 SET 命令将其赋给原键,结果虽然对键执行了两次递增操作,最终的键值却是“6”而不是预想中的“7”。
包括 INCR在内的所有Redis命令都是原子操作(atomic operation) ,无论多少个客户端同时连接,都不会 出现上述情况。


三、实践

1.文章访问量统计

例如假定key=csdn:blog:113208754代表csdn中博客文章ID为113208754的文章,

  • 则用户访问一次该文章,后台调用一次 *incr csdn:blog:113208754*,即可实现每次给文章访问次数+1,
  • 前台需要改文章总的访问次数,后端调用 *get csdn:blog:113208754* 即可得到;

key的设计规范可以根据公司自己内部定义;

2.生成自增ID

上面用到了文章ID,但是怎样生成文件ID呢,传统关系型数据库可以通过设置字段属性AUTO_INCREMENT来实现ID自增,在Redis中可以通过incr命令,例如
$incr csdn:blog //csdn:blog为定义的key,该命令可以实现自增效果

INCR命 令的返回值既是加入该对象后的当前类型的对象总数,又是该新增对象的ID。

3.存储文章数据

由于每个字符串类型键只能存储一个字符串,而一篇博客文章是由标题、正文、作者与 发布时间等多个元素构成的。为了存储这些元素,我们需要使用序列化函数(如PHP中的 serialize和JavaScript中的 JSON.stringify)将它们转换成一个字符串。除此之外因为字符串类 型键可以存储二进制数据,所以也可以使用MessagePack[6] 进行序列化,速度更快,占用空 间也更小。

至此我们已经可以写出发布新文章时与Redis操作相关的伪代码了:

// 首先获得新文章的 ID 
$postID = INCR posts:count 
// 将博客文章的诸多元素序列化成字符串 
$serializedPost = serialize($title, $content, $author, $time) 
// 把序列化后的字符串存一个入字符串类型的键中 
SET post:$postID:data, $serializedPost 

获取文章数据的伪代码如下(以访问ID为42的文章为例): 
// 从 Redis 中读取文章数据 
$serializedPost = GET post:42:data 
// 将文章数据反序列化成文章的各个元素 
$title, $content, $author, $time = unserialize($serializedPost)
// 获取并递增文章的访问数量 
$count = INCR post:42:page.view 

除了使用序列化函数将文章的多个元素存入一个字符串类型键中外,还可以对每个元素使用一个字符串类型键来存储;


四、命令拾遗

  1. 增加指定的整数 INCRBY key increment
    redis> INCRBY bar 2 (integer) 2 //一次增加2个数
  2. 减少指定的整数 DECR key 、DECRBY key decrement DECR用法同incr和incrby
  3. 增加指定浮点数 INCRBYFLOAT key increment INCRBYFLOAT命令类似INCRBY命令,差别是前者可以递增一个双精度浮点数,如:
    redis> INCRBYFLOAT bar 2.7
    “6.7”
  4. 向尾部追加值 APPEND key value
    APPEND作用是向键值的末尾追加value。如果键不存在则将该键的值设置为value,即 相当于 SET key value。返回值是追加后字符串的总长度。如:
 redis> SET key hello 
 OK
 redis> APPEND key " world!" 
 (integer) 12 
 此时 key 的值是"hello world!"。APPEND 命令的第二个参数加了双引号,原因是该参数 包含空格,在redis-cli中输入需要双引号以示区分。 
  1. 获取字符串长度 STRLEN key
    STRLEN命令返回键值的长度,如果键不存在则返回0。例如:
redis> STRLEN key 
(integer) 12 
redis> SET key 你好 
OK
redis> STRLEN key
(integer) 6 

前面提到了字符串类型可以存储二进制数据,所以它可以存储任何编码的字符串。例子 中Redis接收到的是使用UTF-8编码的中文,由于“你”和“好”两个字的UTF-8编码的长度都是 3,所以此例中会返回6。

  1. 同时获得/设置多个键值 MGET key [key …] MSET key value [key value …]
    MGET/MSET 与GET/SET 相似,不过MGET/MSET 可以同时获得/设置多个键的键值。 例如:
redis> MSET key1 v1 key2 v2 key 3 v3 
OK
redis> GET key2 "v2" 
redis> MGET key1 key3 
1) "v1" 
2) "v3" 

文中只是列了部分常见命令,更多命令见 http://www.redis.cn/commands.html, 可以进行搜索

在这里插入图片描述

相关推荐
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页