分布式学习第二天 redis学习

news2024/11/25 14:50:06

目录

1. 数据库类型

1.1 基本概念

1.2 关系/非关系型数据库搭配使用

2. Redis  

2.1 基本知识点

2.2 redis常用命令

2.4 redis数据持久化

3 hiredis的使用

4. 复习


1. 数据库类型

1.1 基本概念

  1. 关系型数据库 - sql

    • 操作数据必须要使用sql语句

    • 数据存储在磁盘

    • 存储的数据量大

    • 举例:

      • mysql

      • oracle

      • sqlite - 文件数据库

      • sql server

  2. 非关系数据库 - nosql

    • 操作不使用sql语句

      • 命令

    • 数据默认存储在内存

      • 速度快, 效率高

      • 存储的数据量小

    • 不需要数据库表

      • 以键值对的方式存储的

1.2 关系/非关系型数据库搭配使用

 

==RDBMS: Relational Database Management System== 关系型数据库

  1. 所有的数据默认存储在关系型数据库中

  2. 客户端访问服务器, 有一些数据, 服务器需要频繁的查询数据

    • 服务器首先将数据从关系型数据库中读出 -> 第一次

      • 将数据写入到redis中

    • 客户端第二次包含以后访问服务器

      • 服务器从redis中直接读数据

2. Redis  

  • 知道redis是什么?

    • 非关系型数据库 也可以叫 内存数据库

  • 能干什么?

    • 存储访问频率高的数据

    • 共享内存

      • 服务器端 -> redis

  • 怎么使用?

    • 常用的操作命令

      • 各种数据类型 -> 会查

    • redis的配置文件

    • redis的数据持久化

    • 写程序的时候如何对redis进行操作

      • 客户端 -> 服务器

2.1 基本知识点

  1. 安装包下载

    • 英文官方: Redis

    • 中文官方: CRUG网站

  2. Redis安装

    • make

    • make install

  3. redis中的两个角色

# 服务器 - 启动
redis-server	# 默认启动
redis-server confFileName # 根据配置文件的设置启动 远程
# 客户端
redis-cli	# 默认连接本地, 绑定了6379默认端口的服务器
redis-cli -p 端口号
redis-cli -h IP地址 -p 端口 # 连接远程主机的指定端口的redis
# 通过客户端关闭服务器
shutdown
# 客户端的测试命令
ping [MSG]

redis中数据的组织格式

  • 键值对

    • key: 必须是字符串 - "hello"

    • value: 可选的

      • String类型

      • List类型

      • Set类型

      • SortedSet类型

      • Hash类型

redis中常用数据类型

  • String类型

    • 字符串

  • List类型

    • 存储多个string字符串的

  • Set类型

    • 集合

      • stl集合

        • 默认是排序的, 元素不重复

      • redis集合

        • 元素不重复, 数据是无序的

  • SortedSet类型

    • 排序集合, 集合中的每个元素分为两部分

      • [分数, 成员] -> [66, ''tom'']

  • Hash类型

    • 跟map数据组织方式一样: key:value

      • Qt -> QHash, QMap

      • Map -> 红黑树

      • hash -> 数组

        • a[index] = xx 

2.2 redis常用命令

String类型

key -> string
value -> string
# 设置一个键值对->string:string
SET key value
# 通过key得到value
GET key
# 同时设置一个或多个 key-value 对
MSET key value [key value ...]
# 同时查看过个key
MGET key [key ...]
# 如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾
# key: hello, value: world, append: 12345 world12345
APPEND key value
# 返回 key 所储存的字符串值的长度
STRLEN key
# 将 key 中储存的数字值减一。
# 前提, value必须是数字字符串 -"12345"
DECR key

List类型 - 存储多个字符串

key -> string
value -> list
# 将一个或多个值 value 插入到列表 key 的表头
LPUSH key value [value ...]
# 将一个或多个值 value 插入到列表 key 的表尾 (最右边)。
RPUSH key value [value ...]
# list中删除元素
LPOP key # 删除最左侧元素
RPOP key # 删除最右侧元素
# 遍历
LRANGE key start stop
	start: 起始位置, 0
	stop: 结束位置, -1
