0%

Redis 安装指南:从 macOS 到源码编译的完整步骤

Redis(Remote Dictionary Server)是一款高性能的开源键值对数据库,支持多种数据结构,广泛用于缓存、会话存储、消息队列等场景。本文详细介绍在 macOS 系统中通过包管理工具(Homebrew)和源码编译两种方式安装 Redis 的步骤,以及基本的服务管理操作。

macOS 下通过 Homebrew 安装(推荐)

Homebrew 是 macOS 下的包管理工具,通过它安装 Redis 简单高效,适合大多数用户。

1. 安装 Homebrew(若未安装)

打开终端,执行以下命令安装 Homebrew:

1
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

2. 安装 Redis

1
brew install redis
  • 该命令会自动下载并安装最新稳定版 Redis,同时配置环境变量,确保 redis-serverredis-cli 等命令可直接使用。

3. 配置 Redis(可选)

Redis 的配置文件 redis.conf 是核心配置入口,通过 Homebrew 安装的 Redis 配置文件路径可通过以下命令查看:

1
brew list redis  # 列出 Redis 安装的所有文件,其中包含 redis.conf 的路径(通常为 /usr/local/etc/redis.conf)

常用配置修改(使用文本编辑器打开 redis.conf):

  • 后台启动:默认 Redis 以前台模式运行,修改为后台启动:

阅读全文 »

Java IO 全解析:从基础流到序列化

Java 的 I/O(输入 / 输出)机制是程序与外部世界(文件、网络、控制台等)交互的核心,其设计围绕 “流(Stream)” 展开 —— 通过流的方式有序传输数据。本文将从 I/O 操作模式出发,详细解析 Java IO 体系的核心类、使用方法及最佳实践。

I/O 操作模式:五种基本类型

I/O 操作的本质是 “数据从设备到内核缓冲区,再从缓冲区到用户进程” 的过程。根据等待数据的方式不同,分为五种模式:

模式 核心特点 适用场景
阻塞 I/O 进程发起请求后阻塞,直到数据复制完成才唤醒。 简单场景(如单线程读取小文件)
非阻塞 I/O 进程不阻塞,定期轮询缓冲区状态,数据就绪后再复制(复制时可能阻塞)。 需快速响应的场景
I/O 复用 单进程监控多个 I/O 通道,数据就绪后通知进程处理(如 select/epoll)。 高并发网络编程(如 NIO)
信号驱动 I/O 进程不阻塞,数据就绪后内核通过信号通知,再处理复制。 实时性要求高的场景
异步 I/O 进程发起请求后完全不阻塞,内核自动完成全流程,完成后通知进程。 高性能 I/O 场景(如磁盘操作)

注:Java 传统 IO(java.io)主要基于阻塞 I/O,而 NIO(java.nio)引入了 I/O 复用机制。

Java IO 核心体系:流的分类

Java IO 包(java.io)的类按功能可分为四大类,核心是 “字节流” 和 “字符流”:

类型 核心接口 / 类 处理数据类型 典型用途
字节流 InputStream(输入)、OutputStream(输出) 二进制数据(字节) 图片、视频、压缩文件等
字符流 Reader(输入)、Writer(输出) 文本数据(字符) 文本文件、配置文件等
磁盘操作 File 文件 / 目录元数据 创建 / 删除文件、获取路径
网络操作(java.net SocketServerSocket 网络字节流 客户端 / 服务器通信

字节流:处理二进制数据

字节流以字节(8 位)为单位传输数据,是所有 I/O 操作的基础。核心基类为抽象类 InputStream(输入)和 OutputStream(输出)。

字节输入流(InputStream

InputStream

所有字节输入流均继承自 InputStream,用于从数据源读取字节。

核心子类及功能
数据源 核心功能 构造器参数示例
ByteArrayInputStream 内存字节数组 从内存缓冲区读取数据,无需磁盘 I/O。 new byte[] {1,2,3}
FileInputStream 本地文件 从文件读取字节,是文件输入的基础类。 "/data/test.bin"new File(...)
PipedInputStream 管道输出流 PipedOutputStream 配合,实现线程间通信。 new PipedOutputStream()
SequenceInputStream 多个输入流 合并多个流为一个,按顺序读取。 new InputStream[] {in1, in2}
装饰器子类(FilterInputStream

通过 “装饰器模式” 为基础流添加功能(如缓冲、数据类型转换):

阅读全文 »

Java NIO 详解:非阻塞 IO 与多路复用技术

Java NIO(Non-blocking IO,非阻塞 IO)是 JDK 1.4 引入的全新 IO 模型(JDK 1.7 补充 NIO.2),旨在解决传统 IO(BIO)在高并发场景下的性能瓶颈。NIO 基于 “通道(Channel)” 和 “缓冲区(Buffer)” 实现,通过 “多路复用(Selector)” 机制支持单线程处理多个 IO 操作,显著提升系统吞吐量。本文将全面解析 NIO 的核心原理、组件及实践。

NIO 核心概念与优势

阻塞 vs 非阻塞

  • 阻塞 IO(BIO):线程调用 read()write() 时会被挂起,直到操作完成才能继续执行。为处理多个客户端,需为每个连接创建独立线程,导致线程资源耗尽(上下文切换开销大)。
  • 非阻塞 IO(NIO):线程发起 IO 操作后无需阻塞,可继续处理其他任务;若操作未完成,仅返回 “未就绪” 状态,通过定期轮询或事件通知获取结果。单线程可管理多个 IO 通道,减少线程数量。

NIO 与传统 IO 的核心区别

特性 传统 IO(BIO) NIO
数据操作单位 字节流 / 字符流(Stream) 缓冲区(Buffer)
传输方向 单向(输入流 / 输出流分离) 双向(通道 Channel 可读写)
阻塞模式 阻塞(线程挂起) 非阻塞(线程可并发处理多任务)
并发处理 多线程(一个连接一个线程) 单线程 / 少线程(多路复用)
核心模型 流模型 通道 - 缓冲区模型
适用场景 低并发、简单 IO 操作 高并发、大流量场景(如网络服务器)

NIO 核心组件

NIO 的核心由三大组件构成:缓冲区(Buffer)通道(Channel)选择器(Selector),三者协同实现非阻塞 IO 操作。

缓冲区(Buffer):数据的容器

Buffer 是一块内存区域,用于存储 IO 操作的数据。所有 NIO 数据读写都必须通过 Buffer 完成(Channel 仅负责传输,不存储数据)。

(1)核心 Buffer 类型

NIO 为每种基本数据类型提供了对应的 Buffer 实现(除 boolean):

类型 描述 示例
ByteBuffer 字节缓冲区(最常用) 网络数据、文件二进制数据
CharBuffer 字符缓冲区 文本数据(自动处理编码)
IntBuffer/LongBuffer 基本类型缓冲区 结构化数据(如整数数组)
(2)Buffer 的核心变量

Buffer 通过三个核心变量控制数据读写,其关系为:0 ≤ mark ≤ position ≤ limit ≤ capacity

阅读全文 »

Java 函数式编程:核心思想与实践

函数式编程(Functional Programming)是一种以函数为核心的编程范式,强调不可变数据无副作用,从根本上解决了并发编程中的数据竞争问题。Java 8 引入 Lambda 表达式和函数式接口,正式支持函数式编程风格,大幅简化了代码并提升了可读性。本文将从核心思想出发,详解 Lambda 表达式、函数式接口、方法引用等关键特性。

函数式编程的核心思想

函数式编程的两大支柱:

  1. 不可变数据(Immutability)
    数据一旦创建就不可修改,任何操作都只会生成新数据,不会改变原始值。这避免了多线程环境下的数据竞争(多个线程同时修改同一数据)。
  2. 无副作用(No Side Effects)
    函数的执行不会影响外部状态(如全局变量、输入参数),相同输入始终产生相同输出。这种 “纯函数” 特性让代码更易测试和推理。

函数式接口:Lambda 表达式的载体

函数式接口是函数式编程的基础,指仅包含一个抽象方法的接口(可包含默认方法或静态方法)。Java 8 提供 @FunctionalInterface 注解用于标记此类接口,编译器会检查其是否符合规范。

1
2
3
4
5
6
7
8
9
10
11
12
@FunctionalInterface // 编译器验证:仅含一个抽象方法
public interface Calculator {
int compute(int a, int b); // 唯一抽象方法

default void printResult(int result) { // 默认方法(允许)
System.out.println("结果:" + result);
}

static void log() { // 静态方法(允许)
System.out.println("计算完成");
}
}

关键:Lambda 表达式本质是函数式接口的匿名实现,简化了接口实现的代码。

Lambda 表达式:简洁的函数实现

Lambda 表达式是函数式接口的简写形式,语法为:

阅读全文 »

Java 集合框架详解:从基础到实践

Java 集合框架(Java Collections Framework)是处理对象集合的核心工具,位于 java.util 包下,提供了一套统一的接口和实现类,用于存储、操作和管理一组对象。与数组相比,集合能自动调整大小,支持泛型(编译期类型检查),并提供了丰富的操作方法(如添加、删除、查找等)。本文将系统讲解集合框架的体系结构、核心实现类及常见问题解决方案。

集合框架体系概览

Java 集合框架主要分为两大体系:Collection(单列集合)Map(双列集合)

1. Collection 接口:独立元素的序列

Collection 是所有单列集合的根接口,存储一组独立元素,主要子接口包括:

  • List:有序、可重复(如动态数组);
  • Set:无序、不可重复(如数学中的 “集合”);
  • Queue:按特定规则排序(如先进先出的队列)。

2. Map 接口:键值对的映射

Map 存储 “键值对”(key-value),通过键(key)查找值(value),键不可重复,值可重复。主要实现类包括 HashMapTreeMapLinkedHashMap 等。

Collection 子接口及实现类

List:有序可重复的动态数组

List 以插入顺序保存元素,允许重复,支持通过索引访问(类似数组)。核心实现类:ArrayListLinkedListVector

(1)ArrayList:基于数组的动态列表
  • 底层结构:数组(Object[]),默认初始容量为 10,当元素满时自动扩容(默认扩容为原容量的 1.5 倍)。
  • 特性:
    • 优势:随机访问效率高(通过索引直接访问,时间复杂度 O(1));
    • 劣势:中间插入 / 删除元素效率低(需移动后续元素,时间复杂度 O(n));
    • 非线程安全(多线程环境需手动同步,或使用 CopyOnWriteArrayList)。
(2)LinkedList:基于双向链表的列表
  • 底层结构:双向链表(每个节点包含 prevnext 指针和元素值)。
  • 特性:
    • 优势:中间插入 / 删除元素效率高(只需修改指针,时间复杂度 O(1));
    • 劣势:随机访问效率低(需从表头 / 表尾遍历,时间复杂度 O(n));
    • 非线程安全,可作为栈、队列、双向队列使用(提供 addFirst()removeLast() 等方法)。
(3)Vector:线程安全的动态数组(已过时)
  • 底层结构:数组,与 ArrayList 类似,但所有方法均被 synchronized 修饰(线程安全)。
  • 问题:同步导致性能低下,推荐用 CopyOnWriteArrayList(并发包中的线程安全列表)替代。
List 实现类对比
特性 ArrayList LinkedList Vector(过时)
底层结构 数组 双向链表 数组
随机访问 快(O(1) 慢(O(n) 快(O(1)
插入 / 删除(中间) 慢(O(n) 快(O(1) 慢(O(n)+ 同步开销)
线程安全 是(低效)
适用场景 频繁查询,少量增删 频繁增删,少量查询 无(推荐 CopyOnWriteArrayList

Set:无序不可重复的集合

Set 不允许存储重复元素(通过 equals()hashCode() 判断重复),无序(元素存储位置与插入顺序无关)。核心实现类:HashSetLinkedHashSetTreeSet

阅读全文 »