龙空技术网

云计算服务架构进度数据池与状态数据池搭建和使用,Redis数据库

程序员高级码农II 137

前言:

现时我们对“云计算php”可能比较珍视,小伙伴们都想要剖析一些“云计算php”的相关资讯。那么小编同时在网上收集了一些关于“云计算php””的相关资讯,希望大家能喜欢,大家一起来学习一下吧!

Redis数据库

进度数据池和状态数据池的读写频率较高,且一般不需要保证数据的持久性,所以选用内存数据库比较合适。而相对于Memcached,Redis支持更多的数据结构和模式,对未知应用场景的包容性会更强一些。因此,Redis比较适合作为进度数据池与状态数据池的载体。下面将对Redis进行详细讲解。

说明:一般情况下,进度数据池和状态数据池中的数据更新频率是较高的,且新数据会覆盖旧数据,即使旧数据丢失,新的数据也会在最多几秒后产生。因此,进度数据池和状态数据池中的数据一般不需要保证持久性。另外,比较重要的数据需要通过定时任务定时写到磁盘数据库中。

Redis(Remote Dictionary Server,远程字典服务)是一个开源的键值(Key-Value)存储非关系型数据库,其数据按照“键值对”的形式进行组织、索引和存储。Redis的数据存储在内存当中,所以Redis的读写效率非常高。另外,Redis还支持消息订阅等功能。

Redis本身是一个独立软件,第三方软件需要与Redis建立通信后才能使用Redis。与Redis建立连接后,第三方软件可以向Redis发送操作指令,Redis处理完指令后会返回处理结果,如图5.28所示。

图5.28 第三方软件与Redis通信

1.Redis的基本操作

Redis的基本操作如代码5.19所示,包括创建与销毁连接、发送指令、返回结果处理和释放结果变量。Redis的指令与SQL类似,都是语句指令,只是Redis的指令远没有SQL丰富。需要注意的是,Redis不支持根据存储值的关键字查询。

说明:以下示例代码是使用C++编写的,除了C++以外,Redis还支持其他语言,如Python、Java、Ruby、PHP等。虽然实际使用的开发语言不尽相同,但调用方式是大同小异的。

代码5.19 Redis的基本操作

//Redis相关头文件,需要先安装相关的库(libhiredis-dev)

#include <hiredis/hiredis.h>

//定义连接变量,connecton为连接变量,与Redis通信都需要加上此变量

redisContext *connection;

//创建与销毁连接

//创建连接,需要Redis的IP地址与端口,6379为Redis的默认端口

connection = redisConnect ("IP地址", 6379);

if (connection == NULL || connect->err) {

//发生错误

}

//密码认证(实际上是发送了一条指令),无密码时无须调用

redisReply *reply = (redisReply *)redisCommand(connection, "AUTH %s",

"Redis密码");

if (reply->type == REDIS_REPLY_ERROR) {

//发生错误

}

//断开连接

redisFree(connection);

//发送指令

//向Redis发送指令,"Redis Command"为具体指令

redisReply *reply = (redisReply *)redisCommand(connection, "Redis

Common");

//返回结果处理

//通用说明:指令返回值处理,指令返回值会放到一个结构体变量中

redisReply *reply; //接收指令结果的变量//不同指令会返回不同的结果,根据reply->type判断

if(type->type == REDIS_REPLY_STRING){ //返回字符串

reply->str; //结果字符串的开始指针(char *)

reply->len; //结果字符串的长度

}

if(type->type == REDIS_REPLY_ARRAY){ //返回数组

for(int index = 0; index < reply->elements; index++){ //遍历数组

//获取数组中单个值

redisReply *tempReply = reply->element[index];

}

}

if(type->type == REDIS_REPLY_INTEGER){ //返回数字

reply->integer; //数字结果(long long)

}

if(type->type == REDIS_REPLY_NIL){ //无返回值

}

if(type->type == REDIS_REPLY_STATUS){ //返回状态

reply->str; //状态字符串的开始指针(char *)

reply->len; //状态字符串的长度

}

if(type->type == REDIS_REPLY_ERROR){ //发生错误

reply->str; //状态字符串的开始指针(char *)

reply->len; //状态字符串的长度

}

//释放结果变量

freeReplyObject(reply);

2.Redis的数据类型

Redis的数据都是以“键值对”的形式存储的,如图5.29所示。其中,“键值对中的键”是字符串,而“键值对中的值”支持多种数据类型,包括字符串、哈希表、列表、集合和有序集合。

图5.29 Redis中存储的数据

(1)键(Key)。键是负责标识数据的字符串。在Redis中,键是唯一的,如果使用相同的键存储不同的数据,那么后存储的数据会覆盖先存储的数据。键的常用操作如代码5.20所示,其中,返回结果的处理方式请参考代码5.19。

代码5.20 键的常用操作

//删除键,指令:DEL key

const char* key = "键的名称";

redisReply *reply = (redisReply *)redisCommand(connection, "DEL %s", key);

//检查键是否存在,指令:EXISTS key

const char* key = "键的名称";

redisReply *reply = (redisReply *)redisCommand(connection, "EXISTS %s", key);

//设置键的过期时间(

ms),指令:PEXPIRE key milliseconds

