redis系列(五)之string相关命令及应用

一、常见命令

set k1 v1 向当前库(0号库)设置一个键 k1,它的值为 v1

set

get k1获取键 k1 的值

get

del k1若 k1 存在,则删除 k1

del

append k1 234向键 k1 的 value 后面追加(拼接一个字符串,因为键默认是字符串类型) “234” 字符串

append

strlen k1获取键 k1 的长度

strlen

incr k1键 k1 对应的 value 加 1(必须是数字类型的字符串

incr

decr k1键 k1 对应的 value 减 1(必须是数字类型的字符串

decr

incrby k1 7键 k1 对应的 value 加 7(必须是数字类型的字符串

incrby

decrby k1 5键 k1 对应的 value 减 5(必须是数字类型的字符串

decrby

10 getrange k1 0 -1 获取键 k1 所对应的 value 的所有位置的值 == get k1

getrange

11 getrange k1 0 2 获取键 k1 所对应的 value 的字符串的前三个字符串(就相当于 substring

getrange

12 setrange k1 1 000 从键 k1 所对应的 value 的下标为 1 的位置向后覆盖 “000” 字符串

setrange

13 setex k2 10 vvv 设置键 k2 对应的 value 为 “vvv” 过期时间为 10 秒

setex

14 setnx k1 v1 如果键 k1 不存在的话就添加

setnx

15 mset k1 v1 k2 v2 同时设置多个 key-value

mset

16 mget k1 k2 k3同时返回多个键对应的 value(不存在的键会返回 nil

 mget

17 msetnx k3 v3 k1 v1不存在的键才会设置(只要有一个键设置失败,其他的都失败)(msetnx 是一个原子性的操作,要么一起成功,要么一起失败!)

msetnx

18 getset k1 v1先获取 k1 的旧值,再为它赋新值 “v1”(若之前不存在 k1 则返回 nil)

getset

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中集中获取,也就很好的解决了这一问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值