从零到一掌握MongoDB与Redis:非结构化数据与缓存实战全攻略

175 阅读6分钟

简介

在现代企业级开发中,MongoDBRedis 是处理非结构化数据和高性能缓存的核心工具。MongoDB以其灵活的文档模型支持复杂数据结构的存储与查询,而Redis则通过内存数据库的特性实现了低延迟、高并发的数据访问。本文将从零开始,通过完整的开发步骤、详细的代码示例和企业级实践案例,带你全面掌握MongoDB与Redis的核心技术。无论你是初学者还是进阶开发者,都能通过本文构建扎实的NoSQL开发能力,并掌握在实际项目中高效整合框架的技巧。


MongoDB:非结构化数据的灵活存储

1. MongoDB基础概念与核心优势

MongoDB 是一种文档型数据库,以BSON(Binary JSON)格式存储数据,支持嵌套结构、动态模式和水平扩展。

1.1 核心特性

  • 动态模式:无需预定义表结构,字段可动态添加或删除。
  • 高可用性:通过副本集(Replica Set)实现自动故障转移。
  • 水平扩展:通过分片(Sharding)实现大规模数据的分布式存储。
  • 丰富的查询语言:支持聚合管道、全文搜索和地理空间查询。

1.2 适用场景

  • 内容管理系统:存储博客文章、用户评论等非结构化数据。
  • 实时分析:日志数据、用户行为记录的存储与分析。
  • 物联网(IoT):设备传感器数据的高吞吐量写入。

2. MongoDB从零开始实战开发

2.1 环境搭建与连接

  1. 安装MongoDB

    • 官网下载最新版本(当前为MongoDB 7.0)并安装。
    • 启动服务:mongod --dbpath=/data/db
  2. 连接MongoDB
    使用MongoDB Java驱动连接数据库:

    import com.mongodb.client.MongoClient;
    import com.mongodb.client.MongoClients;
    
    public class MongoDBExample {
        public static void main(String[] args) {
            String uri = "mongodb://localhost:27017";
            try (MongoClient client = MongoClients.create(uri)) {
                System.out.println("Connected to MongoDB!");
            }
        }
    }
    

2.2 核心数据操作

  1. 插入文档

    import com.mongodb.client.MongoCollection;
    import static com.mongodb.client.model.Filters.*;
    import static com.mongodb.client.model.Updates.*;
    
    public class InsertData {
        public static void main(String[] args) {
            try (MongoClient client = MongoClients.create("mongodb://localhost:27017")) {
                MongoCollection<Document> collection = client.getDatabase("mydb").getCollection("users");
                Document user = new Document("name", "Alice")
                                .append("email", "alice@example.com")
                                .append("roles", Arrays.asList("user", "admin"));
                collection.insertOne(user);
                System.out.println("Document inserted!");
            }
        }
    }
    
  2. 查询文档

    public class QueryData {
        public static void main(String[] args) {
            try (MongoClient client = MongoClients.create("mongodb://localhost:27017")) {
                MongoCollection<Document> collection = client.getDatabase("mydb").getCollection("users");
                FindIterable<Document> result = collection.find(eq("name", "Alice"));
                for (Document doc : result) {
                    System.out.println(doc.toJson());
                }
            }
        }
    }
    
  3. 更新文档

    public class UpdateData {
        public static void main(String[] args) {
            try (MongoClient client = MongoClients.create("mongodb://localhost:27017")) {
                MongoCollection<Document> collection = client.getDatabase("mydb").getCollection("users");
                collection.updateOne(eq("name", "Alice"), set("email", "alice_new@example.com"));
                System.out.println("Document updated!");
            }
        }
    }
    
  4. 删除文档

    public class DeleteData {
        public static void main(String[] args) {
            try (MongoClient client = MongoClients.create("mongodb://localhost:27017")) {
                MongoCollection<Document> collection = client.getDatabase("mydb").getCollection("users");
                collection.deleteOne(eq("name", "Alice"));
                System.out.println("Document deleted!");
            }
        }
    }
    

