【Redis】深入探索 Redis 的数据类型 —— 字符串 string

news2025/2/25 3:25:00

文章目录

  • 前言
  • 一、string 类型的操作命令
    • 设置和获取相关命令
      • 1. SET 和 GET
      • 2. MSET 和 MGET
      • 3. SETNX、SETEX、SETPX
    • 计数相关命令
      • 1. INCR 和 INCRBY
      • 2. DECR 和 DECRBY
      • 3. INCRBYFLOAT
    • 字符串操作相关命令
      • 1. APPEND
      • 2. GETRANGE
      • 3. SETRANGE
      • 4. STRLEN
    • string 相关命令总结
  • 二、string 类型的编码方式
  • 三、string 类型的使用场景
    • 1. 缓存(Cache)
    • 2. 计数(Counter)
    • 3. 共享会话(Session)
    • 4. 手机验证码


前言

string 字符串类型是 Redis 中最基础的数据类型,关于字符串类型需要注意以下几点:

  1. 在 Redis 中,所有的 key 的类型都是 string 类型的,并且其他几种数据类型也都是在字符串类型的基础上构建的,例如列表和集合的元素的类型都是字符串类型的。
  2. 在 Redis 中,字符串都是直接按照二进制的形式储存的,因此在使用 Redis 的时候,不需要像 MySQL 那样考虑编码问题(编码不匹配则会出现乱码)。所以 Redis 不会处理字符集的编码问题,客户端传入的命令中使用的是什么字符集编码,就存储什么字符集编码。
  3. Redis 中的 string 类型的值可以是字符串,JSON、XML格式的字符串,数字、整型、浮点数,甚至是二进制流数据,如图片、音频、视频等。不过一个 string 的最大值不能超过 512MB 。

一、string 类型的操作命令

设置和获取相关命令

1. SET 和 GET

a)SET:

SET 命令的作用是将 string 类型的 value 设置到 Redis 中。如果 key 在设置之前已经存在了,无论原来的数据类型是什么,都会覆盖原来的 value,并且 key 设置的 TTL 也会失效。

SET 的语法:

SET key value [expiration EX seconds|PX milliseconds] [NX|XX]

选项说明:

  • EX seconds:以秒为单位设置 key 的过期时间,相当于 EXPIRE;
  • PX milliseconds:以毫秒为单位设置 key 的过期时间,相当于 PEXPIRE;
  • NX:只有在 key 不存在的时候才进行设置,如果 key 之前已经存在了,则设置不会执行;
  • XX:只有在 key 存在的时候才进行设置,通过 key 之间不存在,则设置不会执行。

注意事项:

  1. []之内的选项只能选择一个,[]之间的选项则可以同时存在。即 EXPX 选项不能同时存在,而 NXXX 不能同时存在,因为它们之间是互斥关系。
  2. 带选项的 SET 命令可以被 SETEX、PSETEX、SETNX等命令替代。

返回值:

  • 如果设置成功,则返回 OK。
  • 如果由于 SET 指定了 NX 或者 XX 选项但条件不满足,则执行失败,返回 nil

使用示例:

EX 和 PX:

NX 和 XX

SETSET NXSET XX 执行流程:

b)GET

GET 命令的作用是获取 key 对应 的 value。如果 key 不存在,就返回 nil,如果 value 的数据类型不是 string,就会报错。

使用示例:

2. MSET 和 MGET

MSET 的作用是一次设置多个键值对;而 MGET 的作用是一次性获取多个 key 的 value,如果对应的 key 不存在或者对应的数据类型不是 string,返回 nil

使用案例:

a)MSET:

b)MGET:

注意事项:

在前面的文章提到过,Redis 是处理任务是单线程的,并且 Redis 的客户端和服务端之间是通过网络进行通信的,因此要设置或者获取多个key 的时候,建议同时进行操作,以减少网络请求的次数。

3. SETNX、SETEX、SETPX

a)SETNX 命令的作用是在如果 key 不存在则设置,否则就不设置,例如:


b)SETEX 命令的作用是在设置 key 的时候指定秒级的过期时间

语法:

SETEX key seconds value

例如:

c)PSETEX 命令的作用是在设置 key 的时候指定毫秒级的过期时间

语法:

SETEX key milliseconds value

例如:

计数相关命令

1. INCR 和 INCRBY

  1. INCR

INCR 命令的作用是将 key 对应的 string 表示的数字加一。

  • 如果 key 不存在,则视为 key 对应的 value 的值为 0,然后再加一;
  • 如果 key 对应的 value 不是一个整数或者其范围超出了 64 位有符号整型,则会报错;
  • 如果 INCR 执行成功,则返回加一后的值,否则返回相应错误信息。

使用示例:

  1. INCRBY

INCRBY 命令的作用是为 key 对应的 string 表示的整数加上一个指定的整数。

  • 如果 key 不存在,则视为 key 对应的 value 的值为 0,然后再加指定的数;
  • 如果 key 对应的 value 不是一个整数或者其范围超出了 64 位有符号整型,则会报错;
  • 如果 INCRBY 执行成功,则返回相加后的值,否则返回相应错误信息。

使用示例:

2. DECR 和 DECRBY

  1. DECR

DECR 命令的作用是将 key 对应的 string 表示的数字减一。

  • 如果 key 不存在,则视为 key 对应的 value 的值为 0,然后再减一;
  • 如果 key 对应的 value 不是一个整数或者其范围超出了 64 位有符号整型,则会报错;
  • 如果 DECR 执行成功,则返回减一后的值,否则返回相应错误信息。

使用示例:

  1. DECRBY

DECRBY 命令的作用是为 key 对应的 string 表示的整数减去一个指定的整数。

  • 如果 key 不存在,则视为 key 对应的 value 的值为 0,然后再减指定的数;
  • 如果 key 对应的 value 不是一个整数或者其范围超出了 64 位有符号整型,则会报错;
  • 如果 DECRBY 执行成功,则返回相减后的值,否则返回相应错误信息;
  • 如果 DECRBY 指定要减去的是一个负数,则表示加上这个数。

使用示例:

3. INCRBYFLOAT

INCRBYFLOAT命令的作用是将 key 对应的 string 表示的浮点数加上指定的数。

语法:

INCRBYFLOAT key increment 
  • 如果 key 不存在,则默认为0,然后在进行相加操作;
  • 如果 key 对应的 string 不是一个数,则会报错
  • 如果指定的数是负数,则表示减去这个数;
  • 如果 INCRBYFLOAT 执行成功,则返回运算结果,否则返回错误信息;
  • 允许采用科学计数法表示浮点数。

使用示例:

字符串操作相关命令

1. APPEND

APPEND命令的作用是中 key 对应的 string 后面追加字符串。

语法:

APPEND key value 
  • 如果 key 不存在,其效果等同于 SET 命令;
  • 如果 APPEND 执行成功,则返回最终字符串的长度。

2. GETRANGE

GETRANGE命令的作用是截取key 对应的 string 中的子串。

语法:

GETRANGE key start end
  • 截取的内容由指定的偏移量 start 和 end 确定,并且区间是左右闭合的;
  • 指定的偏移量可以是负数,当指定为负数时,表示的是倒数第几个字符,如 -1 表示倒数第一个字符;
  • 超出范围的偏移量会根据 string 的长度调整成正确的值。

使用示例:

3. SETRANGE

SETRANGE 命令的作用是覆盖从指定位置开始的 key 对应 string 中的一部分。

语法:

SETRANGE key offset value 
  • 替换的长度为替换字符串的长度,如果原字符串后面的长度不足,则将后面的全部替换;
  • 如果 key 不存在,并且指定替换的位置大于 0,则前面的位置由十六进制的 0 替换;
  • 替换成功则返回最终字符串的长度。

4. STRLEN

STRLEN 命令的作用是获取 key 对应的 string 的长度。

语法:

STRLEN key
  • 其返回值为字符串的长度;
  • 如果 key 不存在,则返回 0;
  • 如果 key 对应的 value 的类型不是 string 则会报错;
  • 字符串的长度有当前编码规则所决定。

使用示例:

string 相关命令总结

以下是 Redis 中与 string 类型相关的命令的总结,包括命令、作用和时间复杂度:

命令作用时间复杂度
SET设置key的值为指定字符串O(1)
GET获取key对应的字符串值O(1)
MSET批量设置多个键值对O(N)(N为键值对数量)
MGET批量获取多个key的值O(N)(N为键的数量)
SETNX仅当key不存在时设置值O(1)
SETEX设置key的值和过期时间(秒)O(1)
PSETEX设置key的值和过期时间(毫秒)O(1)
INCR将key对应的数字值加一O(1)
INCRBY将key对应的数字值加上指定整数O(1)
DECR将key对应的数字值减一O(1)
DECRBY将key对应的数字值减去指定整数O(1)
INCRBYFLOAT将key对应的浮点数值加上指定浮点数O(1)
APPEND在key对应的字符串值后追加字符串O(1)
GETRANGE获取key对应的字符串的子串O(N)(N为子串长度)
SETRANGE覆盖key对应字符串的部分内容O(N)(N为替换字符串长度)
STRLEN获取key对应的字符串的长度O(1)

二、string 类型的编码方式

在Redis中,字符串(string)类型的值可以使用多种不同的编码方式存储,具体的编码方式是根据数据的内容和大小来动态选择的,以最大程度地节省内存和提高性能。以下是Redis中字符串类型的常见编码方式:

  1. RAW(简单动态字符串):这是最常见的字符串编码方式。它用于存储较短的字符串,长度不超过字符串编码结构的限制。这种编码方式不会对字符串进行压缩,因此在存储较小的字符串时效率高。

  2. INT(整数编码):当一个字符串可以被解释为整数时,Redis会将其编码为整数,以节省内存。整数编码分为以下几种子编码方式:

    • int16_t:16位整数编码,存储16位以内的整数。
    • int32_t:32位整数编码,存储32位以内的整数。
    • int64_t:64位整数编码,存储64位以内的整数。
  3. EMBSTR(嵌套字符串编码):用于存储较短的字符串,但与RAW不同的是,EMBSTR的编码方式将字符串长度也一并存储在编码结构中,以节省内存。

  4. RAW和EMBSTR共享编码:在某些情况下,Redis会使用一种特殊的编码方式,该方式可以共享RAW和EMBSTR编码方式的优点。这意味着它既可以存储较短的字符串,又可以高效地存储较大的字符串。

  5. SDS(简单动态字符串):SDS是一种用于表示字符串的数据结构,它具有动态大小,可以在不需要重新分配内存的情况下进行扩展。这种编码方式用于存储较大的字符串,以节省内存和提高性能。

需要注意的是,Redis会根据字符串的内容和大小动态选择适当的编码方式,因此开发者无需手动指定编码方式。这种动态编码方式使得Redis能够在不同情况下充分利用内存,提高效率。

可以使用Redis的OBJECT ENCODING命令来查看特定键的编码方式,例如:

OBJECT ENCODING mykey

这将返回键mykey的编码方式。

例如:

三、string 类型的使用场景

1. 缓存(Cache)

由于 Redis 速度快的特点,因此常用于缓存功能。比较典型的缓存使用场景就是,Redis 作为缓冲层,MySQL 作为存储层,绝大部分请
求的数据都是从 Redis 中获取。由于 Redis 具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用。

Redis + MySQL 组成的缓存存储架构:

下面通过伪代码模拟了上图的业务数据的访问过程:

1)假设业务是根据用户的 uid 获取用户信息

UserInfo getUserInfo(long uid) {
	...
}

2)首先从 Redis 获取用户信息,我们假设用户信息保存在 “user:info:” 对应的键中

