Memcached介绍与使用

news2024/9/21 22:15:33

引言

本文是笔者对Memcached这个高性能分布式缓存组件的实践案例,Memcached是一种高性能的分布式内存对象缓存系统,用于减轻数据库负载,加速动态Web应用,提高网站访问速度。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高应用程序的性能。

本文涉及到的源码gitee地址:源码地址

一、Memcached介绍

主要特点

  • 键值存储:Memcached 使用键值对存储模型,其中键是一个字符串,值可以是任何数据,通常用于存储数据库查询结果、网页或对象的序列化形式。

  • 内存存储:数据存储在内存中,这比从硬盘读取数据要快得多。但是,这也意味着数据是非持久化的,如果 Memcached 或操作系统重启,数据会丢失。

  • LRU 缓存替换策略:当内存不足时,Memcached 使用最近最少使用(Least Recently Used,LRU)算法来自动删除不常用的缓存项,以便为新数据腾出空间。

  • 简单协议:Memcached 使用一个简单的文本行协议,这使得它易于实现和集成。

  • 跨平台:Memcached 可以在多种操作系统上运行,包括 Linux 和 BSD 等。

  • 高可用性和可扩展性:Memcached 支持分布式部署,可以在多个服务器上运行,以增加容量和冗余。

  • 轻量级和快速:由于其简单的架构和内存存储特性,Memcached 能够提供非常低的延迟和高吞吐量。


适用场景

  • 缓存数据库查询结果。

  • 存储用户会话信息。

  • 缓存计算结果或频繁访问的内容。

  • 存储用户个性化数据。


不适用场景

  • 缓存的数据需要持久化

  • key 的长度大于 250 字符

  • 变化频繁且需要存入数据库

  • 过大的数据不适宜放在 Memcached 中


与 Redis 比较相同点

  1. 都是基于内存的数据库系统,最大存储量是根据机器内存大小而定

  2. 都有不同的过期策略,分布式数据的备份可以设置一主多从,也可以一主一从(Master-Slave)

  3. 都支持 key-value 数据缓存


与 Redis 比较不同点

  1. 数据持久化支持:Redis 虽然是基于内存的存储系统,但是它本身是支持内存数据的持久化的,而且提供两种主要的持久化策略:RDB 快照和 AOF 日志。而 Memcached 是不支持数据持久化操作的。

  2. 灾难恢复:Memcached 挂掉后,数据不可恢复。 Redis 数据丢失后可以通过 AOF 恢复

  3. IO 方面:Redis 使用的单线程 IO 复用网络模型, 而 Memcached 多线程非阻塞 IO 复用模型

  4. 数据支持类型:Redis 支持 key-value 数据类型,还有 list、set、zset、hash 等数据结构,而 Memcached 只支持 key-value 数据

  5. Value 值大小不同:Redis 最大可以达到 512mb;Memcached 只有 1mb。

  6. 数据一致性:Memcached 提供了 CAS 命令,可以保证多个并发访问操作同一份数据的一致性问题。Redis 没有提供 CAS 命令,并不能保证这点,不过 Redis 提供了事务的功能,可以保证一串命令的原子性,中间不会被任何操作打断。


二、java客户端介绍

主要有三种不同的 Java 客户端来支持 Memcached, 分别为 Memcached-java-clientSpymemcachedXMemcached

Memcached-java-client 客户端

  • Memcached-java-client 客户端推出较早,应用最广泛,阻塞式 IO,稳定性高,高并发下性能低。较早推出的 Memcached JAVA 客户端 API,应用广泛,运行比较稳定,使用阻塞 IO,不支持 CAS 操作,已停止更新。

Spymemcached 客户端

  • Spymemcached 客户端时基于 JDK 的 Concurrent 和 NIO,存取速度高,并发性能高,支持 CAS 操作,已停止更新。

XMemcached 客户端

  • XMemcached 客户端同样基于 NIO 实现,减少了线程创建和切换的开销,这一点在高并发下特别明显,一直更新。推荐使用。

三、下载安装Memcached

地址:memcached下载

在这里插入图片描述
把这个链接复制到新的标签页打开自动下载。下载后的压缩包解压如下

在这里插入图片描述

使用管理员权限打开cmd,进入此路径

笔者下载的是1.4.4版本

memcached <1.4.5 版本安装

  1. 解压下载的安装包到指定目录。

  2. 在 1.4.5 版本以前 memcached 可以作为一个服务安装,使用管理员权限运行以下命令:

c:\memcached\memcached.exe -d install
注意:你需要使用真实的路径替代 c:\memcached\memcached.exe。

3、然后我们可以使用以下命令来启动和关闭 memcached 服务:

c:\memcached\memcached.exe -d start
c:\memcached\memcached.exe -d stop

在这里插入图片描述
然后使用sc query memcached查看命令是否成功:

在这里插入图片描述
打开 服务列表发现memcached服务已安装,并且是开机自启动,后续无需手动再执行
memcached.exe -d start命令了
在这里插入图片描述

四、各种类型客户端实践

先创建一个Memcached-Project的springboot应用,创建好后去resources下把application.properties改为application.yml

为了方便,三种java客户端,我都使用这个项目来展示。

4.1 Memcached-java-client

首先在pom引入如下依赖:

 <!--Memcached-java-client-->
        <dependency>
            <groupId>commons-pool</groupId>
            <artifactId>commons-pool</artifactId>
        </dependency>
        <dependency>
            <groupId>com.whalin</groupId>
            <artifactId>Memcached-Java-Client</artifactId>
            <version>3.0.2</version>
        </dependency>

MemcachedConfig配置类:

package com.hulei.memcached.memcachedjavaclient;

import com.whalin.MemCached.MemCachedClient;
import com.whalin.MemCached.SockIOPool;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author hulei
 * Memcached-java-client的配置
 */
@Configuration
public class MemcachedConfig {

    @Value("${MemcachedJavaClient.memcached.servers}")
    private String[] servers;
    @Value("${MemcachedJavaClient.memcached.failover}")
    private boolean failover;
    @Value("${MemcachedJavaClient.memcached.initConn}")
    private int initConn;
    @Value("${MemcachedJavaClient.memcached.minConn}")
    private int minConn;
    @Value("${MemcachedJavaClient.memcached.maxConn}")
    private int maxConn;
    @Value("${MemcachedJavaClient.memcached.maintSleep}")
    private int maintSleep;
    @Value("${MemcachedJavaClient.memcached.nagel}")
    private boolean nagel;
    @Value("${MemcachedJavaClient.memcached.socketTO}")
    private int socketTO;
    @Value("${MemcachedJavaClient.memcached.aliveCheck}")
    private boolean aliveCheck;

    @Bean
    public SockIOPool sockIOPool () {
        SockIOPool pool = SockIOPool.getInstance();
        pool.setServers(servers);
        pool.setFailover(failover);
        pool.setInitConn(initConn);
        pool.setMinConn(minConn);
        pool.setMaxConn(maxConn);
        pool.setMaintSleep(maintSleep);
        pool.setNagle(nagel);
        pool.setSocketTO(socketTO);
        pool.setAliveCheck(aliveCheck);
        pool.initialize();
        return pool;
    }

    @Bean
    @ConditionalOnBean(SockIOPool.class)
    public MemCachedClient memCachedClient(){
        return new MemCachedClient();
    }

}

yml配置:
在这里插入图片描述

MemcachedController测试类:

package com.hulei.memcached.memcachedjavaclient;

import com.whalin.MemCached.MemCachedClient;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@RestController
public class MemcachedController {

	@Resource
	private MemCachedClient memCachedClient;

	@RequestMapping("/memcachedIndex")
	public String memcachedIndex() throws InterruptedException {
		// 放入缓存
		boolean flag = memCachedClient.set("a", 1);
		System.out.println(flag);
		// 取出缓存
		Object a = memCachedClient.get("a");
		System.out.println(a);
		// 3s后过期
		memCachedClient.set("b", "2", new Date(3000));
		Object b = memCachedClient.get("b");
		System.out.println(b);

		Thread.sleep(3000);
		b = memCachedClient.get("b");
                System.out.println(a);
		System.out.println(b);
		return "abcd";
	}
}

浏览器输入地址:http://localhost:8080/memcachedIndex,观察IDEA控制台输出:
在这里插入图片描述

4.2 SpyMemcached

pom中引入依赖:

        <!--SpyMemcached-->
        <dependency>
            <groupId>net.spy</groupId>
            <artifactId>spymemcached</artifactId>
            <version>2.12.3</version>
        </dependency>

SpyMemcachedConfig配置类:

package com.hulei.memcached.spymemcached;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.spy.memcached.MemcachedClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.net.InetSocketAddress;

@Configuration
@Slf4j
public class SpyMemcachedConfig implements CommandLineRunner {

        @Value("${SpyMemcached.memcached.ip}")
        private String ip;
        @Value("${SpyMemcached.memcached.port}")
        private int port;