2.3 高级功能实战

  1. 聚合查询
    计算用户数量并按角色分组:

    public class Aggregation {
        public static void main(String[] args) {
            try (MongoClient client = MongoClients.create("mongodb://localhost:27017")) {
                MongoCollection<Document> collection = client.getDatabase("mydb").getCollection("users");
                AggregateIterable<Document> result = collection.aggregate(Arrays.asList(
                    new Document("$group", new Document("_id", "$roles").append("count", new Document("$sum", 1)))
                ));
                for (Document doc : result) {
                    System.out.println(doc.toJson());
                }
            }
        }
    }
    
  2. 索引优化
    创建复合索引提升查询性能:

    public class CreateIndex {
        public static void main(String[] args) {
            try (MongoClient client = MongoClients.create("mongodb://localhost:27017")) {
                MongoCollection<Document> collection = client.getDatabase("mydb").getCollection("users");
                collection.createIndex(new Document("name", 1).append("email", 1));
                System.out.println("Index created!");
            }
        }
    }
    

Redis:高性能缓存与分布式锁

1. Redis基础概念与核心优势

Redis 是一个内存键值数据库,支持多种数据类型(字符串、哈希、列表、集合等),并提供了持久化、主从复制和分布式锁等功能。

1.1 核心特性

  • 高性能:内存读写,单机吞吐量可达10万次/秒。
  • 数据结构丰富:支持字符串、哈希、列表、集合、有序集合等。
  • 分布式锁:通过 SETNX 命令实现分布式场景下的资源互斥访问。
  • 持久化:支持 RDB 快照和 AOF 日志两种持久化方式。

1.2 适用场景

  • 缓存:热点数据的高速访问(如用户会话、商品详情)。
  • 计数器:分布式系统中的全局计数(如点赞数、访问量)。
  • 分布式锁:协调多个节点对共享资源的访问。

2. Redis从零开始实战开发

2.1 环境搭建与连接

  1. 安装Redis

    • 官网下载最新版本(当前为Redis 7.2)并安装。
    • 启动服务:redis-server
  2. 连接Redis
    使用Jedis客户端连接Redis:

    import redis.clients.jedis.Jedis;
    
    public class RedisExample {
        public static void main(String[] args) {
            Jedis jedis = new Jedis("localhost", 6379);
            System.out.println("Connected to Redis!");
            jedis.close();
        }
    }
    

2.2 核心数据操作

  1. 字符串操作

    public class StringOperations {
        public static void main(String[] args) {
            Jedis jedis = new Jedis("localhost", 6379);
            // 存储
            jedis.set("username", "Bob");
            // 查询
            String name = jedis.get("username");
            System.out.println("Username: " + name);
            // 删除
            jedis.del("username");
            System.out.println("Key deleted!");
            jedis.close();
        }
    }
    
  2. 哈希操作

    public class HashOperations {
        public static void main(String[] args) {
            Jedis jedis = new Jedis("localhost", 6379);
            // 存储
            jedis.hset("user:1001", "name", "Charlie");
            jedis.hset("user:1001", "email", "charlie@example.com");
            // 查询
            Map<String, String> user = jedis.hgetAll("user:1001");
            System.out.println("User: " + user);
            // 删除
            jedis.hdel("user:1001", "email");
            System.out.println("Field deleted!");
            jedis.close();
        }
    }
    
  3. 列表操作

    public class ListOperations {
        public static void main(String[] args) {
            Jedis jedis = new Jedis("localhost", 6379);
            // 存储
            jedis.lpush("messages", "Hello", "World");
            // 查询
            List<String> messages = jedis.lrange("messages", 0, -1);
            System.out.println("Messages: " + messages);
            // 删除
            jedis.ltrim("messages", 0, 0);
            System.out.println("List trimmed!");
            jedis.close();
        }
    }
    
  4. 集合操作

    public class SetOperations {
        public static void main(String[] args) {
            Jedis jedis = new Jedis("localhost", 6379);
            // 存储
            jedis.sadd("tags", "java", "redis", "nosql");
            // 查询
            Set<String> tags = jedis.smembers("tags");
            System.out.println("Tags: " + tags);
            // 删除
            jedis.srem("tags", "nosql");
            System.out.println("Tag removed!");
            jedis.close();
        }
    }
    