// 根据 uid 得到 Redis 的键
String key = "user:info:" + uid;
// 尝试从 Redis 中获取对应的值
String value = Redis 执⾏命令:get key;
// 如果缓存命中(hit)
if (value != null) {
	// 假设用户信息按照 JSON 格式存储
	UserInfo userInfo = JSON 反序列化(value);
	return userInfo;
}

3)如果没有从 Redis 中得到用户信息或者缓存未命中(miss),则进一步从 MySQL 中获取对应的信息,随后写入缓存并返回

// 如果缓存未命中(miss)
if (value == null) {
	// 从数据库中,根据 uid 获取⽤⼾信息
	UserInfo userInfo = MySQL 执⾏ SQL:select * from user_info where uid = <uid>
	// 如果表中没有 uid 对应的⽤⼾信息
	if (userInfo == null) {
		// 响应 404
		return null;
	}

	// 将用户信息序列化成 JSON 格式
	String value = JSON 序列化(userInfo);
	
	// 写⼊缓存,为了防⽌数据腐烂(rot),设置过期时间为 1 ⼩时(3600 秒)
	Redis 执⾏命令:set key value ex 3600

	// 返回用户信息
	return userInfo;
}

通过增加缓存功能,在理想情况下,每个用户信息,一个小时期间只会有一次 MySQL 查询存在,极大地提升了查询效率,同时也降低了MySQL 的访问数。

PS: Redis 键名的设计原则和示例

  1. 业务名前缀:将键名以业务名开头,以便将不同业务或项目的键隔离开来。这有助于确保不同的应用程序或团队之间的键不会发生冲突。
    示例:
    user_info:6379
    order_info:1234
  2. 对象名:指定键名中的对象名,以描述存储的内容是什么。这有助于清晰地了解键存储的数据类型或业务对象。
    示例:
    user_profile:6379
    product_catalog:5678
  3. 唯一标识:如果需要,可以在键名中包含唯一标识符,以便更具体地标识存储的数据。这有助于将数据细分为不同的实体。
    示例:
    user:12345:profile
    product:7890:details
  4. 属性:如果数据具有多个属性,可以在键名中包含属性名称,以进一步细化键的用途。
    示例:
    user:12345:profile:name
    product:7890:details:price
  5. 键名缩写:如果键名变得过长,可以使用缩写来减少键名的长度,但要确保缩写对团队内部是清晰可理解的。
    示例:
    u:12345:pr:n(缩写版)

通过使用这种键名命名空间约定,可以使Redis键更有组织,易于维护和管理。它还可以帮助避免键名冲突,特别是在多个应用程序或团队使用同一个Redis实例的情况下。但请注意,键名过长可能会导致性能下降,所以需要权衡键名的可读性和性能需求。

2. 计数(Counter)

计数(Counter)功能是Redis中常见且有用的功能之一,它可以用来快速记录和查询某个对象的计数值。这种功能在许多应用中都非常有用,例如网站的访问计数、点赞数、评论数、播放次数等。

例如记录视频播放次数:

伪代码:

// 在 Redis 中统计某视频的播放次数
long incrVideoCounter(long vid) {
	key = "video:" + vid;
	long count = Redis 执⾏命令:incr key
	return counter;
}

然而,在实际开发一个成熟、稳定的计数系统时,会面临许多挑战和复杂性。以下是一些可能需要应对的挑战和考虑因素:

  1. 防作弊:确保计数系统不容易被恶意操纵是至关重要的。常见的防作弊措施包括限制每个用户或IP地址的计数速率,使用验证码或令牌来验证用户行为等。
  2. 按不同维度计数:有时需要按照不同的维度进行计数,例如按时间、地理位置、用户类型等。为了实现这种灵活性,需要设计适应性强的计数系统架构。
  3. 避免单点问题:单点故障可能会导致计数系统的不可用性。为了确保高可用性,可以考虑使用Redis的主从复制或集群模式,或者使用其他分布式计数系统。
  4. 数据持久化:Redis默认将数据存储在内存中,但为了持久化数据,可以将数据定期快照到磁盘或使用持久化选项,如AOF(Append-Only File)。
  5. 性能优化:处理大量计数请求可能会对性能造成压力。需要优化Redis配置、考虑使用缓存层、分布式计数系统或负载均衡策略,以应对高负载情况。
  6. 并发控制:并发操作可能导致计数不一致。要确保计数的原子性,可以使用Redis的事务或乐观锁等技术。
  7. 监控和日志:建立监控和日志系统,以实时追踪计数系统的性能和运行状况,以及检测潜在的问题。
  8. 容量规划:考虑计数系统的容量规划,包括数据存储需求、内存和硬盘空间等,以支持未来的增长。
  9. 数据清理:定期清理不再需要的计数数据,以防止数据膨胀和内存占用过多。

