redis
NOSQL(not only SQL)数据库
Jedis是Redis在Java中的常用客户端(依赖包),提供多种方法操作redis
数据类型
类型 结构
string key(string) value(string)
hash key(string) fieId value (map)
list key(string) value(双向链表,有序可重复)
set key(string) value(无序列表,无序不可重复)
zset key(string) value(有序不可重复)
key的定义要谨慎:
因为redis中数据是可以根据key值覆盖的
一般定义规则:表名
通用命令(方法)
keys 相当于list,后面可以接key值,相当于模糊查询
expire 设置key的生存时间,即在多少秒后自动删除
redis事务
mulit 开启事务
exec 取出队列中的命令去执行
discard 清除命令队列,退出事务状态
watch 监控某个或多个key进行监控,如果监控key变化时,事务就不会执行
unwatch 解除监控
以上方法用于保证多个redis命令的原子性discard、watch、unwatch等方法用于保证多个redis命令的原子性
redis不支持事务回滚,因此不常用事务,原因:
1.redis错误只有语法错误或者类型错误,这两种错误在开发阶段都是可以预见的
2.redis为了性能方面忽略了事务回滚
数据分类
1. DB更新后,Redis缓存中的数据就要马上清除,以保证将来缓存中的数据与DB中的绝对一致性(一般使用注解方式实现)
2. 对数据准确性要求不高,这类数据只要与DB中差别不大就可以了,所以这类数据一般会设置过期失效(一般使用API方式实现)
高并发下可能出现的问题
(本质:请求直接绕过redis直接访问数据库,给予数据库压力)
1. 缓存穿透,当从DB中查询结果为null时有可能出现缓存穿透的问题(大量请求直接访问DB)
解决方案:在redis中为null的结果赋予默认值
2. 缓存雪崩,当缓存中的某些缓存在同一很短的时段内几乎同时到期,此时会引发缓存雪崩(大量请求直接访问DB)
解决方案:提前规划好系统中所有缓存的到期时间
3. 热点缓存,当某一个缓存的有效期到达时(缓存没有重新从数据库返回数据时,大量请求直接访问DB),其有可能引发热点缓存问题
解决方案:双重检测锁机制
为什么使用redis作为缓存
减轻数据库压力
提高性能
一般来说数据库操作遵循82定律
写入操作占20%
读取操作占80%
缓存发展历史
一开始用static HashMap做缓存
后来用Ehcache,检索速度很快,JVM缓存,缺点在于占用了java程序的内存、CPU,
程序重启时缓存数据丢失,大量查询占用Java程序资源
然后,redis出现了
持久化机制
RDB(重启时重新将持久化数据载入到Redis中,有部分数据没有处理就可能丢失)
AOF(重启时重新执行相关指令,恢复慢)
AOF混合机制,集合上述优点
4.x版本,新版本
Redi历史(发展方案)
- 由于缺乏高可用机制,推出Redis主从机制,主机写入,从机读取,
- 由于宕机时需要人工切换从机转主机,引入哨兵机制,类似zookeeper的心跳机制,主机宕机时哨兵通过投票选举新主机,多数的为主机,因此要奇数个数哨兵,缺点网络波动误判主机已死,可能出现多主机
- 由于主节点受QPS(每秒查询率)限制,同时受木桶效应影响,存储量受内存最小的机器决定,因此要采用Redis代理集群
- 由于代理层需要处理所有请求,服务注册和监听,成为了项目新的瓶颈因此代理集群方式被放弃
- 分布式中间件代理模式
Twemproxy,代理集群,代表新浪微博,目前因业务量过大还没有更换机制
Codis,代表知乎,通过分片式算法,
Redis-cluster,去中心化完美代替代理式集群,依赖于zookeeper,最少6台机器实现3主3从集群