springboot中集成memcached
前言
Memcached 是一个高性能的分布式内存对象缓存系统,其存储性能在某些方面不比redis差,甚至在文本类型数据的存储上性能略优于redis,本文将介绍如何在springboot中集成memcached
准备工作
首先我们需要一款客户端连接对象,类似于我们在使用redis时使用的jedis , 目前memcached主流的客户端是Xmemcached,如果使用的是maven构建项目,则引入对应的依赖
- <!--引入memcached-->
- <dependency>
- <groupId>com.googlecode.xmemcached</groupId>
- <artifactId>xmemcached</artifactId>
- <version>2.4.5</version>
- </dependency>
配置
memcached在yml(properties)文件的相关配置
- # memcached配置
- memcached:
- server: 1.1.1.1:3333 2.2.2.2:4444 #memcached服务器集群(格式为host:port,多个服务器之间用空格隔开)
- opTimeout: 3000 #接口操作的默认超时时间,可以被接口覆盖
- poolSize: 10 #池子大小
- failureMode: false #是否开启失败模式,默认为false
- enabled: true # 是否使用memcached缓存
将memcached的配置由bean来管理,方便我们调用
- package com.me.config.properties;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.stereotype.Component;
- /**
- * @author : wang zns
- * @date : 2018-12-19
- */
- @Component
- @ConfigurationProperties(prefix = "memcached")
- public class MemcachedProperties {
- /**
- * 服务器
- */
- private String server;
- /**
- * 操作超时时间,可以被API覆盖
- */
- private Integer opTimeout;
- /**
- * 连接池大小
- */
- private Integer poolSize;
- /**
- * 是否开启失败模式
- */
- private boolean failureMode;
- /**
- * 是否使用memcached缓存
- */
- private boolean enabled;
- public String getServer() {
- return server;
- }
- public void setServer(String server) {
- this.server = server;
- }
- public Integer getOpTimeout() {
- return opTimeout;
- }
- public void setOpTimeout(Integer opTimeout) {
- this.opTimeout = opTimeout;
- }
- public Integer getPoolSize() {
- return poolSize;
- }
- public void setPoolSize(Integer poolSize) {
- this.poolSize = poolSize;
- }
- public boolean isFailureMode() {
- return failureMode;
- }
- public void setFailureMode(boolean failureMode) {
- this.failureMode = failureMode;
- }
- public boolean isEnabled() {
- return enabled;
- }
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
- }
memcached配置类(创建memcached客户端对象,并注入spring容器中)
- package com.me.config;
- import cn.stylefeng.guns.config.properties.MemcachedProperties;
- 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.Autowired;
- import org.springframework.beans.factory.annotation.Qualifier;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- /**
- * @author : wang zns
- * @date : 2018-12-19
- */
- @Configuration
- @Slf4j
- public class MemcachedConfig {
- @Autowired
- private MemcachedProperties memcachedProperties;
- @Bean(name = "memcachedClientBuilder")
- public MemcachedClientBuilder getBuilder() {
- MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder(memcachedProperties.getServer());
- // 内部采用一致性哈希算法
- memcachedClientBuilder.setSessionLocator(new KetamaMemcachedSessionLocator());
- // 操作的超时时间
- memcachedClientBuilder.setOpTimeout(memcachedProperties.getOpTimeout());
- // 采用二进制传输协议(默认为文本协议)
- memcachedClientBuilder.setCommandFactory(new BinaryCommandFactory());
- // 设置连接池的大小
- memcachedClientBuilder.setConnectionPoolSize(memcachedProperties.getPoolSize());
- // 是否开起失败模式
- memcachedClientBuilder.setFailureMode(memcachedProperties.isFailureMode());
- return memcachedClientBuilder;
- }
- /**
- * 由Builder创建memcachedClient对象,并注入spring容器中
- * @param memcachedClientBuilder
- * @return
- */
- @Bean(name = "memcachedClient")
- public MemcachedClient getClient(@Qualifier("memcachedClientBuilder") MemcachedClientBuilder memcachedClientBuilder) {
- MemcachedClient client = null;
- try {
- client = memcachedClientBuilder.build();
- } catch(Exception e) {
- log.info("exception happens when bulid memcached client{}",e.toString());
- }
- return client;
- }
- }
使用
有了client对象之后,我们可以像直接操作服务端那样进行对应的操作,下面用一个小案例进行演示
service
- package cn.stylefeng.guns.modular.housemanage.cache;
- import cn.stylefeng.guns.modular.system.model.TblHouse;
- /**
- * 房屋管理缓存 业务层
- * @author : wang zns
- * @date : 2018-12-19
- */
- public interface HouseManageCacheService {
- /**
- * 添加
- * @param tblHouse
- */
- void add(TblHouse tblHouse);
- /**
- * 根据主键删除
- * @param tblHouseId
- */
- void delete(Integer tblHouseId);
- }
serviceImpl
- package cn.stylefeng.guns.modular.housemanage.cache;
- import cn.stylefeng.guns.modular.housemanage.service.ITblHouseService;
- import cn.stylefeng.guns.modular.system.model.TblHouse;
- import com.alibaba.fastjson.JSON;
- import lombok.extern.slf4j.Slf4j;
- import net.rubyeye.xmemcached.MemcachedClient;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- /**
- * @author : wang zns
- * @date : 2018-12-19
- */
- @Service
- @Slf4j
- public class HouseManageCacheServiceImpl implements HouseManageCacheService{
- @Autowired
- private MemcachedClient memcachedClient;
- @Autowired
- private ITblHouseService iTblHouseService;
- @Override
- public void add(TblHouse tblHouse) {
- // 先入库,入库成功则入缓存
- boolean isSuccess = iTblHouseService.insert(tblHouse);
- if (isSuccess) {
- try {
- String houseJsonStr = JSON.toJSONString(tblHouse);
- memcachedClient.set(String.valueOf(tblHouse.getId()),0,houseJsonStr);
- } catch (Exception e) {
- log.info("exception happens when add House:{}",e.toString());
- throw new RuntimeException(e.getMessage());
- }
- }
- }
- @Override
- public void delete(Integer tblHouseId) {
- // 先删除数据库内容,成功则清空缓存
- boolean isSuccess = iTblHouseService.deleteById(tblHouseId);
- if (isSuccess) {
- try {
- memcachedClient.delete(String.valueOf(tblHouseId));
- } catch (Exception e) {
- log.info("exception happens when delete House:{}",e.toString());
- throw new RuntimeException(e.getMessage());
- }
- }
- }
- }
controller
- /**
- * 新增房屋管理
- */
- @RequestMapping(value = "/add")
- @ResponseBody
- public Object add(@Valid TblHouse tblHouse, BindingResult bindingResult) {
- if(bindingResult.hasErrors()){
- throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
- }
- // 如果确定要使用缓存
- if (memcachedProperties.isEnabled()) {
- houseManageCacheService.add(tblHouse);
- } else {
- tblHouseService.insert(tblHouse);
- }
- return SUCCESS_TIP;
- }
- /**
- * 删除房屋管理
- */
- @RequestMapping(value = "/delete")
- @ResponseBody
- public Object delete(@RequestParam Integer tblHouseId) {
- if (memcachedProperties.isEnabled()) {
- houseManageCacheService.delete(tblHouseId);
- } else {
- tblHouseService.deleteById(tblHouseId);
- }
- return SUCCESS_TIP;
- }
运行结果:
提交之后,去缓存服务器上查看
至此,springboot中集成memcached就完成了
写在最后
springboot集成memcached非常简单,核心步骤就是添加依赖、创建client对象并注入spring容器、然后就是用client对象进行各种操作。
client的接口当然有非常多,xmemcached对接口进行了封装。
最后附上xmemcached官网的地址,里面的文档很详细 https://github.com/killme2008/xmemcached/wiki
springboot中集成memcached的更多相关文章
- Discuz!NT中集成Memcached分布式缓存
大约在两年前我写过一篇关于Discuz!NT缓存架构的文章,在那篇文章的结尾介绍了在IIS中如果开启多个应用程序池会造成多个缓存实例之间数据同步的问题.虽然给出了一个解决方案,但无形中却把压力转移到了 ...
- 在springboot中集成mybatis开发
在springboot中利用mybatis框架进行开发需要集成mybatis才能进行开发,那么如何在springboot中集成mybatis呢?按照以下几个步骤就可以实现springboot集成myb ...
- 在springboot中集成jsp开发
springboot就是一个升级版的spring.它可以极大的简化xml配置文件,可以采用全注解形式开发,一个字就是很牛.在springboot想要使用jsp开发,需要集成jsp,在springboo ...
- SpringBoot中集成redis
转载:https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html 不是使用注解而是代码调用 需要在springbo ...
- SpringBoot中集成Swagger2
1.依赖jar <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-s ...
- 如何在SpringBoot中集成JWT(JSON Web Token)鉴权
这篇博客主要是简单介绍了一下什么是JWT,以及如何在Spring Boot项目中使用JWT(JSON Web Token). 1.关于JWT 1.1 什么是JWT 老生常谈的开头,我们要用这样一种工具 ...
- springboot 中 集成druid ,redis
1,导入druid jar包 <!--引入drud--> <dependency> <groupId>com.alibaba</groupId> < ...
- 使用Logstash同步数据至Elasticsearch,Spring Boot中集成Elasticsearch实现搜索
安装logstash.同步数据至ElasticSearch 为什么使用logstash来同步,CSDN上有一篇文章简要的分析了以下几种同步工具的优缺点:https://blog.csdn.net/la ...
- springboot中使用spring-session实现共享会话到redis(二)
上篇文章介绍了springboot中集成spring-session实现了将session分布式存到redis中.这篇在深入介绍一些spring-session的细节. 1.session超时: 在t ...
随机推荐
- [USACO19FEB]Painting the Barn G
题意 \(n\)个矩阵\((0\le x_1,y_1,x_2,y_2\le 200)\),可交,可以再放最多两个矩阵(这两个矩阵彼此不交),使得恰好被覆盖\(k\)次的位置最大.\(n,k\le 10 ...
- 使用shell程序备份crontab中的.sh脚本文件
需求 线上环境有一些定时脚本(用crontab -l可查看当前用户的),有时我们可能会改这些定时任务的脚本内容.为避免改错无后悔药,需用shell实现一个程序,定时备份crontab中的.sh脚本文件 ...
- 2019牛客多校第八场 F题 Flowers 计算几何+线段树
2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...
- linux基础之IO模型
一.IO模型 一次read操作: (1)等待数据准备好:从磁盘到内核内存 (2)从内核内存复制到进程内存 示意图如下: I/O类型: 同步和异步:synchronous,asynchronous 关注 ...
- Codeforces 1303E. Erase Subsequences 代码(dp 字符串压缩一维状态优化)
https://codeforces.com/contest/1303/problem/E #include<bits/stdc++.h> using namespace std; ; i ...
- 51nod1326 遥远的旅途(spfa+dp)
题意: 给出一个无向图,问从1到n是否存在一条长度为L的路径. n,m<=50,1<=路径长度<=10000,L<=10^18 思路: 改变一下思路,我们发现,假设从起点1走到 ...
- 【JavaScript Weekly】#471 — JANUARY 17, 2020
https://javascriptweekly.com/issues/471 #471 — JANUARY 17, 2020 READ ON THE WEB JavaScript Weekly Ba ...
- SendMessage模拟按键所需的虚拟键码
Virtual-Key Codes The following table shows the symbolic constant names, hexadecimal values, and mou ...
- Jungle Roads POJ - 1251 模板题
#include<iostream> #include<cstring> #include<algorithm> using namespace std; cons ...
- IDEA的Debug模式灰色无法运行
1. 检查本地环境是否配置得当,进入项目右键看项目是否可以正常debug运行 2. 如果不可运行,那么选择File--Project Structrue 3. 修改Src文件,如图然后就可以正常使用 ...