总之,开发一个真实的计数系统是一个复杂的任务,需要考虑众多因素。选择合适的技术栈、设计良好的架构、实施安全性和防作弊措施、确保高可用性以及建立监控和维护策略都是成功实现计数系统的重要步骤。这些挑战需要仔细的规划和实施,以满足特定项目的需求。

3. 共享会话(Session)

在一个分布式 Web 服务中,用户的会话信息通常存储在各自的服务器上,这包括用户的登录状态和其他会话相关数据。然而,由于负载均衡的需要,用户的请求会被分发到不同的服务器上,而不同服务器上的会话数据并不共享。

这就导致了一个问题:如果用户的请求被均衡到不同的服务器上,用户在刷新页面或发送下一个请求时可能会发现自己需要重新登录,这种体验对用户来说是不可接受的

例如下图所示的 Session 分散储存:

为了解决这个问题,可以使用Redis将用户的 Session 信息进行集中管理。在这种模式下,只要确保 Redis 是高可用和可扩展的,不论用户被均衡到哪台 Web 服务器上,都可以集中从 Redis 中查询、更新Session信息。

4. 手机验证码

为了增强用户登录的安全性,许多应用会采取以下步骤:

  • 在每次用户尝试登录时,要求用户输入其手机号,并通过向其手机发送验证码来进行二次验证。这个验证码需要用户再次输入,以确保登录请求来自于用户本人。
  • 此外,为了防止滥用短信接口和提高安全性,通常会限制用户每分钟获取验证码的频率,例如,在一分钟内,同一手机号最多只能获取验证码5次。

这种流程可以有效地降低恶意登录和滥发验证码的风险,同时保障用户的账户安全。

短信验证码:

此功能可以用以下伪代码说明基本实现思路:

String 发送验证码(phoneNumber) {
    key = "shortMsg:limit:" + phoneNumber;
    // 设置过期时间为 1 分钟(60 秒)
    // 使用 NX,只在不存在 key 时才能设置成功
    bool r = Redis 执行命令:set key 1 ex 60 nx
    if (r == false) {
        // 说明之前设置过该手机号的验证码了
        long c = Redis 执行命令:incr key
        if (c > 5) {
            // 说明超过了一分钟 5 次的限制了
            // 限制发送
            return null;
        }
    }
    // 说明要么之前没有设置过手机号的验证码;要么次数没有超过 5 次
    String validationCode = 生成随机的 6 位数的验证码();
    validationKey = "validation:" + phoneNumber;
    // 验证码 5 分钟(300 秒)内有效
    Redis 执行命令:set validationKey validationCode ex 300;
    // 返回验证码,随后通过手机短信发送给用户
    return validationCode;
}

// 验证用户输入的验证码是否正确
bool 验证验证码(phoneNumber, validationCode) {
    validationKey = "validation:" + phoneNumber;
    String value = Redis 执行命令:get validationKey;
    if (value == null) {
        // 说明没有这个手机号的验证码记录,验证失败
        return false;
    }
    if (value == validationCode) {
        return true;
    } else {
        return false;
    }
}

