首先我们使用docker安装下redis,关于docker还不会用的可以去百度学习下,安装使用还是非常简单的。
1.拉取下redis镜像
docker pull redis:3.2
2.启动容器
dcker run -p 6699:6379 --name myredis -v $PWD/redis.conf:/etc/redis/redis.conf -v $PWD/data:/data -d redis:3.2 redis-server /etc/redis/redis.conf --appendonly yes --requirepass "123456"
命令说明:
--name myredis : 指定容器名称,这个最好加上,不然在看docker进程的时候会很尴尬。
-p 6699:6379 : 端口映射,默认redis启动的是6379,至于外部端口,随便玩吧,不冲突就行。
-v $PWD/redis.conf:/etc/redis/redis.conf : 将主机中当前目录下的redis.conf配置文件映射。
-v $PWD/data:/data -d redis:3.2 :将主机中当前目录下的data挂载到容器的/data
--redis-server --appendonly yes :在容器执行redis-server启动命令,并打开redis持久化配置
--requirepass "123456" 设置redis密码为123456
docker ps 查看下运行状态
使用RedisDesktopManager工具连接下redis测试下
接下就可以集成redis操作起来了。
spring:
redis:
database: 5 #redis中的db5(在命令行可用 select 5 来切换到当前的db)
# 配置Redis的主机地址
host: 192.168.1.174
port: 6379
password: 123456
timeout: 5000
jedis:
pool:
# 连接池中的最大空闲连接,默认值也是8。
max-idle: 500
# 连接池中的最小空闲连接,默认值也是0。
min-idle: 50
# 如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)
max-active: 1000
# 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException
max-wait: 2000
封装一下java操作redis的工具类
package lee.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* @author :lyj
* @email: : iclyj@iclyj.cn
* @date :2019/11/5
*/
@Service
@Slf4j
public class RedisServiceUtil {
@Resource
private StringRedisTemplate stringRedisTemplate;
public static final String userStringKey = "lyj:";
private RedisTemplate<Serializable, Object> redisTemplate;
/**
* set redis : string类型
* @param key key
* @param value value
*/
public void setString(String key,String value){
ValueOperations<String,String> valueOperations = stringRedisTemplate.opsForValue();
valueOperations.set(key,value);
}
public String getString(String key){
return stringRedisTemplate.opsForValue().get(key);
}
/**
* set redis: hash类型
* @param key key
* @param filedKey filedkey
* @param value value
*/
public void setHash(String key, String filedKey, String value){
HashOperations<String, Object, Object> hashOperations = stringRedisTemplate.opsForHash();
hashOperations.put(key,filedKey, value);
}
/**
* get redis: hash类型
* @param key key
* @param filedkey filedkey
* @return
*/
public String getHash(String key, String filedkey){
return (String) stringRedisTemplate.opsForHash().get(key, filedkey);
}
/**
* set redis:list类型
* @param key key
* @param value value
* @return
*/
public long setList(String key, String value){
ListOperations<String, String> listOperations = stringRedisTemplate.opsForList();
return listOperations.leftPush(key, value);
}
/**
* get redis:list类型
* @param key key
* @param start start
* @param end end
* @return
*/
public List<String> getList(String key, long start, long end) {
return stringRedisTemplate.opsForList().range(key, start, end);
}
/**
* 设置key失效时间
* @param key key
* @param timeout timeout
* @return
*/
public boolean setTimeOut(String key, long timeout){
return stringRedisTemplate.expire(key,timeout, TimeUnit.SECONDS);
}
/**
* 根据key删除值
* @param key
* @return
*/
public boolean delKey(String key){
return stringRedisTemplate.delete(key);
}
/**
* 设置值并设置失效时间
* @param key
* @param value
* @param timeOut
*/
public void setCachesData(String key,String value,long timeOut){
if (log.isDebugEnabled()) {
log.debug("String, String, int - start"); //$NON-NLS-1$
}
setString(key,value);
setTimeOut(key,timeOut);
if (log.isDebugEnabled()) {
log.debug("String, String, int - start"); //$NON-NLS-1$
}
}
/**
* 从缓存中删除数据
*
* @param key
* @return
*/
public boolean removeValue(String key) {
if (log.isDebugEnabled()) {
log.debug("String - start"); //$NON-NLS-1$
}
boolean returnlong = delKey(key);
if (log.isDebugEnabled()) {
log.debug("String - end"); //$NON-NLS-1$
}
return returnlong;
}
/**
* 批量删除对应的value
* @param keys
*/
public void remove(final String... keys){
for (String key : keys){
remove(key);
}
}
/**
* 批量删除key
*
* @param pattern
*/
public void removePattern(final String pattern) {
Set<Serializable> keys = redisTemplate.keys(pattern);
if (keys.size() > 0)
redisTemplate.delete(keys);
}
/**
* 删除对应的value
*
* @param key
*/
public void remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/**
* 判断缓存中是否有对应的value
*
* @param key
* @return
*/
public boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
/**
* 读取缓存
*
* @param key
* @return
*/
public Object get(final String key) {
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate
.opsForValue();
result = operations.get(key);
return result;
}
/**
* 写入缓存
*
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value) {
boolean result = false;
try {
// ValueOperations<Serializable, Object> operations = redisTemplate
// .opsForValue();
// operations.set(key, value);
redisTemplate.opsForValue().set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 写入缓存
*
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value, Long expireTime) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate
.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public void batchDel(String... pattern){
for (String kp : pattern) {
redisTemplate.delete(redisTemplate.keys(kp + "*"));
}
}
public Set<Object> getKeys(){
return redisTemplate.opsForSet().members("*".getBytes());
}
public void setRedisTemplate(
RedisTemplate<Serializable, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
}
现在实现第一个功能限定用户登录非常的简单
只需要登录成功之后将用户信息设置到redis中给定一个过期时间,登录之前根据key值去查询下redis是否存在当前用户如果有就直接返回当前用户已被登录。当然登出的时候我们也要做相应的操作。
接下来完成第二个功能我们需要用到一个工具类
package lee.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
/**
* @author :lyj
* @email: : iclyj@iclyj.cn
* @date :2019/11/6
*/
public class JsonUtils {
private static final ObjectMapper MAPPER = new ObjectMapper();
public JsonUtils() {
}
public static String objectToJson(Object data) {
try {
String string = MAPPER.writeValueAsString(data);
return string;
} catch (JsonProcessingException var2) {
var2.printStackTrace();
return null;
}
}
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception var3) {
var3.printStackTrace();
return null;
}
}
public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, new Class[]{beanType});
try {
List<T> list = (List)MAPPER.readValue(jsonData, javaType);
return list;
} catch (Exception var4) {
var4.printStackTrace();
return null;
}
}
}
相同的道理在查询之前将值转成josn设置到redis中,查询之前根据设置的key值查询出来value值将转换为list返回出去即可。
到这我们redis的操作的两个简单的功能就完成了,操作起来还是非常的简单的,但是到了真实的项目中往往只会这些简单的操作还是不行的。
可以思考思考如下的问题:
答案可以到这里查看:https://doocs.github.io/advanced-java/#/?id=%e7%bc%93%e5%ad%98
1.在项目中缓存是如何使用的?缓存如果使用不当会造成什么后果?
2.Redis 和 Memcached 有什么区别?Redis 的线程模型是什么?为什么单线程的 Redis
3.比多线程的 Memcached 效率要高得多?
4.Redis 都有哪些数据类型?分别在哪些场景下使用比较合适?
5.Redis 的过期策略都有哪些?手写一下 LRU 代码实现?
6.如何保证 Redis 高并发、高可用?Redis 的主从复制原理能介绍一下么?Redis 的哨兵原理能介绍一下么?
.Redis 的持久化有哪几种方式?不同的持久化机制都有什么优缺点?持久化机制具体底层是如何实现的?
8.Redis 集群模式的工作原理能说一下么?在集群模式下,Redis 的 key 是如何寻址的?
9.分布式寻址都有哪些算法?了解一致性 hash 算法吗?如何动态增加和删除一个节点?
10.了解什么是 redis 的雪崩、穿透和击穿?Redis 崩溃之后会怎么样?系统该如何应对
11.这种情况?如何处理 Redis 的穿透?
12.如何保证缓存与数据库的双写一致性?
13.Redis 的并发竞争问题是什么?如何解决这个问题?了解 Redis 事务的 CAS 方案吗?14.生产环境中的 Redis 是怎么部署的?