# 通过下标得到对应位置的字符串
LINDEX key index
# list中字符串的个数
LLEN key

Set类型

key -> string
value -> set类型 ("string", "string1")
# 添加元素
# 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略
SADD key member [member ...]
# 遍历
SMEMBERS key
# 差集
SDIFF key [key ...]
# 交集
SINTER key [key ...]
# 并集
SUNION key [key ...]

SortedSet 类型

key -> string
value -> sorted ([socre, member], [socre, member], ...)
# 添加元素
ZADD key score member [[score member] [score member] ...]
# 遍历
ZRANGE key start stop [WITHSCORES] # -> 升序集合
ZREVRANGE key start stop [WITHSCORES] # -> 降序集合
# 指定分数区间内元素的个数
ZCOUNT key min max

Hash类型

 

key ->string
value -> hash ([key:value], [key:value], [key:value], ...)
# 添加数据
HSET key field value
# 取数据
HGET key field
# 批量插入键值对
HMSET key field value [field value ...]
# 批量取数据
HMGET key field [field ...]
# 删除键值对
HDEL key field [field ...]

Key 相关的命令

# 删除键值对
DEL key [key ...]
# 查看key值
KEYS pattern
查找所有符合给定模式 pattern 的 key 。
KEYS * 匹配数据库中所有 key 。
KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
KEYS h*llo 匹配 hllo 和 heeeeello 等。
KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo
# 给key设置生存时长
EXPIRE key seconds
# 取消生存时长
PERSIST key
# key对应的valued类型
TYPE key

配置文件是给redis服务器使用 的

  1. 配置文件位置

    • 从源码安装目录中找 -> redis.conf

  2. 配置文件配置项

# redis服务器绑定谁之后, 谁就能访问redis服务器
# 任何客户端都能访问服务器, 需要注释该选项
bind 127.0.0.1 192.168.1.100 
# 保护模式, 如果要远程客户端访问服务器, 该模式要关闭
protected-mode yes
# reids服务器启动时候绑定的端口, 默认为6379
port 6379
# 超时时长, 0位关闭该选项, >0则开启
timeout 0
# 服务器启动之后不是守护进程 一般会使用yes 让其为守护进程
daemonize yes
# 如果服务器是守护进程, 就会生成一个pid文件
# ./ -> reids服务器启动时候对应的目录
pidfile ./redis.pid
# 日志级别
 loglevel notice
# 如果服务器是守护进程, 才会写日志文件
 logfile "" -> 这是没写
 logfile "./redis.log" //打印的是终端的信息
 # redis中数据库的个数 默认是16个 类似于mysql中的database
 databases 16 
 	- 切换 select dbID [dbID == 0 ~ 16-1]

2.4 redis数据持久化

持久化: 数据从内存到磁盘的过程 关机之后内存的数据释放了 但是存在磁盘上 下次可以直接读取磁盘的数据

持久化的两种方式: rgb和aof两种方式

rgb数据完整性较低 但效率高 aof数据完整性高 但效率低

  • rdb方式

    • 这是一种默认的持久化方式, 默认打开

    • 磁盘的持久化文件xxx.rdb

    • 将内存数据以二进制的方式直接写入磁盘文件

    • 文件比较小, 恢复时间短, 效率高

    • 以用户设定的频率 -> 容易丢失数据

    • 数据完整性相对较低

  • aof方式

    • 默认是关闭的

    • 磁盘的持久化文件xxx.aof

    • 直接将生成数据的命令写入磁盘文件

    • 文件比较大, 恢复时间长, 效率低

    • 以某种频率 -> 1sec

    • 数据完整性高

# rdb的同步频率, 任意一个满足都可以 
save 900 1	//900s发生1次改变
save 300 10	//300发生10次改变
save 60 10000 
# rdb文件的名字
dbfilename dump.rdb


# 生成的持久化文件保存的那个目录下, rdb和aof
dir ./ 

# 是不是要打开aof模式
appendonly no
 -> 打开: yes