以上介绍了使用 Redis 的字符串数据类型在缓存、计数、会话管理和手机验证码等场景中的应用。然而,Redis 的字符串类型的适用场景远不止这些,开发人员可以根据字符串类型的特点以及提供的命令,充分发挥自己的创造力和想象力,将其应用到各种业务场景中。

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

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

相关文章

解决VSCode调试或者发布运行时闪退问题

解决方案&#xff1a;此方案不一定适合所有类型的闪退&#xff0c;但可以尝试一下。 步骤1&#xff1a;依次选择&#xff1a;文件→首选项→设置 步骤2&#xff1a;搜索 terminal.integrated.Default →找到Terminal > Integrated Default Profile: Windows选项→下拉框的…

Git 客户端基本使用及新手常见问题

Git作为一个版本管理工具&#xff0c;在企业中的应用越来越普遍。作为一个测试工程师&#xff0c;不可避免会需要接触到Git的相关操作&#xff0c;以下整理Git客户端的常见操作&#xff0c;以及应用中新手常碰到的一些问题。 1、环境安装及配置 Git下载地址&#xff1a;https…

YOLOV7改进-添加基于注意力机制的目标检测头(DYHEAD)

DYHEAD 复制到这&#xff1a; 1、models下新建文件 2、yolo.py中import一下 3、改IDetect这里 4、论文中说6的效果最好&#xff0c;但参数量不少&#xff0c;做一下工作量 5、在进入IDetect之前&#xff0c;会对RepConv做卷积 5、因为DYHEAD需要三个层输入的特征层一致&am…

【DS思想+堆贪心】CF595div3 D2

Problem - D2 - Codeforces 题意&#xff1a; 思路&#xff1a; 大家都说这是典&#xff0c;但是我不懂怎么个典法&#xff0c;可能堆贪心都是这样做的吗&#xff0c;不懂 首先肯定要贪心&#xff0c;对于一个坏点&#xff0c;优先删除覆盖别的点多的 考虑nlogn做法&#x…

9.177777777

Tomcat配置ssl 部署tomcat服务&#xff0c;项目做到用https访问&#xff0c;使用nginx去做&#xff0c;访问任意一个子网站&#xff0c;都是https 或者 医美项目需要 上传jdk 456 tomcat war包 [nginx-stable] namenginx stable repo baseurlhttp://nginx.org/packages/…

关于Greenplum Platform Extension Framework(PXF)

本文翻译自 https://docs.vmware.com/en/VMware-Greenplum-Platform-Extension-Framework/6.6/greenplum-platform-extension-framework/overview_pxf.html 随着数据存储和云服务的爆炸式增长&#xff0c;数据现在以各种格式驻留在许多不同的系统中。通常&#xff0c;数据根据…

Maven学习记录

一、Maven是什么 简单来说Maven是一个标准化的java管理和构建工具&#xff0c;它提供了一系列规范&#xff0c;包括项目结构&#xff0c;构建流程&#xff08;编译&#xff0c;测试&#xff0c;打包&#xff0c;发布……&#xff09;&#xff0c;依赖管理等。 标准化就是定下…

科技项目验收怎么做?不通过怎么办?

CMA、CNAS 一、科技项目验收是什么&#xff1f; 科技项目验收测试是依据GB/T 17544《信息技术 软件包 质量要求和测试》、GB/T 16260《软件工程 产品质量》&#xff0c;对申报国家、省、市科技项目、或企业申请中小企业创新基金、科技项目验收、科技成果鉴定等提供软件产品第…

机器学习——自然语言处理(NLP)一

机器学习——自然语言处理&#xff08;NLP&#xff09;一 文章目录 前言一、TF-IDF算法1.1. 原理1.2. 算法步骤&#xff1a;1.2.1. 文本预处理1.2.2. 构建词袋模型1.2.3. 计算TF-IDF值1.2.4. 特征选择 1.3. 代码实现1.3.1. TF-IDF1.3.2 计数器向量化文本1.3.3. 两者的区别1.3.4…

Android MeidiaCodec之OMXPluginBase与QComOMXPlugin实现本质(四十)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…

