Redis 在springboot中集成 redis锁、数据库、缓存demo

Redis

1.简介

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker.

Redis是一个开源的、基于内存数据结构存储器,可以用作数据库缓存消息中间件

  • 可作为分步式锁
  • 缓存
  • 数据库

2.安装

Window 下安装

下载地址:https://github.com/tporadowski/redis/releases。

3.集成springboot

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

4.数据类型

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

String

string 类型是二进制安全的。是redis中最常用的数据类型

redis 127.0.0.1:6379> SET company "Apple"
OK
redis 127.0.0.1:6379> GET company
"Apple"

Set(集合)

Redis 的 Set 是 string 类型的无序集合。

List(列表)

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

Hash(哈希)

Redis hash 是一个键值(key=>value)对集合。

Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

5.Redis 单线程模式(javaguide

Redis 基于 Reactor 模式来设计开发了自己的一套高效的事件处理模型 (Netty 的线程模型也基于 Reactor 模式,Reactor 模式不愧是高性能 IO 的基石),这套事件处理模型对应的是 Redis 中的文件事件处理器(file event handler)。由于文件事件处理器(file event handler)是单线程方式运行的,所以我们一般都说 Redis 是单线程模型。

既然是单线程,那怎么监听大量的客户端连接呢?

Redis 通过IO 多路复用程序 来监听来自客户端的大量连接(或者说是监听多个 socket),它会将感兴趣的事件及类型(读、写)注册到内核中并监听每个事件是否发生。

这样的好处非常明显: I/O 多路复用技术的使用让 Redis 不需要额外创建多余的线程来监听客户端的大量连接,降低了资源的消耗(和 NIO 中的 Selector 组件很像)。

另外, Redis 服务器是一个事件驱动程序,服务器需要处理两类事件: 1. 文件事件; 2. 时间事件。

时间事件不需要多花时间了解,我们接触最多的还是 文件事件(客户端进行读取写入等操作,涉及一系列网络通信)。

《Redis 设计与实现》有一段话是如是介绍文件事件的,我觉得写得挺不错。

Redis 基于 Reactor 模式开发了自己的网络事件处理器:这个处理器被称为文件事件处理器(file event handler)。文件事件处理器使用 I/O 多路复用(multiplexing)程序来同时监听多个套接字,并根据 套接字目前执行的任务来为套接字关联不同的事件处理器。

当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关 闭(close)等操作时,与操作相对应的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。

虽然文件事件处理器以单线程方式运行,但通过使用 I/O 多路复用程序来监听多个套接字,文件事件处理器既实现了高性能的网络通信模型,又可以很好地与 Redis 服务器中其他同样以单线程方式运行的模块进行对接,这保持了 Redis 内部单线程设计的简单性。

可以看出,文件事件处理器(file event handler)主要是包含 4 个部分:

  • 多个 socket(客户端连接)
  • IO 多路复用程序(支持多个客户端连接的关键)
  • 文件事件分派器(将 socket 关联到相应的事件处理器)
  • 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)

6. Redis作为数据库存取demo

@Controller
@RequestMapping("/redis")
public class RedisController {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @RequestMapping("/test")
    @ResponseBody
    public  String test(){
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        ops.set("leader","lll");

        String leader = ops.get("leader");
        return  leader;
    }

}

7.Redis作为锁demo

//锁的工具类
public class RedisLock {
        //得到锁
        public static boolean tryLock (String method){
            Jedis j = new Jedis("localhost", 6379);
            try {
                while (true) {
                    long r = j.setnx(method, "1");
                    if (r == 1) {
                        return true;
                    }
                    Thread.sleep(5000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
        //释放锁
        public static void unlock (String method){
            Jedis j = new Jedis("localhost", 6379);
            j.del(method);
        }
}

public class Shop {
    private  int num = 1;
    public  void  buyOne(){
        if(RedisLock.tryLock("buyone")){
            if(num>0){
                System.out.println(Thread.currentThread().getName()+"购买成功");
                num--;
            }else {
                System.out.println(Thread.currentThread().getName()+"库存不足");

            }
            RedisLock.unlock("buyone");
        }
    }
}
public class Main {
    public static void main(String[] args) {
        Shop shop=new Shop();
        Thread t1 = new Thread(()->{
            shop.buyOne();
        },"客户端1");
        Thread t2 = new Thread(()->{
            shop.buyOne();
        },"客户端2");
        t1.start();
        t2.start();
    }
}

运行结果

客户端1购买成功
客户端2库存不足

8.在springboot中配置Redis缓存

缓存工具类

package com.moon.utils;

import java.io.Serializable;
import java.util.concurrent.Callable;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.SerializationUtils;

public class RedisCache implements Cache {
	private RedisTemplate<String, Object> redisTemplate;
	private String name;

	@Override
	public void clear() {
		redisTemplate.execute(new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection connection) throws DataAccessException {
				connection.flushDb();
				return "ok";
			}
		});
		System.out.println("--------清空缓存--------");
	}

	@Override
	public void evict(Object key) {
		final String keyf = key.toString();
		redisTemplate.execute(new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.del(keyf.getBytes());
			}
		});
		System.out.println("--------删除缓存--------");
		System.out.println("key : " + keyf);
	}