# 设置aof文件的名字
appendfilename "appendonly.aof"
# aof更新的频率
# appendfsync always
appendfsync everysec
# appendfsync no
  1. aof和rdb能不能同时打开?

    • 可以

  2. aof和rdb能不能同时关闭?

    • 可以

    • rdb如何关闭?

      save ""
  3. 两种模式同时开启, 如果要进行数据恢复, 如何选择?

    • 效率上考虑: rdb模式

    • 数据的完整性: aof模式

3 hiredis的使用

  1. hiredis的安装

    • 下载地址: Redis客户端连接工具资料 -- Redis中文网 -- Redis中国用户组(CRUG)

    • 安装

      • make

      • make

  2. hiredis API接口的使用

    连接数据库
// 连接数据库
redisContext *redisConnect(const char *ip, int port);
redisContext *redisConnectWithTimeout(const char *ip, 
                                      int port, const struct timeval tv);

执行redis命令函数

// 执行redis命令
void *redisCommand(redisContext *c, const char *format, ...);

//虽然返回的是void *实际上是redisply类型
// redisCommand 函数实际的返回值类型
typedef struct redisReply {
    /* 命令执行结果的返回类型 */
    int type; 
    /* 存储执行结果返回为整数 */
    long long integer;
    /* str变量的字符串值长度 */
    size_t len;
    /* 存储命令执行结果返回是字符串, 或者错误信息 */
    char *str;
    /* 返回结果是数组, 代表数据的大小 */
    size_t elements;
    /* 存储执行结果返回是数组*/
    struct redisReply **element;
} redisReply;

//访问数组里面的元素
redisReply a[100];
element[i]->str
    
//根据类型取出对应的值
type为类型
type状态表示含义
REDIS_REPLY_STRING==1返回值是字符串,字符串储存在redis->str当中,字符串长度为redi
REDIS_REPLY_ARRAY== 2返回值是数组,数组大小存在redis->elements里面,数组值存储在redis->element[i]里面。数组里面存储的是指向redisReply的指针,数组里面的返回值可以通过redis->element[i]->str来访问,数组的结果里全是type==REDIS_REPLY_STRING的redisReply对象指针。
REDIS_REPLY_INTEGER == 3返回整数long long,从integer字段获取值
REDIS_REPLY_NIL==4返回值为空表示执行结果为空
REDIS_REPLY_STATUS ==5返回命令执行的状态,比如set foo bar 返回的状态为OK,存储在str当中 reply->str == "OK" 。
REDIS_REPLY_ERROR ==6命令执行错误,错误信息存放在 reply->str当中。

 释放资源

// 释放资源
void freeReplyObject(void *reply);
void redisFree(redisContext *c);

案列代码

#include <stdio.h>
#include <hiredis.h>

int main()
{
    // 1. 连接redis服务器
    redisContext* c = redisConnect("127.0.0.1", 6379);
    if (c->err != 0)
    {
        return -1;
    }
    // 2. 执行redis命令
    void *prt = redisCommand(c, "hmset user userName zhang3 passwd 123456 age 23 sex man");
    redisReply* ply = (redisReply*)prt;
    if(ply->type == 5)
    {
        // 状态输出
        printf("状态: %s\n", ply->str);
    }
    freeReplyObject(ply);

    // 3. 从数据库中读数据
    prt = redisCommand(c, "hgetall user");
    ply = (redisReply*)prt;
    if(ply->type == 2)
    {
        // 遍历
        for(int i=0; i<ply->elements; i+=2)
        {
            printf("key: %s, value: %s\n", ply->element[i]->str, ply->element[i+1]->str);
        }
    }
    freeReplyObject(ply);

    redisFree(c);
    return 0;
}

4. 复习

fastDFS

  • 是什么?

    • 分布式文件系统

  • 干什么?

    • 提供文件上传

    • 提供文件下载

  • 怎么使用?

    • 根据主机的角色 -> 修改对应的配置文件

    • 启动各个角色

