NoSQL 之 Redis 配置与优化
目录
一、 前置知识点
1. 关系数据库与非关系型数据库
(1)关系型数据库
(2)非关系型数据库
(3)非关系型数据库产生背景
(4)两者对比
2. Redis 基础
(1)Redis 简介
(2)Redis 安装部署
(3)配置参数
3. Redis 命令工具
(1)redis-cli 命令行工具
(2)redis-benchmark 测试工具
4. Redis 数据库常用命令
(1)命令
(2)多数据库常用命令
二、Redis 持久化
1. 持久化概述
2. 持久化分类
3. RDB 和 AOF 的区别
4. RDB 和 AOF 的优缺点
(1)RDB 优缺点
(2)AOF 优缺点
5. Redis 持久化配置
(1)RDB 持久化配置
(2)AOF 持久化配置
6. AOF 重写
为什么需要重写?
三、性能管理
1. 内存碎片率(Mem Fragmentation Ratio)
定义
监控方法
优化策略
2. 内存使用率(Memory Utilization)
定义
监控方法
优化策略
3. 回收 Key(Key Eviction & Deletion)
自动回收(淘汰策略)
手动回收(主动删除)
过期 Key 管理
一、 前置知识点
1. 关系数据库与非关系型数据库
(1)关系型数据库
-
定义:采用关系模型来组织数据的数据库,关系模型即二维表格模型,由二维表及其之间的联系组成数据组织。
-
特点:
-
结构化数据:数据以行和列的方式存储在表格中,具有严格的行列结构。
-
ACID 特性:支持事务,确保数据的原子性、一致性、隔离性和持久性。
-
强关系支持:通过主键、外键和索引实现表间关系。
-
标准化查询:支持标准 SQL 语句,可方便地在一个表以及多个表之间做复杂的数据查询。
-
-
典型例子:MySQL、PostgreSQL、Oracle、SQL Server 等。
-
适用场景:适用于需要处理复杂关系、保证数据一致性和完整性的场景,如银行系统、电子商务系统的订单处理等。
(2)非关系型数据库
-
定义:非关系型的、分布式的,且一般不保证遵循 ACID 原则的数据存储系统。
-
特点:
-
灵活数据模型:支持键值对、文档、列族或图等模型,适合非结构化或半结构化数据。
-
高性能和高扩展性:支持高并发读写,易于水平扩展。
-
无固定模式:数据结构可以动态变化,无需严格定义模式。
-
弱一致性:优先保证数据的可用性和分区容错性。
-
-
分类及典型例子:
-
键值对数据库:如 Redis、Amazon DynamoDB 等,以简单的键值对方式存储数据,读写速度快,常用于缓存、实时数据处理等场景。
-
文档型数据库:如 MongoDB、CouchDB 等,以文档形式存储数据,文档可以是 JSON、XML 等格式,适合存储半结构化数据,如用户生成的内容、日志等。
-
列族数据库:如 Cassandra 等,以列为单位存储数据,适合处理大规模的分布式数据,常用于大数据存储和分析场景。
-
图数据库:如 Neo4j 等,用于存储图形关系数据,能高效处理复杂的关系查询,适用于社交网络、知识图谱等领域。
-
-
适用场景:适用于高并发、分布式存储和灵活的非结构化数据场景,如大规模互联网应用、移动应用、物联网等领域。
(3)非关系型数据库产生背景
-
High performance ——对数据库高并发读写需求
-
Huge Storage —— 对海量数据高效存储与访问需求
-
High Scalability && High Availability —— 对数据库高可扩展性与高可
(4)两者对比
-
成本:非关系型数据库简单易部署,基本都是开源软件,相比关系型数据库价格便宜。
-
存储数据的格式:非关系型数据库的存储格式多样,如 key - value 形式、文档形式、图片形式等,可存储基础类型以及对象、集合等各种格式;关系型数据库只支持基础类型。
-
扩展性:关系型数据库因多表查询机制的限制导致扩展艰难;非关系型数据库基于键值对,数据之间没有耦合性,容易水平扩展。
-
数据一致性:关系型数据库强调数据的强一致性;非关系型数据库一般强调数据最终一致性。
-
事务处理:关系型数据库支持事务处理;非关系型数据库一般不提供对事务的处理。
2. Redis 基础
(1)Redis 简介
-
概述:
-
基于内存运行并支持持久化
-
采用key-value(键值对)的存储形式
-
-
优点:
-
具有极高的数据读写速度
-
支持丰富的数据类型
-
支持数据的持久化
-
原子性
-
支持数据备份
-
(2)Redis 安装部署
--关闭防火墙
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
--安装依赖环境
dnf -y install gcc zlib-devel
--解压redis包
tar zxvf redis
cd redis
--make安装(redis 源码包直接提供了Makefile)
make
make PREFIX=/usr/local/redis install
--软链接环境变量
ln -s /usr/local/redis/bin/* /usr/local/bin/
--初始化
cd /root/redis/utils
./install_server.sh (一直回车保持默认位置就OK)`Selecting default: 6379 默认端口
`Please select the redis config file name 文件位置`[/etc/redis/6379.conf]
`Please select the redis log file name 日志文件位置[/var/log/redis_6379.log]
"Please select the data directory for this instance [/var/lib/redis/6379] "
Please select the redis executable path [/usr/local/bin/redis-server] Please select the data directory for this instance [/var/lib/redis/6379]--查看启动是否(默认监听回环,无法远程)
netstat -anpt | grep redis
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 5953/redis-server 1
(3)配置参数
--改配置
vi /etc/redis/6379.conf
bind 127.0.0.1 192.168.10.101 //监听的主机地址
port 6379 //端口
daemonize yes //启用守护进程
pidfile /var/run/redis_6379.pid //指定PID文件
loglevel notice //日志级别
lofile /var/log/redis_6379.log //指定日志文件
--重启
/etc/init.d/redis_6379 restart--验证成功是否(多了一行)
netstat -anpt | grep redis
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 5968/redis-server 1
tcp 0 0 192.168.10.101:6379 0.0.0.0:* LISTEN 5968/redis-server 1
3. Redis 命令工具
(1)redis-cli 命令行工具
--登录redis(直接登无密码,存的是非结构化数据)
redis-cli //本地连
redis-cli -h 192.168.10.101 -p 6379 //远程连
(2)redis-benchmark 测试工具
4. Redis 数据库常用命令
(1)命令
采用 key-value(键值对)的数据存储形式
set : 存放数据,基础格式为 set key value
get : 获取数据,基础格式为 get key
keys 命令
keys 命令符合规则的键值列表,通常情况可以结合*、?等选项来使用
keys * //查看当前数据库中所有键
keys v* //查看当前数据库中以v开头的数据
keys v? //查看当前数据库中以v开头后面包含任意一位的数据
keys v?? //查看当前数据中以v开头v开头后面包含任意两位的数据
exists 命令
exists 命令可以判断键值是否存在
格式: exists 键名
例如:
exists teacher
(integer) 1 //表示 teacher 键是存在
(integer) 0 //表示 tea 键不存在
del 命令
del 命令可以删除当前数据库的指定 key
keys *
del 指定键
type 命令
type 命令可以获取key对应的value值类型
rename 命令
rename 命令是对已有key进行重命名
命令格式:rename 源key 目标key
例如:rename v22 v2容易出错若出现同名则会覆盖
可以使用exists先检查是否存在,或者renamenx
renamenx 命令
renamenx : 可检测目标(新名)是否存在,避免冲突覆盖,存在则不进行
dbsize 命令
dbsize 命令的作用是查看当前数据库中key 的数目
(2)多数据库常用命令
二、Redis 持久化
1. 持久化概述
运行在内存,容易丢,为防止,则要把数据写入磁盘空间中,即为持久化
2. 持久化分类
-
RDB方式:默认方式,创建快照的方式获取当时的所有信息数据
-
AOF(Append Only File)方式:仅仅在文件末尾追加信息,以日志方式记录数据变化
3. RDB 和 AOF 的区别
维度 | RDB (Redis Database) | AOF (Append Only File) |
---|---|---|
持久化方式 | 定时生成内存快照(二进制文件) | 记录每次写操作命令(文本文件) |
数据完整性 | 可能丢失最后一次快照后的数据 | 最多丢失 1 秒数据(取决于 fsync 策略) |
文件大小 | 小(压缩二进制) | 大(命令文本) |
恢复速度 | 快(直接加载二进制) | 慢(需重放所有命令) |
资源消耗 | 高(fork 子进程时 CPU/内存峰值) | 低(追加写入) |
核心差异:
RDB 是数据快照,AOF 是操作日志
RDB 适合灾难恢复,AOF 适合数据安全
4. RDB 和 AOF 的优缺点
(1)RDB 优缺点
优点 | 缺点 |
---|---|
① 恢复速度快(大数据集秒级加载) | ① 可能丢失分钟级数据 |
② 文件紧凑(适合备份/迁移) | ② fork 子进程时内存占用翻倍 |
③ 最大化 Redis 性能(持久化时不影响主进程) | ③ 数据完整性低 |
适用场景:
-
允许丢失部分数据的缓存服务
-
需要快速恢复的大数据集
(2)AOF 优缺点
优点 | 缺点 |
---|---|
① 数据安全(最多丢失 1 秒数据) | ① 文件体积大(需定期重写) |
② 实时持久化(每次写操作记录) | ② 恢复速度慢(需重放日志) |
③ 可读性好(文本格式查看历史操作) | ③ 写入性能略低于 RDB(fsync 开销) |
适用场景:
-
金融交易等对数据完整性要求高的场景
-
需要审计操作历史的系统
5. Redis 持久化配置
(1)RDB 持久化配置
# 触发规则:900秒内至少1次修改
save 900 1
# 触发规则:300秒内至少10次修改
save 300 10
# 触发规则:60秒内至少10000次修改
save 60 10000 # RDB文件名
dbfilename dump.rdb # 工作目录(持久化文件存储位置)
dir /var/lib/redis # 压缩存储
rdbcompression yes
(2)AOF 持久化配置
# 启用 AOF
appendonly yes # AOF 文件名
appendfilename "appendonly.aof" # 同步策略
appendfsync everysec # 推荐值:每秒同步(平衡性能与安全)
# appendfsync always # 每次写操作同步(最安全)
# appendfsync no # 由操作系统决定(性能最好) # AOF 重写触发条件
auto-aof-rewrite-percentage 100 # 文件增长超过100%时触发
auto-aof-rewrite-min-size 64mb # 最小重写文件大小
6. AOF 重写
为什么需要重写?
-
问题:AOF 文件持续增长(如执行 100 次
INCR counter
会记录 100 条命令) -
解决:重写生成精简的新 AOF 文件(如合并为
SET counter 100
)
关键步骤:
-
主进程 fork 子进程
-
子进程遍历内存数据生成新 AOF 文件
-
主进程将重写期间的增量命令写入缓冲区
-
子进程完成时,主进程追加缓冲区命令到新文件
-
原子替换旧 AOF 文件
重写配置优化
# 重写期间是否禁用 fsync(提升性能但可能丢失数据)
no-appendfsync-on-rewrite yes # 重写触发阈值(默认文件增长100%且大于64MB)
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
三、性能管理
redis-cli //登录数据库
info memory //查看redis 使用内存值
回收策略(文件中带lru的,相关配置)expire name 5 //设置过期时间,自动回收
1. 内存碎片率(Mem Fragmentation Ratio)
定义
- 公式:
mem_fragmentation_ratio = used_memory_rss / used_memory
used_memory_rss
:操作系统分配给 Redis 的物理内存(通过 malloc 分配)。used_memory
:Redis 逻辑使用的内存(存储数据实际占用)。
- 理想范围:1.0 ~ 1.5
- <1:内存不足,可能触发 swap(严重影响性能)。
- >1.5:碎片率过高,浪费内存。
监控方法
- 命令:
INFO MEMORY
查看mem_fragmentation_ratio
。 - 示例输出:
plaintext
# Memory used_memory:1073741824 # 逻辑内存(1GB) used_memory_rss:1572864000 # 物理内存(1.5GB) mem_fragmentation_ratio:1.46 # 碎片率
优化策略
- 自动碎片整理(4.0 + 版本)
- 开启配置:
conf
activedefrag yes # 开启主动碎片整理 active-defrag-threshold-lower 10 # 当碎片率>1.1时触发 active-defrag-threshold-upper 100 # 碎片率>2时加强整理
- 开启配置:
- 手动整理
- 执行
BGREWRITEAOF
(通过 AOF 重写触发内存重分配)。 - 重启实例(
SHUTDOWN RESTART
,彻底释放碎片,但需停服)。
- 执行
- 避免大 Key / 热 Key 集中删除:用
UNLINK key
异步删除,减少内存空洞。
2. 内存使用率(Memory Utilization)
定义
- 指标:
used_memory / maxmemory
(建议控制在 70%~80%,预留空间应对突发流量)。 - 风险点:
- 超过
maxmemory
且未配置淘汰策略时,会拒绝写请求。 - 内存使用率过高可能导致碎片率上升(分配器难以找到连续内存块)。
- 超过
监控方法
- 命令:
INFO MEMORY
查看used_memory
和max_memory
。 - 外部工具:Prometheus 监控
redis_memory_usage_percent
指标。
优化策略
- 配置淘汰策略(
maxmemory-policy
)- 生产首选:
allkeys-lru
(淘汰最近最少使用的 Key)。 - 带过期时间场景:
volatile-ttl
(优先淘汰 TTL 短的 Key)。
- 生产首选:
- 大 Key 治理
- 用
redis-cli --bigkeys
定位大 Key,拆解为小 Key(如分桶存储)。 - 示例:用户数据按 ID 哈希分桶,避免单个 Hash 键存储数万字段。
- 用
- 冷热数据分离
- 热数据(高频访问)保留在 Redis,冷数据迁移至数据库或分布式存储(如 HBase)。
3. 回收 Key(Key Eviction & Deletion)
自动回收(淘汰策略)
- 触发条件:内存达到
maxmemory
时,按策略删除 Key。 - 策略对比:
策略 适用场景 allkeys-lru
通用场景,无差别淘汰冷数据 volatile-lru
仅淘汰带过期时间的冷数据 allkeys-random
测试环境,随机淘汰 noeviction
禁止淘汰(写满后拒绝请求)
手动回收(主动删除)
- 普通删除:
DEL key
(阻塞主线程,避免删除大 Key)。 - 异步删除:
UNLINK key
(4.0 + 版本支持,后台线程处理删除,不阻塞)。 - 批量删除:
- 避免
KEYS *
遍历,用SCAN
分批获取 Key 再删除:bash
redis-cli --scan --pattern "prefix:*" | xargs -I {} redis-cli UNLINK {}
- 避免
过期 Key 管理
- 定期删除:Redis 每秒随机检查少量 Key,发现过期则删除。
- 惰性删除:访问 Key 时检查是否过期,过期则删除。
- 内存泄漏排查:
- 用
INFO STATS
查看expired_keys
(累计过期删除数),若长期为 0,可能未设置 TTL 或淘汰策略失效。 - 检查业务代码是否遗漏设置 Key 过期时间(
EXPIRE key seconds
)。
- 用
相关文章:
NoSQL 之 Redis 配置与优化
目录 一、 前置知识点 1. 关系数据库与非关系型数据库 (1)关系型数据库 (2)非关系型数据库 (3)非关系型数据库产生背景 (4)两者对比 2. Redis 基础 (1࿰…...

pikachu靶场通关笔记20 SQL注入03-搜索型注入(GET)
目录 一、SQL注入 二、搜索型注入 三、源码分析 1、渗透思路1 2、渗透思路2 四、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入百分号单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取…...

产品笔试专业名词梳理
目录 产品常识 四种常见广告形式 贴片广告 中插广告 信息流广告 横幅广告 BAT和TMD BAT TMD 付费渗透率 蓝海市场、红海市场 蓝海市场 红海市场 竞品研究 SWOT分析 SWOT分析的核心目的: SWOT分析的优点: SWOT分析的局限与注意事项&…...

【前端】es6相关,柯里化
0. 严格模式 严格模式的概念从ES6引进。通过严格模式,可以在函数内部选择进行较为严格的全局或局部的错误条件检测。 MDN中严格模式的描述 严格模式通过抛出错误来消除了一些原有静默错误严格模式修复了一些导致 JavaScript引擎难以执行优化的缺陷:有时…...

51单片机基础部分——矩阵按键检测
前言 上一节,我们说到了独立按键的检测以及使用,但是独立按键每一个按键都要对应一个IO口进行检测,在一些需要多按键的情况下,使用过多的独立按键会过多的占用单片机的IO资源,为了解决这个问题的出现,我们…...
onSaveInstanceState() 和 ViewModel 在数据保存能力差异
一、设计目标差异 维度onSaveInstanceState()ViewModel核心目的保存 瞬态 UI 状态(如用户输入、滚动位置),应对进程意外终止或配置变更。管理 业务逻辑相关数据,在配置变更时保留数据࿰…...

SpringBoot2.3.1集成Knife4j接口文档
首先要查看项目中pom文件里面有没有swagger和knife4j的依赖,如果有的话删除,加入以下依赖 <!-- swagger --><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter</…...
Java Fork/Join框架:三大核心组件深度解析
ForkJoinTask、ForkJoinWorkerThread 和 ForkJoinPool 构成了 Java 中 Fork/Join 框架的三个核心组件,它们之间形成了紧密的协作关系,共同提供了高效的并行计算能力。 三者关系概述 ForkJoinPool:执行环境,管理工作线程和任务调…...
【envoy】-1.安装与下载源码
1.安装 建议使用ubuntu2004,对glibc有要求。上个ti子更快。 wget -O- https://apt.envoyproxy.io/signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/envoy-keyring.gpg $ echo "deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/envo…...
B站的视频怎么下载下来——Best Video下载器
B站(哔哩哔哩)作为国内最受欢迎的视频平台之一,聚集了无数优质内容:动漫番剧、游戏实况、学习课程、纪录片、Vlog、鬼畜剪辑……总有那么些视频让人想反复观看、离线观看,甚至剪辑创作。 但你是否遇到过这样的烦恼&am…...
Mysql-定时删除数据库中的验证码
Moudle 1 使用调度器定时删除事件 数据库实现验证码自动删除的解决方案 -- 删除旧事件(如果存在) DROP EVENT IF EXISTS delete_expired_captchas;-- 创建新事件(每分钟执行一次) CREATE EVENT delete_expired_captchas ON SCHE…...

容器安全最佳实践:云原生环境下的零信任架构实施
📋 目录 引言:容器安全的重要性零信任架构基础理论云原生环境的安全挑战容器安全威胁模型分析零信任架构在容器环境中的实施关键技术组件与工具安全策略与最佳实践监控与响应机制案例研究与实施路径未来发展趋势 引言 随着容器技术和云原生架构的快速…...

[BIOS]VSCode zx-6000 编译问题
前提:Python 3.6.6及以上版本安装成功,Python 3.6.6路径加到了环境变量# DEVITS工具包准备好 问题:添加环境变量 1:出现环境变量错误,“py -3” is not installed or added to environment variables #先在C:\Windows里…...
MySQL连接报SSL错误
问题(cmd) C:\Users>mysql -h xx.xx.xx.xx -u root -p Enter password: ERROR 2026 (HY000): SSL connection error: error:0A000102:SSL routines::unsupported protocol 解决方案 1. 临时禁用 SSL 连接(不推荐生产环境使用࿰…...
在WPF项目中集成Python:Python.NET深度实战指南
随着Python在数据分析、机器学习、自动化等领域的广泛应用,越来越多的.NET开发者希望在WPF桌面应用中调用Python代码,实现两者优势互补。Python.NET(pythonnet)作为连接.NET与Python的桥梁,提供了强大的跨语言调用能力…...
Nuxt.js 布局系统详解:构建可复用页面框架
Nuxt.js 是一个基于 Vue.js 的强大框架,旨在简化开发流程并提高项目的可维护性。布局系统是 Nuxt.js 项目结构中的一个重要组成部分,它位于 layouts 目录下,帮助开发者实现页面间的统一风格和结构复用。 什么是 Nuxt.js 布局系统 Nuxt.js 提…...

CICD实战(二)-----gitlab的安装与配置
1、安装gitlab所需要的依赖包与工具 sudo yum install wget net-tools sudo yum install curl policycoreutils openssh-server openssh-clients postfix -y 2、配置清华源 vim /etc/yum.repo.d/gitlab-ce.repo[gitlab-ce] namegitlab-ce baseurlhttp://mirrors.tuna.tsin…...

[GitHub] 优秀开源项目
1 工具类 1.1 桌面猫咪互动 BongoCat...

Linux中su与sudo命令的区别:权限管理的关键差异解析
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析LLP (二)
低层协议(Low Level Protocol, LLP)详细解析 1. 低层协议(Low Level Protocol, LLP)核心特性 包基础 :基于字节的包协议,支持 短包 (32位)和 长包 (可变长度࿰…...

第4天:RNN应用(心脏病预测)
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 目标 具体实现 (一)环境 语言环境:Python 3.10 编 译 器: PyCharm 框 架: Pytorch (二)具体步骤…...
Python训练day40
知识点回顾: 彩色和灰度图片测试和训练的规范写法:封装在函数中 展平操作:除第一个维度batchsize外全部展平 dropout操作:训练阶段随机丢弃神经元,测试阶段eval模式关闭dropout 作业:仔细学习下测试和训练…...
湖北理元理律师事务所:债务优化中的民生保障实践
在债务纠纷数量年增21%(2023年最高人民法院数据)的背景下,法律服务机构如何平衡债务清偿与民生保障,成为行业重要课题。湖北理元理律师事务所通过“法律金融心理”三维服务模式,探索出一条可持续的债务化解路径。 一、…...
Vue-Todo-list 案例
一、前言 在前端开发中,Todo List(待办事项列表) 是一个非常经典的入门项目。它涵盖了组件化思想、数据绑定、事件处理、本地存储等核心知识点,非常适合用来练习 Vue 的基本用法。 本文将带你一步步实现一个功能完整的 Vue Todo…...

GIC700概述
GIC-700是用于处理外设与处理器核之间,以及核与核之间中断的通用中断控制器。GIC-700支持分布式微体系结构,其中包含用于提供灵活GIC实现的几个独立块。 GIC700支持GICv3、GICv3.1、GICv4.1架构。 该微体系结构规模可从单核到互联多chip环境࿰…...
动静态库的使用(Linux)
1.库 通俗来说,库就是现有的,可复用的代码,例如:在C/C语言编译时,就需要依赖相关的C/C标准库。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。通常我们可以在windows下看到一些后…...
Flutter、React Native 项目如何搞定 iOS 上架?从构建 IPA 到上传 App Store 的实战流程全解析
你可能会认为:用了跨平台框架(如 Flutter 或 React Native),开发效率提高了,发布流程也该更轻松才对。 但当我第一次要将一个 Flutter 项目发布到 App Store 时,现实给了我一巴掌: “没有 Mac&…...

统信桌面专业版如何使用python开发平台jupyter
哈喽呀,小伙伴们 最近有学员想了解在统信UOS桌面专业版系统上开发python程序,Anaconda作为python开发平台,anaconda提供图形开发平台,提供大量的开发插件和管理各种插件的平台,但是存在版权问题,有没有其他工具可以替代Anaconda呢…...
移除元素-JavaScript【算法学习day.04】
题目链接:27. 移除元素 - 力扣(LeetCode) 第一种思路 标签:拷贝覆盖 主要思路是遍历数组 nums,每次取出的数字变量为 num,同时设置一个下标 ans 在遍历过程中如果出现数字与需要移除的值不相同时ÿ…...
Android 相对布局管理器(RelativeLayout)
俩重要属性 android:gravity android:ignoreGravity Android 相对布局管理器:自由排列的魔法布局 想象一下,你是一个室内设计师,需要在一个房间里摆放家具。RelativeLayout(相对布局)就像是一个 "自由摆放"…...