一、常见命令
1 set k1 v1
向当前库(0号库)设置一个键 k1,它的值为 v1
2 get k1
获取键 k1 的值
3 del k1
若 k1 存在,则删除 k1
4 append k1 234
向键 k1 的 value 后面追加(拼接一个字符串,因为键默认是字符串类型) “234” 字符串
5 strlen k1
获取键 k1 的长度
6 incr k1
键 k1 对应的 value 加 1(必须是数字类型的字符串)
7 decr k1
键 k1 对应的 value 减 1(必须是数字类型的字符串)
8 incrby k1 7
键 k1 对应的 value 加 7(必须是数字类型的字符串)
9 decrby k1 5
键 k1 对应的 value 减 5(必须是数字类型的字符串)
10 getrange k1 0 -1
获取键 k1 所对应的 value 的所有位置的值 == get k1
11 getrange k1 0 2
获取键 k1 所对应的 value 的字符串的前三个字符串(就相当于 substring)
12 setrange k1 1 000
从键 k1 所对应的 value 的下标为 1 的位置向后覆盖 “000” 字符串
13 setex k2 10 vvv
设置键 k2 对应的 value 为 “vvv” 过期时间为 10 秒
14 setnx k1 v1
如果键 k1 不存在的话就添加
15 mset k1 v1 k2 v2
同时设置多个 key-value
16 mget k1 k2 k3
同时返回多个键对应的 value(不存在的键会返回 nil)
17 msetnx k3 v3 k1 v1
不存在的键才会设置(只要有一个键设置失败,其他的都失败)(msetnx 是一个原子性的操作,要么一起成功,要么一起失败!)
18 getset k1 v1
先获取 k1 的旧值,再为它赋新值 “v1”(若之前不存在 k1 则返回 nil)
19 对象存储方式
# 对象
set user:1 {name:zhangsan,age:3} # 设置一个user:1 对象 值为 json字符来保存一个对象!
# 这里的key是一个巧妙的设计: user:{id}:{filed} , 如此设计在Redis中是完全OK了!
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "2"
二、真实应用场景
2.1 用redis当缓存层来加速读写性能降低后端的压力
//注意:本代码只是示例,后续修改
String userIdForRedis = "dmpuser:info:"+id;
//从缓存中查询数据,若是前后端分离项目用JSON作数据交互,直接存json串
User user = (User) SerializeUtil.unserialize(redisClei.get(userIdForRedis.getBytes()));
if(user != null){
//缓存中有直接取缓存数据
return user;
}
//没有则从数据库中查询
return userDao.selectUserById(id);
2.2 用作计数器,数据分两类冷数据与热数据,热数据表示经常使用的时常发生变化的数据如一个视频的点击量,某文件的浏览次数,某商品的日月销量,系统消息以及用户消息这些热数据都可以用Redis来做,下面是一个思路(粉丝数一样的做法)
redis> HSET user:<userId>:message system 1 //1条未读系统消息
(integer) 1
redis> HINCRBY user:<userId>:message system 1 //未读系统消息+1
(integer) 2
redis> HINCRBY user:<userId>:message comment 1 //未读评论消息+1
(integer) 1
redis> HSET user:<userId>:message system 0//设为系统消息已读
(integer) 1
redis> HGETALL user:<userId>:message //获取这key hashkey 和value
1) "system"
2) "0"
3) "comment"
4) "1"
2.3 限制某段时间内的访问次数,就比如我们登录的功能可以用手机获取验证码登录,但是我们发送验证码使用的第三方,是多少钱多少条的,肯定不能让他一直点,一直发短信,就算前端js做了校验,若有些人用fiddler拦截绕过前台就麻烦了,这时候可以用redis的incr命令和expire结合起来做一个解决方案
解决方案
用户请求了我们的发送短信验证码服务
先从换从里取出这个用户对应的key(可以是电话号码拼接点东西)
mKey = redisCli.get(key);
if(mKey != null)
{
如果缓存中存在了,就是已经请求过验证码了,比如我系统参数设置的至少60秒发送一次短信
那就代表60之内再次请求了,返回false阻止
return false;
}
else
{
否则就是第一次请求短信验证码或者等了60再次请求的验证码
发送验证码
sendMsg()
放入redis缓存并设置失效时间60秒
redisCli.set(key,value,expire)
}
具体参考
try {
//先判断Redis中是否有该key值
if (RedisHelper.exists(key)) {
//取出访问次数
int times = Integer.parseInt(RedisHelper.get(key));
//判断访问是否大于最大次数
if (times >= maxTimes) {
return true;
}
//若不大于则将访问次数加1
RedisHelper.incr(key, 1L);
} else { //若没有则创建并设置失效时间
RedisHelper.set(key, "1", days, TimeUnit.DAYS);
}
} catch (Exception e) {
throw new Exception
}
return false;
}
2.4 分布式的共享session
当我们的系统做成分布式的时候,我们分布式的服务器将用户的session信息保存在各自的服务器中,那么在做Nginx负载均衡的时候,各个用户的请求都会被负载到各个服务器上,这样就造成这么一个问题,比如我们某些服务是需要用户登录才能使用的,一般我们会在用户进行操作的时候用一个拦截器去拦截用户的请求,然后再查看服务器中的Session中有没有用户的信息,如果有就放行。没有就跳转到登录界面提示登录,也就是一个简单的横向越权的问题。在分布式的系统中就比较头疼了,比如我们系统中有三台服务器做负载均衡,服务器A,服务器B,服务器C
第一次请求被Nginx转发到了服务器A,用户登录之后,操作请求又被分发到了服务器B,这时B服务器没有用户的Session数据,又提示用户需要登录就造成了非常不友好的用户体验,我想到的是两种解决方案,一种是按用户的ip来进行计算,对应的ip经过算法的处理,固定请求某一固定的服务器。还有一种就是用Redis将用户的Session信息进行集中的管理,每次用户登录信息都从Redis中集中获取,也就很好的解决了这一问题