fdfs_trackerd /etc/fdfs/tracker.conf
fdfs_storaged /etc/fdfs/storage.conf
 客户端编写

 ![1531272014374](1531272014374.png)

 - 操作步骤

   1. 创建管道 - pipe
   2. 创建子进程
   3. 子进程干什么?

      - 写管道, 关闭读端
        - 将标准输出 -> 管道的写端
      - 重定向
      - 执行execl命令, 调用另外的进程fdfs_upload_file
      - 子进程退出
   4. 父进程?
      - 读管道, 关闭写端
      - 释放子进程资源 - pcb
        - wait()/ waitpid()

实现代码

fdfs.upload_file.h

#ifdef _FDFS_UPLOAD_FILE_H
#define _FDFS_UPLOAD_FILE_H

int upload_file1(const char *configfile, const char * myfile,char * fileid);
int upload_file2(const char * configFile, const char * upLoadFile, char * fileid, int size);

#endif

fdfs.upload_file.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "fdfs_client.h"
#include "fdfs_upload_file.h"

//第一种方法 改写源码 将其改为底层可用
int upload_file1(const char *configfile, const char * myfile,char * fileid)
{
	char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
	ConnectionInfo *pTrackerServer;
	int result;
	int store_path_index;
	ConnectionInfo storageServer;

	if ((result=fdfs_client_init(configfile)) != 0)
	{
		return result;
	}

	pTrackerServer = tracker_get_connection();
	if (pTrackerServer == NULL)
	{
		fdfs_client_destroy();
		return errno != 0 ? errno : ECONNREFUSED;
	}

	*group_name = '\0';
	if ((result=tracker_query_storage_store(pTrackerServer, \
	                &storageServer, group_name, &store_path_index)) != 0)
	{
		fdfs_client_destroy();
		fprintf(stderr, "tracker_query_storage fail, " \
			"error no: %d, error info: %s\n", \
			result, STRERROR(result));
		return result;
	}

	result = storage_upload_by_filename1(pTrackerServer, \
			&storageServer, store_path_index, \
			myfile, NULL, \
			NULL, 0, group_name, fileid);
	if (result == 0)
	{
		printf("%s\n", fileid);
	}
	else
	{
		fprintf(stderr, "upload file fail, " \
			"error no: %d, error info: %s\n", \
			result, STRERROR(result));
	}

	tracker_disconnect_server_ex(pTrackerServer, true);
	fdfs_client_destroy();

	return result;
}

//第二种方法 使用execlp
//使用多进程实现
int upload_file2(const char * configFile, const char * upLoadFile, char * fileid, int size)
{
	//1、创建管道
	int fd[2];
	int ret = pipe(fd);
	if (ret == -1)
	{
		perror("pipe error");
		return -1;
	}

	//2、创建子线程
	pid_t pid = fork();
	//如果是子线程
	if(pid == 0)
	{
		//3、重定向到管道的写端 old,new
		dup2(fd[1], STDIN_FILENO);

		//关闭读端
		close(fd[0]);

		//执行exclp命令
		execlp("file_upload_file", "xxx", configFile, upLoadFile, NULL);
		perror("execlp error");
	}
	else 
	{
		//关闭写端
		close(fd[1]);

		//读取数据 将数据读出到fileid参数中
		char buf[1024];
		read(fd[0], fileid, size);

		//回收子进程
		wait(NULL);
	}
}

main.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "fdfs_upload_file.h"

//查找位置 在编译时加上
//find / -name "fdfs_client.h"

int main(int argc, char **argv[])
{
    char fileID[1024];
    upload_file1("/etc/fdfs/client.conf", "main.c", fileID);
    printf("fileID: %s\n", fileID);
    printf("================================================================\n");

    upload_file2("/etc/fdfs/client.conf", "main.c", fileID, sizeof(fileID));
    printf("fileID: %s\n", fileID);
    return 0;
};

执行 需要找到头文件和库

gcc *.c -I /usr/include/fastdfs -I  /usr/include/fastcommon/ -lfdfsclient

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/663011.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用CDN给OSS做加速详解