	@Override
	public ValueWrapper get(Object key) {
		final String keyf = key.toString();
		Object obj = redisTemplate.execute(new RedisCallback<Object>() {
			@Override
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				byte[] keyb = keyf.getBytes();
				byte[] valueb = connection.get(keyb);
				if (valueb == null) {
					return null;
				}
				return SerializationUtils.deserialize(valueb);
			}
		});
		System.out.println("--------获取缓存--------");
		System.out.println("key : " + keyf);
		System.out.println("val : " + (obj != null ? MyStrUtils.substr(obj.toString(), 100) + " ~ " : null));
		return (obj != null ? new SimpleValueWrapper(obj) : null);
	}

	@Override
	public void put(Object key, Object value) {
		final String keyf = key.toString();
		final Object valuef = value;
		final long liveTime = 86400;
		redisTemplate.execute(new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				byte[] keyb = keyf.getBytes();
				byte[] valueb = SerializationUtils.serialize((Serializable) valuef);
				connection.set(keyb, valueb);
				if (liveTime > 0) {
					connection.expire(keyb, liveTime);
				}
				return 1L;
			}
		});
		System.out.println("--------加入缓存--------");
		System.out.println("key : " + keyf);
		System.out.println("val : " + (valuef != null ? MyStrUtils.substr(valuef.toString(), 100) + " ~ " : null));
	}

	@Override
	public <T> T get(Object arg0, Class<T> arg1) {
		return null;
	}

	@Override
	public String getName() {
		return this.name;
	}

	@Override
	public Object getNativeCache() {
		return this.redisTemplate;
	}

	@Override
	public ValueWrapper putIfAbsent(Object arg0, Object arg1) {
		return null;
	}

	public RedisTemplate<String, Object> getRedisTemplate() {
		return redisTemplate;
	}

	public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public <T> T get(Object key, Callable<T> valueLoader) {
		// TODO Auto-generated method stub
		return null;
	}
}

Config类

package com.moon.config;

import com.moon.utils.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.HashSet;
import java.util.Set;

/**
 * @author liz
 * @create 2020-08-2013:17
 */
@Configuration
@EnableCaching
public class RedisCacheConfig {
    @Autowired
    private RedisTemplate redisTemplate;


    @Bean
    public SimpleCacheManager cacheManager(RedisTemplate redisTemplate) {
        SimpleCacheManager cachemgr = new SimpleCacheManager();
        RedisCache r = new RedisCache();
        r.setRedisTemplate(redisTemplate);
        r.setName("cache0");
        Set<RedisCache> set = new HashSet<RedisCache>();
        set.add(r);
        cachemgr.setCaches(set);
        return cachemgr;
    }
}

测试demo

@Controller
@RequestMapping("/moon/Student")
public class StudentController extends BaseController {
	@Autowired
	private StudentService studentService;

	@Cacheable(cacheNames = "cache0" )
	@RequestMapping("/selectByCon")
	@ResponseBody
	public MyPage<Student> selectAll(String dept, String sex, int pageNum, int pageSize){
		return studentService.selectAll(dept,sex,pageNum,pageSize);
	}
}

执行方法后,缓存保存在Redis

image-20200822113444158

SimpleKey重命名方法

9.Redis全文检索倒排

分词:结巴分词

	 <dependency>
			<groupId>com.huaban</groupId>
			<artifactId>jieba-analysis</artifactId>
			<version>1.0.2</version>
		</dependency>

将数据库的诗词分词存入Redis

public class Analysis {
    public static void main(String[] args) throws SQLException {
        try {
            Jedis jedis = new Jedis("localhost", 6379);
            Class.forName("com.mysql.jdbc.Driver");
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydemo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai", "root", "admin");
            PreparedStatement ps = connection.prepareStatement("select * from poetry");
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                int id = rs.getInt("id");
                String title = rs.getString("title");
                String cont = rs.getString("content");
                JiebaSegmenter sg = new JiebaSegmenter();
                List<SegToken> list = sg.process(cont, JiebaSegmenter.SegMode.INDEX);
                for (SegToken tk : list) {
                    if (tk.word.length() < 2) {
                        continue;
                    }
                    jedis.sadd(tk.word, id + "");
                    System.out.println("导入完成" + title);
                }
            }
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
@Controller
@RequestMapping("/moon/Poetry")
public class PoetryController extends BaseController {
    @Autowired
    private PoetryService poetryService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RequestMapping("/selectByWord")
    @ResponseBody
    public List<Poetry> selectByWord(String word) {
        StringBuilder stringBuilder = new StringBuilder("id in(");
        JiebaSegmenter jiebaSegmenter = new JiebaSegmenter();
        List<SegToken> list = jiebaSegmenter.process(word, JiebaSegmenter.SegMode.SEARCH);
        for (SegToken tk : list) {
            Set<String> ids = stringRedisTemplate.opsForSet().members(tk.word);
            for(String id:ids){
                stringBuilder.append(id+",");

            }
        }
        stringBuilder.append("0)");
        return  poetryService.selectByWhereSql(stringBuilder.toString());
    }

}
@Transactional
@Service
public class PoetryService {
	@Autowired
	private PoetryMapper poetryMapper;

	public PoetryMapper getPoetryMapper() {
		return poetryMapper;
	}

    public List<Poetry> selectByWhereSql(String whereSql) {
		return poetryMapper.selectByWhereSql(whereSql);
    }
}
public interface PoetryMapper extends Mapper<Poetry> {
    public List<Poetry> selectByWhereSql(@Param("whereSql")String whereSql);
}
  <select id="selectByWhereSql" resultMap="BaseResultMap">
    select *
    from  poetry where  ${whereSql};
  </select>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值