const char* key = "键的名称";

int milliseconds = 1000; //1000ms后过期

redisReply *reply = (redisReply *)redisCommand(connection, "PEXPIRE %s %d",

key, milliseconds);

//检索给定模式的键,指令:KEYS patternconst char* pattern = "abc*"; //可以添加通配符

redisReply *reply = (redisReply *)redisCommand(connection, "KEYS %s", key);

//修改键名称,指令:RENAME key newkey

const char* oldkey = "旧键名称";

const char* newkey = "新键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "RENAME %s %s",

oldkey, newkey);

(2)字符串(String)。字符串是数据的基本类型。Redis中的字符串是二进制安全的,也就是说,任意数据可以转换成字符串存储到Redis中,当该字符串被获取并重新转换成原本的数据格式时,数据不会产生偏差。通过这一特性,将JSON格式的数据转换成字符串后,即可存入Redis。字符串类型数据的常用操作如代码5.21所示,其中,返回结果的处理方式请参考代码5.19。

代码5.21 字符串类型数据的常用操作

//设置字符串的值,指令:SET key value

const char* key = "数据的键名称";

const char* value = "值";

redisReply *reply = (redisReply *)redisCommand(connection, "SET %s %s",

key, value);

//获取字符串的值,指令:GET key

const char* key = "数据的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "GET %s",

key);

(3)哈希表(Hash)。哈希表是字符串的“键值对”,哈希表的应用场景是存储一些结构化的数据,例如存储个人信息(包含用户名、年龄、性别等信息)。哈希表类型数据的常用操作如代码5.22所示,其中,返回结果的处理方式请参考代码5.19。

代码5.22 哈希表类型数据的常用操作

//设置哈希表中的值,指令:HSET key field value

const char* key = "数据的键名称";

const char* field = "哈希表的键名称";

const char* value = "哈希表的值";

redisReply *reply = (redisReply *)redisCommand(connection, "HSET %s %s

%s",key, field, value);

//获取哈希表中的值,指令:HGET key field

const char* key = "数据的键名称";

const char* field = "哈希表的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "HGET %s %s",

key, field);

//删除哈希表中的值,指令:HDEL key field

const char* key = "数据的键名称";

const char* field = "哈希表的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "HDEL %s %s",

key, field);

//在哈希表中查看键是否存在,指令:HEXISTS key field

const char* key = "数据的键名称";

const char* field = "哈希表的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "HEXISTS %s

%s", key, field);

//获取哈希表中的所有键,指令:HKEYS key

const char* key = "数据的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "HKEYS %s",

key);

(4)列表(List)。列表是字符串的列表,其顺序是按插入顺序排列的,插入新数据时,可以选择将数据添加到列表的头部(左)或者末尾(右)。列表中的字符串是可以重复的。列表类型数据的常用操作如代码5.23所示,其中,返回结果的处理方式请参考代码5.19。

代码5.23 列表类型数据的常用操作

//在列表的头部添加一个值,指令:LPUSH key value

const char* key = "数据的键名称";

const char* value = "值";

redisReply *reply = (redisReply *)redisCommand(connection, "LPUSH %s

%s", key, value);

//在列表的末尾添加一个值,指令:RPUSH key value

const char* key = "数据的键名称";

const char* value = "值";

redisReply *reply = (redisReply *)redisCommand(connection, "RPUSH %s

%s", key, value);

//获取并移除列表中的第一个值,指令:LPOP key value

const char* key = "数据的键名称";redisReply *reply = (redisReply *)redisCommand(connection, "LPOP %s %s",

key, value);

//获取并移除列表中的最后一个值,指令:RPOP key value

const char* key = "数据的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "RPOP %s %s",

key, value);

//通过索引获取列表的值,指令:LINDEX key index

const char* key = "数据的键名称";

int index = 2; //索引

redisReply *reply = (redisReply *)redisCommand(connection, "LINDEX %s

%d", key, index);

(5)集合(Set)。集合是字符串的无序集合,集合中不能存储重复的字符串。使用集合的好处是可以进行交集、合集、差集等操作,例如利用集合的交集求共同的好友等。集合类型数据的常用操作如代码5.24所示,其中,返回结果的处理方式请参考代码5.19。

代码5.24 集合类型数据的常用操作

//向集合添加值,指令:SADD key value

const char* key = "数据的键名称";

const char* value = "值";

redisReply *reply = (redisReply *)redisCommand(connection, "SADD %s %s",

key, value);

//获取集合中的所有成员,指令:SMEMBERS key

const char* key = "数据的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "SMEMBERS %s ",

key);

//判断元素是否在集合当中,指令:SISMEMBER key value

const char* key = "数据的键名称";

const char* value = "需要判断的值";

redisReply *reply = (redisReply *)redisCommand(connection, "SISMEMBER

%s %s",

key, value);

//获取多个集合的交集,指令:SINTER key1 [key2]

const char* key1 = "数据的键名称";

const char* key2 = "数据的键名称";

const char* key3 = "数据的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "SINTER %s

%s %s",

key1, key2, key3);//获取多个集合的交集并存储在新的键中,指令:SINTERSTORE destination key1 [key2]

