redis介绍:
Redis相信大家都不陌生了,一款优秀的开源的高性能而且轻量级的key-value存储系统。和memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。
这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。 [1]
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。
关于Redis的安装,操作,使用场景,百度一大把,这里就不做介绍了。
记得有一次面试被问到一个场景描述的技术选型性问题,就是基于redis 的key-value和查询快的缓存机制实现的唯一设备id和重连次数的判断,其实大多数情况都是根据它的数据结构,key-value机制,缓存,等特性来确定使用reids的使用场景的。
常见的有:
1,会话缓存(最常用)
2,消息队列,
比如支付3,活动排行榜或计数
4,发布,订阅消息(消息通知)
5,商品列表,评论列表等
有点跑题。。。下面是SSM关于redis整合和登录失败次数的校验部分代码,直接上代码:
1.导入Jedis依赖(建议去mave仓库下载最新依赖):
<!-- redis 依赖-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.1</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
用到了JSON,顺便把json的依赖也放上来
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
2.创建 单例的Jedis客户端
import org.springframework.core.io.support.PropertiesLoaderUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.io.IOException;
import java.util.Properties;
/**
* @Auther : guojianmin
* @Date : 2019/5/28 17:35
* @Description : redis
*/
public class JedisPoolUtil {
private static volatile JedisPool jedisPool = null;
// 获得资源包
private static Properties properties;
static {
try {
properties = PropertiesLoaderUtils.loadAllProperties("redis.properties");
} catch (IOException e) {
e.printStackTrace();
}
}
private static String host = properties.getProperty("redis.host");
private static Integer port = Integer.valueOf(properties.getProperty("redis.port"));
private static String auth = properties.getProperty("redis.auth");
private static Integer maxTotal = Integer.valueOf(properties.getProperty("redis.maxTotal"));
private static Integer maxWait = Integer.valueOf(properties.getProperty("redis.maxWait"));
private static Integer timeout = Integer.valueOf(properties.getProperty("redis.timeOut"));
private static Integer maxIdle = Integer.valueOf(properties.getProperty("redis.maxIdle"));
private static Boolean testOnBorrow = Boolean.valueOf(properties.getProperty("redis.testOnBorrow"));
private JedisPoolUtil() {};
public static JedisPool getJedisPoolInstance() {
synchronized (JedisPoolUtil.class) {
if (jedisPool == null) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(maxTotal);
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMaxWaitMillis(maxWait);
poolConfig.setTestOnBorrow(testOnBorrow);
jedisPool = new JedisPool(poolConfig, host,port,timeout,auth);
}
}
return jedisPool;
}
//释放回池子
public static void close(Jedis jedis){
if(jedis != null){
if (jedis.isConnected()) {
try {
System.out.println("退出" + jedis.toString() + ":" + jedis.quit());
jedis.disconnect();
} catch (Exception e) {
System.out.println("退出失败");
e.printStackTrace();
}
}
jedis.close();
}
}
}
3.编写redis.properties(设置的IP,端口,密码,最大连接数等)
##redis数据库的相关配置
##连接地址ip
redis.host =
##端口号
redis.port = 6379
##访问密码(开发使用redis暂时没有密码,生产可以根据需要设置密码)
redis.auth =
##控制一个pool最多可以有多少个状态为Idle(空)的jedis实例默认值为8
redis.maxIdle = 200
##等待可用连接的最大时间单位为毫秒 默认为-1表示永不超时,一旦超过等待时间则直接抛出
redis.maxWait = 100000
redis.timeOut = 10000
##设置为true则会在borrow一个jedis实例时,提前做validate操作
redis.testOnBorrow =true
##最大连接数
redis.maxTotal=30
4.LoginController
@RequestMapping(value = "/loginIn",method= {RequestMethod.POST,RequestMethod.GET})
@ResponseBody
public ResponseMsg userLogin(@RequestBody Map map, HttpServletRequest request, HttpServletResponse response) {
ResponseMsg responseMsg = new ResponseMsg();
LoginVo_Redis loginVo = new LoginVo_Redis();
String username = (String) map.get("username");
String password = (String) map.get("password");
try {
password = EncryptUtils.base64(password,"MyPassword");
System.out.println("password :========> " +password);
} catch (Exception e) {
e.printStackTrace();
}
loginVo.setUsername(username);
loginVo.setPassword(password);
loginVo.setLoginTime(DateUtil.getCurrentTime(System.currentTimeMillis()));
Jedis redis = jedisPool.getResource();
String userInfo = redis.get(username);
if (userInfo == null){
loginVo.setLoginFailureCount(0);
redis.set(username, JSONObject.toJSONString(loginVo));
userInfo = redis.get(username);
}
JSON json =JSONObject.parseObject(userInfo);
System.out.println(json);
LoginVo_Redis userLoginInfo = JSONObject.toJavaObject(json, LoginVo_Redis.class);
int loginFailCount = userLoginInfo.getLoginFailureCount();
try {
//3.判断登录失败次数是否大于3次(若大于3次,则15分钟后尝试登录)
Date lastTime = DateUtil.parseToDate(userLoginInfo.getLoginTime());
if (loginFailCount >=3 && System.currentTimeMillis() <= lastTime.getTime()+900000){
System.out.println("密码输入失败超过3次,请15分钟后继续尝试!"+DateUtil.getCurrentTime(lastTime.getTime()));
System.out.println("15分钟后:"+DateUtil.getCurrentTime(lastTime.getTime()+900000));
request.getSession().setAttribute("user",loginVo);
responseMsg.setResult(false);
responseMsg.setMsg("用户名或密码错误!");
responseMsg.setUser(null);
return responseMsg;
}
} catch (ParseException e) {
//类型转换异常
e.printStackTrace();
}
User user = userService.checkLogin(username, password);
//4.1 检查时候登录成功,登录失败,失败次数+1,记录当前登录时间并刷新缓存
if (user == null){
loginFailCount ++;
loginVo.setLoginFailureCount(loginFailCount);
redis.set(username,JSONObject.toJSONString(loginVo));
request.getSession().setAttribute("user",loginVo);
System.out.println("用户名或密码错误!");
responseMsg.setResult(false);
responseMsg.setMsg("用户名或密码错误!");
responseMsg.setUser(null);
return responseMsg;
}
//4.2 检查时候登录成功,登录成功,记录当前登录时间并刷新缓存
redis.set(username, JSONObject.toJSONString(loginVo));
request.getSession().setAttribute("user",loginVo);
responseMsg.setResult(true);
responseMsg.setMsg("登录成功!");
responseMsg.setUser(user);
return responseMsg;
}
5.用到的其他类
5.1 ResponseMsg.java
public class ResponseMsg {
private Boolean result;
private String msg;
private User user;
public ResponseMsg() {
}
public ResponseMsg(Boolean result, String msg, User user) {
this.result = result;
this.msg = msg;
this.user = user;
}
@Override
public String toString() {
return "ResponseMsg{" +
"result=" + result +
", msg='" + msg + '\'' +
", user=" + user +
'}';
}
public Boolean getResult() {
return result;
}
public void setResult(Boolean result) {
this.result = result;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
5.2 LoginVo_Redis.java
public class LoginVo_Redis {
private String username;
private String password;
private int loginFailureCount;
private String loginTime;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getLoginFailureCount() {
return loginFailureCount;
}
public void setLoginFailureCount(int loginFailureCount) {
this.loginFailureCount = loginFailureCount;
}
public String getLoginTime() {
return loginTime;
}
public void setLoginTime(String loginTime) {
this.loginTime = loginTime;
}
@Override
public String toString() {
return "LoginVo_Redis{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", loginFailureCount=" + loginFailureCount +
", loginTime='" + loginTime + '\'' +
'}';
}
}