帧动画实现

背景&#xff1a; pag实现痛点 文档&#xff1a;libpag参考文档 1.打包依赖的类型缺失问题 2.pagview初始化文件过大,影响小程序打包 3.兼容性较差关键帧动画实现痛点: 当关键帧变化过多的时候&#xff0c;无法准确分辨出需要写出多少个关键帧&#xff0c;以及各个关键帧的具…

umi 中的路由切换动画如何实现

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 umi路由切换动画步骤 1、查看node版本2、搭建脚手架①.找个地方建一个空目录2.搭建umi脚手架3.正式配置路由动画1.1 在src文件目录下创建一个 layouts文件夹&#xff0c;在文…

【疑难杂症】用户无法使用sudo提权

目录 用户无法使用sudo提权 用户无法使用sudo提权 第一步&#xff1a;切换成超级用户。 su 第二步&#xff1a;打开/etc/sudoers文件。 vim /etc/sudoers 第三步&#xff1a;将用户添加到文件力。 这样就得到解决了......

404 not found nginx(dist打包后,刷新和跳转都是404 not found nginx的问题) 解决方案(打包发布在服务器)

当我们执行了yarn run build之后&#xff0c;生成dist文件 我们将代码放入nginx-1.24.0下面的html中 然后我们就配置conf文件下的nginx.conf 配置方面不介绍了&#xff0c;主要问题是因为没有加这句话 问题分析 index index.htm index.html; index 就是根目录&#xff0c;也就…

Android获取 H264视频流中的SPS和PPS

代码其实很简单&#xff0c;主要是要知道H264帧数据结构。分析H264码流结构的文章一大把&#xff0c;自己网上搜索一下就知道了。 背景&#xff1a; h264aac封装mp4格式的时候&#xff0c;需要获取视频流的sps,pps。 封装mp4文件格式的大体方案 使用 MediaExtractor 和 Medi…

Python实现机器学习(上)— 基础知识介绍及环境部署

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。本门课程将介绍人工智能相关概念&#xff0c;重点讲解机器学习原理机器基本算法&#xff08;监督学习及非监督学习&#xff09;。使用python&#xff0c;结合sklearn、jupyter-notebook进行编程&#xff0c;介绍iris、匹马…

【Mysql系列】(二)日志系统:一条更新语句是如何执行的

有的时候博客内容会有变动&#xff0c;首发博客是最新的&#xff0c;其他博客地址可能会未同步,认准https://blog.zysicyj.top 这篇文章是从Github ReadMe拷贝的&#xff0c;内容实践下载是没问题的&#xff0c;能够正常发送短信&#xff0c;而且也不需要服务器&#xff0c;本地…

语言基础篇14——Python源文件组织结构,模块与包、命名空间与作用域的奥秘

源文件组织结构 模块与包 模块&#xff0c;module 一个文件&#xff0c;包含Python源码&#xff0c;以.py为后缀 包&#xff0c;package 结构化模块&#xff0c;一个文件夹&#xff0c;包含__init__.py文件、若干.py文件和若干文件夹 module对象 模块和包被导入后为modu…

保姆级-微信小程序开发教程

一&#xff0c;注册微信小程序 如果你还没有微信公众平台的账号&#xff0c;请先进入微信公众平台首页&#xff0c;点击 “立即注册” 按钮进行注册。注册的账号类型可以是订阅号、服务号、小程序以及企业微信&#xff0c;我们选择 “小程序” 即可。 接着填写账号信息&#x…

洗衣洗鞋小程序干洗店洗衣店上门取衣门店管理系统开发定制

校园洗衣洗鞋软件是一款非常优质的校园洗护服务软件&#xff0c;软件功能非常强大&#xff0c;学生们可以通过软件预约洗衣服务&#xff0c;支持上门取送&#xff0c;还能够浏览洗衣产品商城&#xff0c;操作非常便捷&#xff0c;感兴趣的朋友快来体验吧&#xff01; 后台管理…