redis的安装与string类型

1. redis的安装

1.1 升级gcc版本

因为centos7.x的gcc版本还是4.8.5,而编译指定的版本是需要5.3以上。

  1. 环境部署与安装scl源

yum install gcc cmake -y --部署安装环境
yum install centos-release-scl scl-utils-build -y --安装scl源
  1. 安装gcc新版本

yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils --安装gcc
​
scl enable devtoolset-9 bash  --更新gcc版本
​
gcc -v --查看gcc版本
1.2 安装redis
tar zxvf redis-6.2.6.tar.gz   --解压源码包
​
cd redis-6.2.6                --进入解压目录
​
mkdir /www/
mkdir /www/server
​
make && make install PREFIX=/www/server/redis          --执行安装命令
​
mkdir /www/server/redis/conf
cp redis.conf /www/server/redis/conf/
cp sentinel.conf /www/server/redis/conf/
vim /www/server/redis/conf/redis.conf

配置下Redis的配置文件:

protected-mode no
daemonize yes
appendonly yes
./bin/redis-server /www/server/redis/conf/redis.conf 启动redis服务
​
ps -ef | grep redis   查看redis进程
​
./bin/redis-cli   启动redis客户端
​
keys *  查看所有的key
127.0.0.1:6379> set name "xx"
OK
127.0.0.1:6379> get name
"starsky"
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> quit
​
​

2.3 配置管理shell文件

这个脚本与之前的nginx脚本一样,都是用来做管理软件之用,我们进入到目录/etc/init.d下:

touch redis

创建了文件redis之后,我们使用vim命令进行编辑写入下面的内容:

#! /bin/sh
# chkconfig: 2345 55 25
​
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
NAMESERVER=redis-server
NAME=redis
REDIS_BIN=/www/server/redis/bin/$NAMESERVER
CONFIGFILE=/www/server/redis/conf/$NAME.conf
PIDFILE=/var/run/redis_6379.pid
ulimit -n 8192
​
case "$1" in
    start)
        echo -n "Staring $NAME..."
                if [ -f $PIDFILE ]; then
                        mPID=`cat $PIDFILE`
                        isStart=`ps ax | awk '{ print $1 }' | grep -e "^${mPID}$"`
                        if [ "$isStart" != '' ]; then
                                echo -e "\e[31m$NAME ( pid `pidof $NAMESERVER`) already running.\e[0m"
                                exit 1
                        fi
                fi
        $REDIS_BIN $CONFIGFILE
        if [ "$?" != 0 ] ; then
            echo -e "\e[31mfailed\e[0m"
            exit
        else
            echo -e "\e[32msuccess\e[0m"
        fi
        ;;
    stop)
        echo -n "Stoping $NAME..."
                if [ -f $PIDFILE ];then
                        mPID=`cat $PIDFILE`
                        isStart=`ps ax | awk '{ print $1 }' | grep -e "^${mPID}$"`
                        if [ "$isStart" = '' ];then
                                echo -e "\e[31m$NAME is not running.\e[0m"
                                exit 1
                        fi
                fi
                mPID=`cat $PIDFILE`
                kill -9 $mPID
​
                if [ "$?" != 0 ] ; then
                    echo -e "\e[31mfailed. Use force-quit\e[0m"
                    exit 1
                else
                    echo -e "\e[32mdone\e[0m"
                fi
                ;;
    status)
    if [ -f $PIDFILE ];then
                        mPID=`cat $PIDFILE`
                        isStart=`ps ax | awk '{ print $1 }' | grep -e "^${mPID}$"`
                        if [ "$isStart" != '' ];then
                                echo -e "\e[36m$NAME ( pid `pidof $NAMESERVER`) already running.\e[0m"
                                exit 1
                        else
                                echo -e "\e[31m$NAME is stopped\e[0m"
                                exit 0
                        fi
                else
                        echo -e "\e[31m$NAME is stopped\e[0m"
                        exit 0
                fi
                ;;
    restart)
        $0 stop
        sleep 1
        $0 start
        ;;
    *)
        echo -e "Usage: $0 {\e[36mstart|stop|restart|status\e[0m}"
        exit 1
    ;;
esac
 #>

测试脚本:

env: /etc/init.d/redis: 权限不够
[root@localhost init.d]# chmod 777 /etc/init.d/redis
[root@localhost init.d]# chkconfig -add /etc/init.d/redis
​
service redis start  # 启动redis
ps -ef | grep redis  # 查看redis进程是否存在,存在则已经启动
​
service redis stop   # 停止redis
ps -ef | grep redis  # 查看redis进程是否存在,不存在则已经停止
​
service redis status # 查看redis状态信息
​

2. string数据类型

2.1 类型介绍

String类型是redis的最基础的数据结构,也是最经常使用到的类型。而且其他的四种类型多多少少都是在字符串类型的基础上构建的,所以String类型是redis的基础。

string 类型的值最大能存储 512MB,这里的String类型可以是简单字符串、复杂的xml/json的字符串、二进制图像或者音频的字符串、以及可以是数字的字符串。

set 命令

描述:该命令用于设置给定 key 的值。如果 key 已经存储其他值, SET 就覆写旧值,且无视类型

127.0.0.1:6379> set name xx
OK
127.0.0.1:6379>

通过set命令给restkey这个key值绑定value,当SET在设置操作成功完成时,才返回 OK

get 命令

描述:该命令用于获取指定 key 的值。如果 key不存在,返回 nil 。如果key对应储存的值不是字符串类型,返回一个错误。

127.0.0.1:6379> get name
"xx"
127.0.0.1:6379>

getset命令

描述:该命令用于获取指定的key的旧值,然后按照新值对key进行赋值。当key中没有旧值的时候返回nil。

127.0.0.1:6379> getset name aa
"bb"
127.0.0.1:6379> get name
"aa"
127.0.0.1:6379>

mget 命令

描述:该命令用于返回多个key的值,当其中某一个KEY的值不存在,返回nil

127.0.0.1:6379> set age 10
OK
127.0.0.1:6379> set sex 1
OK
127.0.0.1:6379> mget name age sex
1) "aa"
2) "10"
3) "1"
127.0.0.1:6379>

decr 命令

描述:对key对应的数字做减1操作。如果key不存在,那么在操作之前,这个key对应的值会被置为0。如果key有一个错误类型的value或者是一个不能表示成数字的字符串,就返回错误

127.0.0.1:6379> decr age
(integer) 9
127.0.0.1:6379> get age
"9"
127.0.0.1:6379>

incr 命令

描述:对存储在指定key的数值执行原子的加1操作,如果指定的key不存在,那么在执行incr操作之前,会先将它的值设定为0。如果指定的key中存储的值不是字符串类型(fix:)或者存储的字符串类型不能表示为一个整数,那么执行这个命令时服务器会返回一个错误(eq:(error) ERR value is not an integer or out of range)。

127.0.0.1:6379> get age
"9"
127.0.0.1:6379> incr age
(integer) 10
127.0.0.1:6379>

更多string命令,参考这里:http://www.redis.cn/commands.html#string

2.2 string简单字符结构
2.2.1 SDS动态字符串

SDS(Simple Dynamic Strings, 简单动态字符串)是 Redis 的一种基本数据结构,主要是用于存储字符串和整数。

SDS数据结构实现(Redis3):

struct sdshdr {
    unsigned int len;
    unsigned int free;
    char buf[];
};

其中,buf 表示数据空间,用于存储字符串;len 表示 buf 中已占用的字节数,也即字符串长度;free 表示 buf 中剩余可用字节数。

好处

  • 用单独的变量 len 和 free,可以方便地获取字符串长度和剩余空间;

  • 内容存储在动态数组 buf 中,SDS 对上层暴露的指针指向 buf,而不是指向结构体 SDS。因此,上层可以像读取 C 字符串一样读取 SDS 的内容,兼容 C 语言处理字符串的各种函数,同时也能通过 buf 地址的偏移,方便地获取其他变量;

  • 读写字符串不依赖于 \0,保证二进制安全。

坏处

对于不同长度的字符串,没有必要使用 len 和 free 这 2 个 4 字节的变量?

4 字节的 len,可表示的字符串长度为 2^32,而在实际应用中,存放于 Redis 中的字符串往往没有这么长,因此,空间的使用上能否进一步压缩?

2.2.2 新的SDS结构

Redis 增加了一个 flags 字段来标识类型,用一个字节(8 位)来存储。