意义 用户直接访问OSS资源&#xff0c;速度会受到OSS下行带宽以及Bucket地域的限制&#xff0c;若通过CDNOSS的方式进行访问&#xff0c;带宽上限更高&#xff0c;并且可以将OSS的资源缓存至就近的CDN节点&#xff0c;通过CDN节点进行分发&#xff0c;可以缩短网络传输距离&am…

Linux学习之CentOS(八)--Linux系统的分区概念

不知不觉已经记录了8篇Linux学习随笔了&#xff0c;虽然还是漂浮在Linux系统的表面&#xff0c;还有很多很多没有学&#xff0c;但是坚持学下去、坚持写下去就是成功的&#xff01;&#xff01;&#xff01;&#xff01; 在讲Linux系统分区之前&#xff0c;首先得介绍一下硬盘…

【SpringCloud】2.微服务的熔断和降级

目 录 1. 熔 断1.1 发生场景1.2 熔断实现1.3 熔断测试 2. 降 级2.1 发生场景2.2 降级处理2.3 降级测试 在 上篇博客&#xff0c;我们完成了项目的基本搭建工作&#xff0c;那这篇博客就来实现一下微服务的熔断和降级。 1. 熔 断 1.1 发生场景 在前面&#xff0c;我们用 spri…

【Java高级语法】(八)反射机制:有朋友问反射到底是怎样玩的?看完这篇文章你就清楚了~

Java高级语法详解之反射机制 :one: 概念:two: 优势和缺点:three: 使用3.1 Class类3.2 获取类的结构信息- 构造函数3.3 获取类的结构信息- 方法3.4 获取类的结构信息- 字段3.5 动态创建对象、调用方法和设置属性3.6 动态代理 :four: 底层原理:five: 应用场景:ear_of_rice: 总结:…

SedonaSQL 聚合函数使用说明

ST_Envelope_Aggr 函数说明: 返回几何的外边界 语法: ST_Envelope_Aggr (A:geometryColumn) 支持版本: v1.0.0 Spark SQL 举例说明: SELECT ST_Envelope_Aggr(pointdf.arealandmark) FROM pointdf运行示例(AggregateFunctionTest.java): ST_Intersection_Aggr 函数说明: …

大文件如何传输到电脑?亲测又快又简单!

我们平时可以因为各种原因&#xff0c;如更换新电脑、高清视频分享等&#xff0c;需要将大文件传输到另一台电脑上。大文件如何传输到电脑?相信这是很多朋友都想知道如何实现吧。我们为您提供了2种轻松将大文件从PC传输到PC的方法。话不多说&#xff0c;上技巧&#xff01; 方…

腾讯云服务器地域有什么区别?怎么选比较好

腾讯云服务器地域有什么区别&#xff1f;云服务器地域怎么选择&#xff1f;地域是指云服务器所在机房的地理位置&#xff0c;用户距离地域越近网络延迟越低&#xff0c;速度越快&#xff0c;所以地域就近选择即可。广州上海北京等地域网站域名需要备案&#xff0c;中国香港或其…

SpringBoot使用MockMVC单元测试Controller

前言&#xff1a; 在SpringBoot应用程序中&#xff0c;Controller是接受客户端请求并返回响应数据的核心组件。为了保证Controller的正确性和稳定性&#xff0c;我们可以使用MockMVC框架进行单元测试。MockMVC是Spring框架提供的一个HTTP客户端&#xff0c;用于模拟HTTP请求和响…

2023年智能优化算法之——增长优化器Growth Optimizer(GO),附MATLAB代码

增长优化器的主要设计灵感来源于个人在社会成长过程中的学习和反思机制。学习是个体通过从外部世界获得知识而成长的过程。反思是检查个人自身不足并调整个人学习策略以帮助个人成长的过程。参考文献如下&#xff1a; Zhang, Qingke, et al. “Growth Optimizer: A Powerful M…

二维码在固定资产实物盘点中的应用

很多企业为了掌握固定资产的后续使用情况和状态&#xff0c;会定期对投入使用的固定资产进行盘点&#xff0c;然而固定资产常会出现分散情况&#xff0c;在这种情况下让财务人员到达每个固定资产的所在处进行实地盘点显得极为不现实。 也有不少企业会在盘点过程中使用到固定资…

