String数据类型的编码方式:
字符串类型的内部编码有 3 种:
- int:8 个字节的长整型。
- embstr:小于等于 39 个字节的字符串。
- raw:大于 39 个字节的字符串。
Resis会根据当前值的类型和长度动态决定使用哪种内部编码实现。关于这里的39等数字一般是可以根据实际的应用场景在配置文件中去修改的,甚至有些公司会对redis源码直接进行魔改。
Redis中整数直接用int来存,相当于C++中的long long 、java中的long。对于小数是将其视作字符串来存储的,者即意味着小数运算,需要将字符串转化为小数,计算完成之后再将结果转化为字符串。
String的应用场景:
作为缓存:
收到用户请求,系统会现在redis缓存中去查找数据,如果hit也就是找到了数据,直接去使用就好了,如果miss也就是没有找到数据,那么就需要进一步在数据库中查询数据了,同时可能会将这个数据存入到redis缓存中,方便下一次查找(这里是因为,当磁盘上的数据被访问是,可能未来不久该数据及其周围为的数据很可能也会被访问到,所以可以提前将这些数据加载到缓存中,随着时间的推移,这种策略可能会导致redis内存不足,我们可以给这些从数据库加载到缓存的数据设置过期时间,以及redis的内存淘汰机制关键的作用)
计数功能:
比如统计视频播放量:
用户请求数据资源,在返回数据的时候,执行incr video:5253命令来统计播放次数。
incr video:5253 //“video:5253”是某键值对的key,video是某实体的名字,5253是实体的id。
上图只是一个简易版的统计视频播放量的流程,实际情况要更复杂一些,比如要考虑完播率,防止用户刷播放量等等。
存储session会话信息:
Cookie(浏览器存储数据的机制);Session(服务器存储数据的机制)
如果不是使用redis缓存session的话,在分布式系统中就会出现下面这种比较尴尬的况,多次请求如果被发送到不同的web服务上,因为session没有共享可能导致用户需要多次登录进行身份验证:
如果使用Redis缓存session,在分布式系统中所有web服务器可以共享这个session:
就好比,一个病人周一去医院找医生看病,医生要病人周五复查,如果周五是另外一个医生值班,新医生无法对病情做先后对比,还好医院的系统存储了病人周一时的病情,每个值班的医生都可以查看得到,就可以给病人复诊了。
存储手机验证码:
手机验证码一般都具有时效性,可能是五分钟或者十分钟等等。可以通过给数据设置过期时间来完成这个功能。
String 发送验证码(String phoneNumber) {
String key = "shortMsg:limit:" + phoneNumber;
// 设置过期时间为 1 分钟(60 秒)
// 使用 NX,只在不存在 key 时才能设置成功
boolean r = Redis.执行命令:set(key, "1", "ex", 60, "nx");
if (r == false) {
// 说明之前设置过该手机的验证码了
long c = Redis.执行命令:incr(key);
if (c > 5) {
// 说明超过了一分钟 5 次的限制了
// 限制发送
return null;
}
}
// 说明要么之前没有设置过手机的验证码;要么次数没有超过 5 次
String validationCode = 生成随机的6位数的验证码();
String validationKey = "validation:" + phoneNumber;
// 验证码 5 分钟(300 秒)内有效
Redis.执行命令:set(validationKey, validationCode, "ex", 300);
// 返回验证码,随后通过手机短信发送给用户
return validationCode;
}
// 验证用户输入的验证码是否正确
boolean 验证验证码(String phoneNumber, String validationCode) {
String validationKey = "validation:" + phoneNumber;
String value = Redis.执行命令:get(validationKey);
if (value == null) {
// 说明没有这个手机的验证码记录,验证失败
return false;
}
if (value.equals(validationCode)) {
return true;
} else {
return false;
}
}
题外话:
业务决定计数,有些时候计数解决不了的问题,可以优化业务来实现。
比如12306购票软件:如果每早八点放出所有的高铁票,这个时候所有人都来抢票就会导致服务器压力直接拉满,使用一些常规技术手段去优化,效果也不明显;此时可以从业务上去优化进行分时段放票,将票分几个时间去放出,此时就不会导致这么多人抢票,大大减轻了服务器的压力。