其中:前 3 位表示字符串的类型;剩余 5 位,可以用来存储长度小于 32 的短字符串。

struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; /* 前3位存储类型,后5位存储长度 */
    char buf[]; /* 动态数组,存放字符串 */
};

而对于长度大于 31 的字符串,仅仅靠 flags 的后 5 位来存储长度明显是不够的,需要用另外的变量来存储。sdshdr8、sdshdr16、sdshdr32、sdshdr64 的数据结构定义如下,其中 :

  • len 表示已使用的长度

  • alloc 表示总长度

  • buf 存储实际内容

  • flags 的前 3 位依然存储类型,后 5 位则预留。

struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* 已使用长度,1字节 */
    uint8_t alloc; /* 总长度,1字节 */
    unsigned char flags; /* 前3位存储类型,后5位预留 */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; /* 已使用长度,2字节 */
    uint16_t alloc; /* 总长度,2字节 */
    unsigned char flags; /* 前3位存储类型,后5位预留 */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len; /* 已使用长度,4字节 */
    uint32_t alloc; /* 总长度,4字节 */
    unsigned char flags; /* 前3位存储类型,后5位预留 */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
    uint64_t len; /* 已使用长度,8字节 */
    uint64_t alloc; /* 总长度,8字节 */
    unsigned char flags; /* 前3位存储类型,后5位预留 */
    char buf[];
};

Redis创建字符串流程

sds sdsnewlen(const void *init, size_t initlen) {
    void *sh;
    sds s;
    // 根据字符串长度计算相应类型
    char type = sdsReqType(initlen);
    // 如果创建的是""字符串,强转为SDS_TYPE_8
    if (type == SDS_TYPE_5 && initlen == 0) type = SDS_TYPE_8;
    // 根据类型计算头部所需长度(头部包含 len、alloc、flags)
    int hdrlen = sdsHdrSize(type);
    // 指向flags的指针
    unsigned char *fp;
    // 创建字符串,+1是因为 `\0` 结束符
    sh = s_malloc(hdrlen+initlen+1);
    if (sh == NULL) return NULL;
    if (init==SDS_NOINIT)
        init = NULL;
    else if (!init)
        memset(sh, 0, hdrlen+initlen+1);
    // s指向buf
    s = (char*)sh+hdrlen;
    // s减1得到flags
    fp = ((unsigned char*)s)-1;
    ...
    // 在s末尾添加\0结束符
    s[initlen] = '\0';
    // 返回指向buf的指针s
    return s;
}

创建 SDS 的大致流程是这样的:首先根据字符串长度计算得到 type,根据 type 计算头部所需长度,然后动态分配内存空间。

注意:

  1. 创建空字符串时,SDS_TYPE_5 被强制转换为 SDS_TYPE_8(原因是创建空字符串后,内容可能会频繁更新而引发扩容操作,故直接创建为 sdshdr8)

  2. 长度计算有 +1 操作,因为结束符 \0 会占用一个长度的空间。

  3. 返回的是指向 buf 的指针 s。

2.3 使用场景

1.主页高频访问信息显示限制,例如新浪、微博大V主页显示粉丝数与微博数量

2.限流限速

3.Session集中管理

4.验证码

3.与openresty结合做限流

Openresty介绍: OpenResty是一个基于Nginx与Lua的高性能web平台,由中国人章亦春发起, 其内部集成了大量精良的Lua库、第三方模块以及大多数的依赖项。用于方便搭 建能处理超高并发、扩展性极高的动态Web应用、web服务和动态网关

OpenResty简单理解成就相当于封装了NGINX,并且集成了LUA脚本,开发人 员只需要简单的使用其提供了模块就可以实现相关的逻辑,而不像之前,还需 要在NGINX中编写lua的脚本

3.1 Openresty安装:

1.安装包地址: https://github.com/openresty/openresty/archive/refs/tags/v1.19 .9.1.tar.gz

2.解压安装包: tar –zxvf openresty-1.19.9.1.tar.gz

3.安装: make && make install PREFIX=/www/server/openresty

local function wait()

        ngx.sleep(1)

end