聊天室(一)___常见的基本功能实现

最近搞聊天室的人还挺多&#xff0c;正好自己也弄就总结自己遇到必不可少的一些功能&#xff0c;本篇文章主要为自己和看到我文章的人一种思路&#xff0c;希望大家不要把聊天室想的太复杂。 上图是我自己做的一个聊天室&#xff0c;类似微信的单聊群聊收藏等功能&#xff0c;根…

python+requests接口自动化框架详解,没有比这个更详细的了

目录 为什么要做接口自动化框架 正常接口测试的流程是什么&#xff1f; 一、接口框架如下&#xff1a; 二、接口的数据规范设计---Case设计 2.1注册接口用例 2.2登录接口用例 三、创建utils包&#xff1a;用来存放公共的类 3.1 ParseExcel.py 操作封装excel的类&#xf…

【AI工具】-Stable Diffusion本地化部署教程

前言 今天我们要介绍的是时下最流行的AI绘图软件Stable Diffusion&#xff0c;虽然Diffusion.ai已经开放api&#xff0c;但是长时间的商业化调用我们需要购买很多的金币。所以我们需要找一个平替的AI绘图平台&#xff0c;现在主流市场中AI绘图软件主要就是OpenAI的DALLE、midj…

SSM会议管理系统

SSM会议管理系统 后端基于SSM、前端基于Freemarker写的会议管理系统、使用JDK8、mysql使用5.7版本 技术栈 Spring SpringMVC MyBatis Mysql Freemarker jqueryajax[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JGo0luHu-1687163482019)(img.png)] …

【Python 随练】打印水仙花数

题目&#xff1a; 打印出所有的"水仙花数"&#xff0c;所谓"水仙花数"是指一个三位数&#xff0c;其各位数字立方和等于该数 简介&#xff1a; 在本篇博客中&#xff0c;我们将解决一个经典的数学问题&#xff1a;打印出所有的水仙花数。水仙花数是指一…

Unity核心5——Tilemap

Tilemap 一般称之为瓦片地图或者平铺地图&#xff0c;是 Unity2017 中新增的功能&#xff0c;主要用于快速编辑 2D 游戏中的场景&#xff0c;通过复用资源的形式提升地图多样性 ​ 工作原理就是用一张张的小图排列组合为一张大地图 ​ 它和 SpriteShape 的异同 共同点&#x…

浅析GPT2中的autoregressive和BERT的autoencoding源码实现

经常使用BERT来做研究&#xff0c;因此对Encoder的架构较为熟悉&#xff0c;但是从来没有了解过GPT这样的Decoder架构&#xff0c;尤其对自回归的形式不知道源码是如何实现的。 为了方便对比和讨论&#xff0c;接来下所探讨的源码都是基于HuggingFace这个框架的。 Bert注意力…

基于亚马逊云科技Serverless,朝夕光年和Second Dinner携手打造年度手游

经典的漫威IP&#xff0c;酷炫的卡牌对战&#xff0c;丰富的故事情节&#xff0c;这款移动游戏《MARVEL SNAP》一经上线就深得全球玩家喜爱。在The Game Awards 2022的年度颁奖典礼上&#xff0c;它更是以出色的表现&#xff0c;一举斩获最佳移动游戏奖项。 其研发公司Second …

【ElasticSearch】中文分词器

ES默认的analyzer&#xff08;分词器&#xff09;&#xff0c;对英文单词比较友好&#xff0c;对中文分词效果不好。不过ES支持安装分词插件&#xff0c;增加新的分词器。 1、如何指定analyzer&#xff1f; 默认的分词器不满足需要&#xff0c;可以在定义索引映射的时候&#…

Python自动办公之合并多个PDF文件

本文基于使用pycharm平台&#xff0c;使用glob库和PyPDF2库实现 首先将需要合并的文件放于一个文件中 如下图 addpdf文件夹为需要合并的文件位置 good.py为代码块 代码如下 print(这个小代码仅仅用于合并pdf文件数量小于10的情况) print() from PyPDF2 import PdfMerger,P…