2.3 高级功能实战

  1. 分布式锁实现
    使用 SETNX 实现分布式锁:

    public class DistributedLock {
        public static void main(String[] args) {
            Jedis jedis = new Jedis("localhost", 6379);
            String lockKey = "resource_lock";
            String clientId = UUID.randomUUID().toString();
            int expireTime = 10; // 锁过期时间(秒)
    
            // 尝试获取锁
            Long result = jedis.setnx(lockKey, clientId);
            if (result == 1) {
                System.out.println("Lock acquired!");
                // 执行业务逻辑
                try {
                    Thread.sleep(5000); // 模拟业务耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 释放锁
                    String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
                    jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(clientId));
                    System.out.println("Lock released!");
                }
            } else {
                System.out.println("Failed to acquire lock!");
            }
            jedis.close();
        }
    }
    
  2. 缓存穿透与雪崩解决方案

    • 缓存穿透:使用布隆过滤器拦截非法请求。
    • 缓存雪崩:随机设置缓存过期时间。
    • 缓存击穿:使用互斥锁重建缓存。

    示例代码(缓存雪崩解决方案):

    public class CacheSolution {
        public static void main(String[] args) {
            Jedis jedis = new Jedis("localhost", 6379);
            String key = "product:1001";
            String value = "Product 1001 data";
    
            // 设置随机过期时间
            int baseTTL = 3600; // 1小时
            int randomTTL = baseTTL + new Random().nextInt(600); // 0~10分钟随机
            jedis.setex(key, randomTTL, value);
            System.out.println("Cached with TTL: " + randomTTL + " seconds");
            jedis.close();
        }
    }
    

企业级开发中的MongoDB与Redis整合

1. Spring Boot整合MongoDB

1.1 添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

1.2 配置数据源

spring:
  data:
    mongodb:
      uri: mongodb://localhost:27017/mydb

1.3 创建实体类

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "users")
public class User {
    @Id
    private String id;
    private String name;
    private String email;
    private List<String> roles;

    // Getter和Setter方法
}

1.4 创建Repository接口

import org.springframework.data.mongodb.repository.MongoRepository;

public interface UserRepository extends MongoRepository<User, String> {
    List<User> findByName(String name);
}

1.5 Service层实现

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public void addUser(User user) {
        userRepository.save(user);
    }

    public List<User> getUsersByName(String name) {
        return userRepository.findByName(name);
    }
}

1.6 Controller层实现

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping
    public ResponseEntity<String> createUser(@RequestBody User user) {
        userService.addUser(user);
        return ResponseEntity.ok("User created successfully");
    }

    @GetMapping("/{name}")
    public ResponseEntity<List<User>> getUsersByName(@PathVariable String name) {
        return ResponseEntity.ok(userService.getUsersByName(name));
    }
}

2. Spring Boot整合Redis

2.1 添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.2 配置数据源

spring:
  redis:
    host: localhost
    port: 6379

2.3 创建缓存注解

import org.springframework.cache.annotation.Cacheable;

public class CacheUtil {
    @Cacheable(value = "products", key = "#id")
    public Product getProductById(String id) {
        // 模拟数据库查询
        return new Product(id, "Product " + id);
    }
}

2.4 Service层实现

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ProductService {
    @Autowired
    private CacheUtil cacheUtil;

    public Product getProduct(String id) {
        return cacheUtil.getProductById(id);
    }
}

2.5 Controller层实现

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/products")
public class ProductController {
    @Autowired
    private ProductService productService;

    @GetMapping("/{id}")
    public ResponseEntity<Product> getProduct(@PathVariable String id) {
        return ResponseEntity.ok(productService.getProduct(id));
    }
}

总结

MongoDB与Redis作为NoSQL领域的核心工具,分别在非结构化数据存储和高性能缓存方面展现了强大的能力。通过本文的详细讲解和代码示例,你已经掌握了从零开始搭建MongoDB与Redis项目的方法,并了解了如何在企业级开发中整合这些技术。无论是小型项目还是大型分布式系统,MongoDB与Redis都能显著提升开发效率和系统性能。现在,动手实践吧!