const char* destination = "存储的键名称"

const char* key1 = "数据的键名称";

const char* key2 = "数据的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "SINTERSTORE

%s %s %s",

destination, key1, key2);

//获取多个集合的合集,指令:SUNION key1 [key2]

const char* key1 = "数据的键名称";

const char* key2 = "数据的键名称";

const char* key3 = "数据的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "SUNION %s

%s %s",

key1, key2, key3);

//获取多个集合的合集并存储在新的键中,指令:SUNIONSTORE destination key1 [key2]

const char* destination = "存储的键名称"

const char* key1 = "数据的键名称";

const char* key2 = "数据的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "SUNIONSTORE

%s %s %s",

destination, key1, key2);

//获取多个集合的差集,指令:SDIFF key1 [key2]

const char* key1 = "数据的键名称";

const char* key2 = "数据的键名称";

const char* key3 = "数据的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "SDIFF %s %s

%s",

key1, key2, key3);

//获取多个集合的差集并存储在新的键中,指令:SDIFFSTORE destination key1 [key2]

const char* destination = "存储的键名称"

const char* key1 = "数据的键名称";

const char* key2 = "数据的键名称";

redisReply *reply = (redisReply *)redisCommand(connection, "SDIFFSTORE

%s %s %s",

destination, key1, key2);

(6)有序集合(Set)。有序集合是字符串的有序集合。有序集合与集合的区别是,有序集合的值都会关联一个浮点(double)类型的分数,Redis会按照分数对有序集合中的值进行自动排序。有序集合中不能存储重复的字符串,但分数是可以重复的。有序列表的应用场景是一些需要自动排序的场景,例如,获取成绩前十的学生姓名,有序集合的值为学生姓名,而分数为成绩。有序集合类型数据的常用操作如代码5.25所示,其中,返回结果的处理方式请参考代码5.19。

代码5.25 有序集合类型数据的常用操作

//向有序集合添加值,指令:ZADD key score value

const char* key = "数据的键名称";

const char* score = "分数"; //分数为浮点型,如14.32

const char* value = "值";

redisReply *reply = (redisReply *)redisCommand(connection, "ZADD %s %s

%s ",

key, score, value);

//移除有序集合中的值,指令:ZREM key value

const char* key = "数据的键名称";

const char* value = "值";

redisReply *reply = (redisReply *)redisCommand(connection, "ZREM %s %s",

key, value);

//增加有序集合中值的分数,指令:ZINCRBY key increment value

const char* key = "数据的键名称";

const char* increment = "增加的分数"; //分数为浮点型,负数时为减

const char* value = "值";

redisReply *reply = (redisReply *)redisCommand(connection, " ZINCRBY %s

%s %s ",

key, increment, value);

//获取有序集合中指定分数区间的值,指令:ZREVRANGEBYSCORE key min max

const char* destination = "存储的键名称"

const char* key = "数据的键名称";

const char* min = "下限分数"; //分数为浮点型

const char* max = "上限分数"; //分数为浮点型

redisReply *reply = (redisReply *)redisCommand(connection,

"ZREVRANGEBYSCORE

%s %s %s",

key, min, max);

//获取有序集合中指定值的分数,指令:ZSCORE key value

const char* key = "数据的键名称";

const char* value = "值";

redisReply *reply = (redisReply *)redisCommand(connection, "ZSCORE %s

%s", key, value);

3.Redis的发布订阅模式

Redis除了提供数据存储功能以外,还支持消息发布订阅模式。Redis的消息发布订阅模式可以充当消息队列,发布者向Redis的指定频道发送消息后,订阅该频道的订阅者都会收到消息。但Redis的发布订阅模式提供的功能相当简单,与RabbitMQ相比,其不支持消息确认和消息持久化等功能。另外,订阅者只能收到订阅时间节点以后发送的消息。

因此,Redis提供的发布订阅功能一般是不被提倡使用的,除非应用场景非常简单,且发布出去的消息允许丢失。

本文给大家讲解的内容是云计算服务架构:进度数据池与状态数据池的搭建和使用,Redis数据库下篇文章给大家讲解的内容是云计算服务架构:进度数据池与状态数据池的搭建和使用感谢大家的支持!

标签: #云计算php