        @Getter
        private MemcachedClient client = null;

	@Override
	public void run(String... args) {
		try {
			client = new MemcachedClient(new InetSocketAddress(ip,port));
		} catch (IOException e) {
			log.error("SpyMemcached初始化失败",e);
			throw new RuntimeException("SpyMemcached初始化失败");
		}
	}

}

yml配置

在这里插入图片描述

SpyMemcachedController测试控制类:

package com.hulei.memcached.spymemcached;

import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SpyMemcachedController {

	@Resource
	private SpyMemcachedConfig spyMemcachedConfig;

	@RequestMapping("/spyMemcachedIndex")
	public String spyMemcachedIndex() throws InterruptedException {
		/*这个过期时间单位是秒,最大值是60*60*24*30*/
		spyMemcachedConfig.getClient().set("spyMemcachedKey",1,"张三");
		System.out.println("基于spyMemcached实现,现在的值为 "+spyMemcachedConfig.getClient().get("spyMemcachedKey"));
		Thread.sleep(2000);
		System.out.println("1秒后缓存内容清除,现在的值为: "+spyMemcachedConfig.getClient().get("spyMemcachedKey"));
		return "SpyMemcached";
	}
}

浏览器输入地址:http://localhost:8080/spyMemcachedIndex,观察IDEA控制台输出:

在这里插入图片描述

4.3 XMemcached

pom中再引入依赖:

        <!--XMemcached -->
        <dependency>
            <groupId>com.googlecode.xmemcached</groupId>
            <artifactId>xmemcached</artifactId>
            <version>2.4.8</version>
        </dependency>

XMemcachedConfig配置类:

package com.hulei.memcached.xmemcached;

import lombok.extern.slf4j.Slf4j;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.command.BinaryCommandFactory;
import net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@Slf4j
public class XMemcachedConfig {

	@Value("${XMemcached.memcached.server}")
	private String server;

	@Value("${XMemcached.memcached.opTimeout}")
	private Integer opTimeout;

	@Value("${XMemcached.memcached.poolSize}")
	private Integer poolSize;

	@Value("${XMemcached.memcached.failureMode}")
	private boolean failureMode;

	@Value("${XMemcached.memcached.enabled}")
	private boolean enabled;

	@Bean(name = "memcachedClientBuilder")
	public MemcachedClientBuilder getBuilder() {
		MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder(server);
		// 内部采用一致性哈希算法
		memcachedClientBuilder.setSessionLocator(new KetamaMemcachedSessionLocator());
		// 操作的超时时间
		memcachedClientBuilder.setOpTimeout(opTimeout);
		// 采用二进制传输协议(默认为文本协议)
		memcachedClientBuilder.setCommandFactory(new BinaryCommandFactory());
		// 设置连接池的大小
		memcachedClientBuilder.setConnectionPoolSize(poolSize);
		// 是否开起失败模式
		memcachedClientBuilder.setFailureMode(failureMode);
		return memcachedClientBuilder;
	}
	/**
	 * 由Builder创建memcachedClient对象,并注入spring容器中
	 */
	@Bean(name = "memcachedClient")
	public MemcachedClient getClient(@Qualifier("memcachedClientBuilder") MemcachedClientBuilder memcachedClientBuilder) {
		MemcachedClient client;
		try {
			client =  memcachedClientBuilder.build();
		} catch(Exception e) {
			log.error("创建MemcachedClient对象失败", e);
			throw new RuntimeException("创建MemcachedClient对象失败", e);
		}
		return client;
	}
}

yml配置
在这里插入图片描述

XMemcachedController测试服务类:

package com.hulei.memcached.xmemcached;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.rubyeye.xmemcached.MemcachedClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class XMemcachedController {

	@Resource
	private MemcachedClient memcachedClient;

	@RequestMapping("/XMemcachedIndex")
	public String XMemcachedIndex() {
		try {
			//新增操作
			memcachedClient.set("XMemcachedKeyOne",0,"张三");
			System.out.println((String)memcachedClient.get("XMemcachedKeyOne"));

			//删除操作
			memcachedClient.delete("XMemcachedKeyOne");
			System.out.println((String)memcachedClient.get("XMemcachedKeyOne"));

			//设置存活时间
			memcachedClient.set("XMemcachedKeyTwo",1,"李四");
			Thread.sleep(2000);
			System.out.println((String)memcachedClient.get("XMemcachedKeyTwo"));

			//更新操作
			memcachedClient.set("XMemcachedKeyThree",0,"王五");
			System.out.println((String)memcachedClient.get("XMemcachedKeyThree"));
			memcachedClient.set("XMemcachedKeyThree",0,"王五他儿子");
			System.out.println((String)memcachedClient.get("XMemcachedKeyThree"));

		} catch (Exception e) {
			log.error("XMemcachedIndex error",e);
		}
		return "xMemcachedIndex";
	}
}