3.2 使用
function limit_check()
local redis = require "resty.redis"
local redisConnect = redis:new()
local ip = "127.0.0.1"
local port = 6379
local password = "root"
local ok , err = redisConnect:connect(ip,port)
if not ok then
ngx.say( '{"code": 6379,"msg": "系统错误,请稍后
再试!"}',err )
ngx.exit(200)
return
end
3.3 缓存 
ocal uri = ngx.var.uri
local uriKey = "req:uri:"..uri
res , err = redisConnect:eval("local res , err = redis.call('incr',KEYS[1]) if res == 1 then 
local resexpire , err = redis.call('expire',KEYS[1],KEYS[2]) end return (res)",2,uriKey,1)
if res > 5 then
return false
else
return true
end
end
3.4 调用
restful = limit_check()
if not restful then
ngx.say( '{"code": 400,"msg": "request is error !"}' )
ngx.exit(200);
return
end

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Batch Normalization(批量归一化)和 Layer Normalization(层归一化)

Batch Normalization(批量归一化)和 Layer Normalization(层归一化)都是深度学习中用于改善网络训练过程的归一化技术。尽管它们的目标相似,即通过规范化中间层的激活值来加速训练过程并提高性能,但它们在细节上有所不同。 Batch Normalization (批量归一化) Batch Nor…

如何处理WordPress网站域名循环重定向

我在 HostEase 搭建了一个 WordPress 网站。在访问网站时出现了循环重定向的问题。经检查,发现是我在 .htaccess 文件中设置的重定向规则导致的。 重定向循环通常指的是一个网页或者URL地址在不断地进行重定向,最终形成一个循环,导致网页无法…

docker swarm 集群创建

1,目的: 通过docker swarm 工具将一台或者多台安装了docker的服务器组成一个完整的集群,该集群中的node节点可以通过Leader节点管理。在使用docker stack部署时,可以将容器自动分发到合适的节点上。 2,服务器准备&am…

C# 数组(Array)

C# 数组(Array) 初始化数组 声明一个数组不会在内存中初始化数组。当初始化数组变量时,您可以赋值给数组。 数组是一个引用类型,所以您需要使用 new 关键字来创建数组的实例。 例如: double[] b new double[10];…

VMware 替代专题 | 浅析 VMware 与 SmartX 超融合 I/O 路径差异及其影响

不同的超融合软件,其读写机制有一定的差异性,I/O 路径也不尽相同,这使得他们在 I/O 读写效率以及资源占用上都有不同的表现。有兴趣着手构建超融合基础架构的用户,可能会希望了解更多关于 I/O 路径的细节,从而在实施之…

二极管使用总结

1、整流的二极管、快恢复二极管、肖特基二极管做整流的差异。 标准整流二极管与快恢复二极管主要差异在恢复时间上。 • Standard rectifiers with a trr > 500 ns • Fast rectifiers with a 100 ns < trr < 500 ns • Ultrafast rectifiers with a trr < 100…

软件工程导论画图题汇总:期末+复试

文章目录 一、数据模型&#xff1a;实体联系图&#xff08;E-R图&#xff09;二、行为模型&#xff1a;状态转换图三、功能模型&#xff1a;数据流图四、数据字典五、系统流程图六、层次图七、HIPO图八、结构图九、程序流程图十、盒图十一、PAD图十二、判定表、判定树 一、数据…

【链表】Leetcode 19. 删除链表的倒数第 N 个结点【中等】

删除链表的倒数第 N 个结点 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 解题思路 1、使用快慢指针找到要删除节点的前一个节点。2、删…

30-如何使用命令给共享文件夹给人员授权?windows 的共享文件

&#xff08;1&#xff09;需求&#xff1a; 维护公司的DFS真的很烦&#xff0c;每天要给他们人员进行授权。用AD组可以&#xff0c;但是呢&#xff0c;用户想看到他们授权情况&#xff0c;没办法只能一个个授权吗&#xff1f;可以使用命令吗&#xff1f;可以的 &#xff08;2&…

【SpringMVC】知识汇总

SpringMVC 短暂回来&#xff0c;有时间就会更新博客 文章目录 SpringMVC前言一、第一章 SpingMVC概述二、SpringMVC常用注解1. Controller注解2. RequestMapping注解3. ResponseBody注解4. RequestParam5. EnableWebMvc注解介绍6. RequestBody注解介绍7. RequestBody与RequestP…

腾讯游戏全年收入1799亿,DNF手游有望突破100亿

易采游戏网3月21日消息&#xff1a;腾讯公司近期发布的2023财务年度报告显示&#xff0c;其营收和净利润双双显著上升&#xff0c;尤以游戏业务成绩不俗。管理团队承诺&#xff0c;将继续深耕既有游戏产品&#xff0c;同时强化新游研发力度&#xff0c;提升市场竞争力。引人瞩目…

SV-7035VP播放模块通用型播放终端SV-7035VP-SIP 网络通用型播放功放模块

SV-7035VP播放模块通用型播放终端SV-7035VP-SIP 网络通用型播放功放模块 产品介绍 SV-7035VP模块是一款SIP播放模块&#xff0c;具有10/100M以太网接口&#xff0c;其接收网络的音频数据&#xff0c;提供立体声的音频输出。 本SIP播放模块带有一个继电器端子和一个NET接口&a…

C++ —— 内存管理

目录 1. C内存分布 2. C 内存管理方式 2.1 new 和 delete 操作内置类型 2.2 new 和 delete 操作自定义类型 3. operator new与operator delete函数 4. new和delete的实现原理 5. malloc/free 和 new/delete 的区别 1. C内存分布 首先看一段代码&#xff1a; int globalV…

【xr806开发板使用】连接wifi例程实现

##开发环境 win10 WSL ##1、环境配置 参考&#xff1a;https://aijishu.com/a/1060000000287513 首先下载安装wsl 和ubuntu https://docs.microsoft.com/zh-cn/windows/wsl/install &#xff08;1&#xff09;安装repo&#xff1a; 创建repo安装目录&#xff1a; mkdir ~/…

【人工智能Ⅱ】实验2:VGG图像分类

实验2&#xff1a;VGG图像分类 一&#xff1a;实验目的与要求 1&#xff1a;掌握VGG网络的原理与结构。 2&#xff1a;学会利用VGG网络建立训练模型&#xff0c;并对模型进行评估。 3&#xff1a;学会使用VGG网络进行分类。 二&#xff1a;实验内容 1&#xff1a;用VGG网络…

PHP使用PHP_DIO读取串口数据

一、安装PHP_DIO扩展 1. 下载对应版本的dll扩展 根据你的操作系统类型选择对应的扩展名 PECL :: Package :: dio 下载地址&#xff1a; PECL :: Package :: dio 0.2.1 for Windows 以我使用的为例 我本地使用的是phpStudy PHP为7.4.3nts 64位的那就需要下载 注意你的是线程安全…

HTML5语法总结

文章目录 一.HTML基本框架二.标题标签三.段落标签四.换行与水平线标签五.文本格式化标签(加粗、倾斜、下划线、删除线)六.图像标签扩展&#xff1a;相对路径,绝对路径与在线网址 七.超链接标签八.音频标签九.视频标签十.列表标签十一.表格标签扩展&#xff1a;表格结构标签合并…

iStoreOS使用体验

iStoreOS是OpenWRT改版而来的易用的软路由系统 我们知道OpenWRT还是有一定的上手难度的&#xff0c;对于小白要玩好openwrt就需要学习openwrt的扩容 和一些插件的安装&#xff0c;问题的拍错&#xff0c;需要一定的linux系统基础 而iStoreOS这个系统对于小白非常的优化 首先他…

HCIP配置实验(路由配置)

要求&#xff1a; 1、R6为ISP&#xff0c;接口IP地址均为公有地址&#xff0c;该设备只能配置IP地址&#xff0c;之后不能冉对其进行任何配置; 2、R1-R5为局域网&#xff0c;私有IP地址192.168.1.0/24;请合理分配; 3、R1、R2、R4&#xff0c;各有两个环回IP地址; R5, R6各有一个…

[网鼎杯 2020 朱雀组]Think Java

[网鼎杯 2020 朱雀组]Think Java swagger [[swagger]] 首先下载源码&#xff0c;查看之后发现 查找swagger资料&#xff0c;或者扫描&#xff0c;得到&#xff1a;swagger-ui.html swagger-ui 提供了一个可视化的UI页面展示描述文件。接口的调用方、测试、项目经理等都可以…