浏览器输入地址:http://localhost:8080/XMemcachedIndex,观察IDEA控制台输出:
在这里插入图片描述

五、总结

通过以上三个java客户端的案例,演示了Memcached的实际用法,整体较为简单,笔者把三个客户端的代码用一个项目演示,需要源码的请从文章顶部获取。

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

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

相关文章

路由数据获取及封装方法

数据库设计 自联表 定义tree字段 public class LabelValue{public int label { get; set; }public string? value { get; set; }public List<LabelValue> children { get; set; }}获取路由方法 public Response<object> getMenuList() {Response<object>…

【python基础】基本数据类型

文章目录 一. Python基本数据类型1. 整数1.1. python的四种进制1.2. 数中的下划线 2. 浮点数3. 复数4. 布尔型5. 运算符5.1. 算术运算符5.2. 比较运算符5.3. 逻辑运算符5.4 运算符优先级 6. 常量 二. 注释三. Python之禅 一. Python基本数据类型 1. 整数 无长度限制&#xff1…

Java面试八股之什么是Redis的缓存更新

什么是Redis的缓存更新 Redis的缓存更新是指当缓存中的数据发生变化时&#xff0c;需要将这些变化同步到缓存中以保持数据的一致性。缓存更新的目的是确保缓存中的数据始终是最新的&#xff0c;以便用户可以获取到最新的数据。 常见的缓存更新策略包括&#xff1a; 直接覆盖…

OpenCv 如何在 Java 中使用

Java 项目引入 OpenCv 环境准备OpenCv介绍下载Maven 安装动态链接库 完成 环境准备 JDK 8 OpenCv 4.0.0 Maven 3.9 Windows 11 OpenCv 介绍 OpenCV&#xff08;开源计算机视觉库&#xff09;是一个功能强大的计算机视觉和机器学习库。它提供了广泛的工具和算法&#xff0c;用…

Kafka Producer之幂等性

文章目录 1. 启用幂等性2. 底层变化3. 数据不重复4. 数据有序 幂等性通过消耗时间和性能的方式&#xff0c;解决乱序和重复问题。 但是只能保证同一生产者在一个分区中的幂等性。 1. 启用幂等性 //创建producerHashMap<String, Object> config new HashMap<>();…

js vue axios post 数组请求参数获取转换, 后端go参数解析(gin框架)全流程示例

今天介绍的是前后端分离系统中的请求参数 数组参数的生成&#xff0c;api请求发送&#xff0c;到后端请求参数接收的全过程示例。 为何会有这个文章&#xff1a;后端同一个API接口同时处理单条或者多条数据&#xff0c;这样就要求我们在前端发送请求参数的时候需要统一将请…

精准营销从数据开始,Xinstall为App增长插上翅膀,安装数据尽在掌握!

在这个信息爆炸的时代&#xff0c;App市场竞争日益激烈&#xff0c;如何精准获取并分析安装数据&#xff0c;成为了每一个App开发者和运营者必须面对的重要课题。数据&#xff0c;是指导我们行动的灯塔&#xff0c;是优化策略、提升转化的关键。然而&#xff0c;对于许多开发者…

ElmoCha——体验最好的 web 内容 AI 总结插件

介绍 最近我用了很多网页总结产品&#xff0c;share 一下我认为最好用的 web 总结的 AI 插件。 当前体验最好的 web 内容总结插件&#xff1a;ElmoChat&#xff0c;由 Lepton 开发&#xff0c;可以生成网页总结、摘要、观点、相关问题。 非常方便的是&#xff0c;总结的内容提…

【学习笔记】无人机系统(UAS)的连接、识别和跟踪(二)-定义和缩写

引言 3GPP TS 23.256 技术规范&#xff0c;主要定义了3GPP系统对无人机&#xff08;UAV&#xff09;的连接性、身份识别、跟踪及A2X&#xff08;Aircraft-to-Everything&#xff09;服务的支持。 3GPP TS 23.256 技术规范&#xff1a; 【免费】3GPPTS23.256技术报告-无人机系…

【JVM基础03】——组成-详细介绍下Java中的堆

目录 1- 引言&#xff1a;堆1-1 堆是什么&#xff1f;(What)1-2 为什么用堆&#xff1f;堆的作用 (Why) 2- ⭐核心&#xff1a;堆的原理&#xff08;How&#xff09;2-1 堆的划分2-2 Java 7 与 Java 8 的堆区别 3- 小结&#xff1a;3-1 详细介绍下Java的堆&#xff1f;3-2 JVM …

【转盘案例-弹框-修改Bug-完成 Objective-C语言】

一、我们来看示例程序啊 1.旋转完了以后,它会弹一个框,这个框,是啥, Alert 啊,AlertView 也行, AlertView,跟大家说过,是吧,演示过的啊,然后,我们就用iOS9来做了啊,完成了以后,我们要去弹一个框, // 弹框 UIAlertController *alertController = [UIAlertContr…

CI/CD的node.js编译报错npm ERR! network request to https://registry.npmjs.org/

1、背景&#xff1a; 在维护paas云平台过程中&#xff0c;有研发反馈paas云平台上的CI/CD的前端流水线执行异常。 2、问题描述&#xff1a; 流水线执行的是前端编译&#xff0c;使用的是node.js环境。报错内容如下&#xff1a; 2024-07-18T01:23:04.203585287Z npm ERR! code E…

源码分析SpringCloud Gateway如何加载断言(predicates)与过滤器(filters)

我们今天的主角是Gateway网关&#xff0c;一听名字就知道它基本的任务就是去分发路由。根据不同的指定名称去请求各个服务&#xff0c;下面是Gateway官方的解释&#xff1a; Spring Cloud Gateway&#xff0c;其他的博主就不多说了&#xff0c;大家多去官网看看&#xff0c;只…

HarmonyOS NEXT零基础入门到实战-第一部分

构建节页面思路&#xff1a; 1、排版 (分析布局) 2、内容&#xff08;基础组件&#xff09; 3、美化&#xff08;属性方法&#xff09; 设计资源-svg图标 界面中展示图标 ->可以使用svg图标&#xff08;任意放大缩小不失真&#xff0c;可以改颜色&#xff09; 使用方式&a…

Re-labeling ImageNet(CVPR 2021, Naver)

paper&#xff1a;Re-labeling ImageNet: from Single to Multi-Labels, from Global to Localized Labels official implementation&#xff1a;GitHub - naver-ai/relabel_imagenet 背景 ImageNet 数据集是现代计算机视觉领域的重要基准&#xff0c;广泛用于图像分类模型的…

低代码中间件学习体验分享:业务系统的创新引擎

前言 星云低代码平台介绍 星云低代码中间件主要面向企业IT部门、软件实施部门的低代码开发平台&#xff0c;无需学习开发语言/技术框架&#xff0c;可视化开发PC网页/PC项目/小程序/安卓/IOS原生移动应用&#xff0c;低门槛&#xff0c;高效率。针对企业研发部门人员少&#…

从0到1搭建数据中台(4):neo4j初识及安装使用

在数据中台中&#xff0c;neo4j作为图数据库&#xff0c;可以用于数据血缘关系的存储 图数据库的其他用于主要用于知识图谱&#xff0c;人物关系的搭建&#xff0c;描述实体&#xff0c;关系&#xff0c;以及实体属性 安装 在官网 https://neo4j.com/ 下载安装包 neo4j-co…

【jenkins+cmake+svn管理c++项目】msbuild: command not found

一、前言 jenkins中配置cmakeVS的编译构建过程&#xff0c;需要用到MSBuild这个工具来完成VS工作&#xff0c;MSBuild的安装配置方法见&#xff1a;windows编译环境和工具配置 MSBuildCMAKE的编译可以用脚本来完成&#xff0c;我在jenkins的构建步骤中添加了一个ExecuteShell…

Hadoop-36 HBase 3节点云服务器集群 HBase Shell 增删改查 全程多图详细 列族 row key value filter

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; HadoopHDFSMapReduceHiveFlumeSqoopZookeeperHBase 正在 章节内容 上一节我们完成了&#xff1a; 集群的…

解决:Linux上SVN 1.12版本以上无法直接存储明文密码

问题&#xff1a;今天在Linux机器上安装了SVN&#xff0c;作为客户端使用&#xff0c;首次执行SVN相关操作&#xff0c;输入账号密码信息后&#xff0c;后面再执行SVN相关操作&#xff08;比如"svn update"&#xff09;还是每次都需要输入密码。 回想以前在首次输入…