提示:Ferao这位大哥对redis写的幽默风趣,简单明了,通俗易懂。强烈推荐–>redis详解(全)
本文部分内容借鉴于此,如有侵权,请联系删除!!!
提示:本文部分内容借鉴于此,如有侵权,请联系删除
!!!
如有想对redis了解的更加全面透彻,请查看Ferao写的redis详解(全)
包含redis的使用、安装、详解。
概括
应用场景
缓存(数据查询,短连接,新闻内容,商品内容等等)
聊天室的在线好友列表
任务队列。(秒杀,抢购,12306等等)
应用排行榜
网站访问统计
数据过期处理
分布式集群架构中的session分离
基础命令
dbsize 当前redis库的大小
select 7 切换redis库
keys * 当前redis库存储的所有key
flushdb 清除当前redis库中所有数据
flushall 清除全部redis库中数据
config get requirepass 当前使用的密码
set requirepass "123456"设置密码
auth 123456 输入密码
info replication 查看当前库的信息
bind 127.0.0.1 绑定的ip
protected-mode yew 保护模式
port 6379 端口设置
通用 GENERAL
Daemonize yes 以守护进程的方式进行,默认是no,开发者需要自己开启为yes
pidfile /var/run/redis_6379.pid
如果以后台的方式运行,我们就需要制定一个pid文件
loglevel notice 日志水平(debug、verbose、notice、warning)
logfile "" 日志的文件位置名
databases 16 数据库的数量,默认是16个数据库
always-show-logo yes 是否总是显示Logo
快照
# 持久化,在规定时间内执行了多少次操作,则会持久化到文件rdb.aof
# redis是内存数据库,如果没有持久化,那么数据断点及失
save 900 1 如果900s内,至少有一个Key进行了修改,redis进行持久化操作
save 300 10 如果300s内,至少10个key进行了修改,redis进行持久化操作
save 60 10000 如果60s内,至少10000个key进行了修改,redis进行进行持久化操作
stop-writes-on-bgsave-error yes 持久化如果出错,是否还需要继续工作
rdbcompression yes 是否压缩rdb文件,需要消耗一些cpu资源
rdbchecksum yes 保有rdb文件的时候,进行错误的检查校验
dir ./ 文件保存的目录
SECURITY(安全)
requirepass 123456
CLIENTS(限制)
maxclients 10000 设置能连接上redis的最大客户端的数量
maxmemory <bytes> redis配置最大的内存容量
maxmemory-policy noeviction
内存到达上限之后的处理策略
1.volatile-1ru: 只对设置了过期时间的Key进行LRU(默认值)
2.allkeys-1ru 删除1ru算法的key
3.volatile-random 随机删除即将过期key
4.allkeys-random 随机删除
5.volatile-ttl 删除即将过期的
6.noeviction 永不过期,返回错误
APPEND ONLY MODE (aof配置)
appendonly no 默认是不开启aof模式的,默认是使用rdb方式持久化的,在大部分庆康下,rdb够用
appendfilename "appendonly.aof"
持久化的文件的名字
# appendfsync always
每次修改都会sync,消耗性能
appendfsync everysec
每次执行一次sync,可能会丢失这1s的数据
# appendfsync no
不执行sync,这个时候操作系统自己同步数据,速度最快
字符串类型(String)
存储 set key value
获取 get key
删除 del key
哈希类型(map格式)
存储 hset key field value
获取
获取指定的field对应的值 hget key field
获取所有的field和value hgetall key
删除 hdel key field
列表类型(list,linkedlist格式)
存储
将元素加入列表左表 lpush key value
将元素加入列表右边 rpush key value
范围获取 lrange key start end
删除
删除列表最左边的元素,并将元素返回 lpop key
删除列表最右边的元素,并将元素返回 rpop key
集合类型(set)
存储 sadd key value
获取所有元素 smembers key
删除集合中某个元素 srem key value
有序集合类型(sortedset)
存储 zadd key score value
获取 zrange key start end
删除 zrem key value
-------------------------------------------------------
通用命令
查询所有键 key *
获取键对应的value类型 tepe key
删除指定的Key,value del key
1.redis存储的是:key,value 格式的数据,其中Key都是字符串,value有5种不同的数据结构
2.列表类型支持重复元素
3.redis列表是简单的字符串列表,按照插入顺序排序,操作者可以添加一个元素到列表头部(左边)或者尾部(右边)
4.集合类型不允许重复元素
5.有序集合类型,不允许重复元素,且元素有顺序,每个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序。
1.字符串(String)
一个键最大能存储512M
最基本的类型,一个key对应一个value。
适用:任何数据,只要不超过512M.
2. 哈希(Hash)
Redis Hash 是一个 string 类型的 field 和 value 的映射表。
底层使用哈希表结构实现数据存储。
适用:适合存储对象,并支持对象的存储,读取,修改。
3. 列表(List)
字符串列表,有序,按照插入顺序排序,可以在头部或尾部插入。
底层使用双向链表实现存储结构。
适用:最新消息排序或任务队列等。
4. 集合(Set)
string类型元素的集合,集合元素是无序的且不重复的,只存储键,不存储值,值为nil。
底层使用哈希表实现存储结构。(其实就是只有键没有值的哈希(Hash))。
适用:共同好友(集合提供了求交集、并集、差集等操作)
5. 有序集合(Sorted Set)
string类型元素的集合,集合元素是有序的且不重复的,只存储键,不存储值,值为nil。
每个元素都会关联一个double类型的分数(score)可以重复,通过分数来为集合中的成员进行从小到大的排序。
底层使用哈希表实现存储结构,在此基础上添加排序字段(score)。
适用:带有权重的,如: 排行榜(游戏,新闻)。
问题1
redis数据都是在内存中,内存的空间资源是有限的,不能无节制的这么存下去,不然迟早会将内存填满。
解决1
给缓存内容设置一个超时时间,具体设置多长交给应用程序们去设置,我要做的就是把过期了的内容删除掉,及时腾出空间就行了。
问题2
超时时间有了,该在什么时候去干这个清理的活呢?
解决2
最简单的就是定期删除,100ms就做一次,一秒钟就是10次!
问题3
清理的时候也不能一口气把所有过期的都给删除掉,这里面存了大量的数据,要全面扫一遍的话那不知道要花多久时间,会严重影响后面的请求,降低效率!
解决3
时间紧任务重,只好随机选择一部分来清理,能缓解内存压力就行了。
问题4
有些占用内存较大的键值运气比较好,每次都没有被随机算法选中,每次都能幸免于难,这可不行,这些长时间过期的数据一直霸占着不少的内存空间。
解决4
原来定期删除的基础上,又加了一招:那些原来逃脱随机选择算法的键值,一旦遇到查询请求,发现已经超期了,立即删除。
这种方式因为是被动式触发的,不查询就不会发生,所以也叫惰性删除!
问题5
可是,还是有部分键值,既逃脱了随机选择算法,又一直没有被查询,导致它们一直逍遥法外!而于此同时,可以使用的内存空间却越来越少。
而且就算退一步讲,我能够把过期的数据都删除掉,那万一过期时间设置的很长,还没等到我去清理,内存就吃满了,一样要吃枣药丸.
解决5
使用内存淘汰策略
提供了8种策略供应用程序选择,用于我遇到内存不足时该如何决策:
名称 | 作用 |
---|---|
noeviction | 返回错误,不会删除任何键值 |
allkeys-lru | 使用LRU算法删除最近最少使用的键值 |
volatile-lru | 使用LRU算法从设置了过期时间的键集合中删除最近最少使用的键值 |
allkeys-random | 从所有key随机删除 |
volatile-random | 从设置了过期时间的键的集合中随机删除 |
volatile-ttl | 从设置了过期时间的键中删除剩余时间最短的键 |
volatile-lfu | 从配置了过期时间的键中删除使用频率最少的键 |
allkeys-lfu | 从所有键中删除使用频率最少的键 |
问题1
当查询的数据不存在,就要去数据库中查询,因为不存在,redis也没法缓存,导致同样的请求来了每次都要去数据库中查询一次,这就是常说的缓存穿透
。
解决
使用布隆过滤器
,布隆过滤器
擅长从超大的数据集中快速告诉你查找的数据存不存在(布隆过滤器返回存在,其实有可能是不存在的,不过它要是返回不存在的话,那就一定不存在)。
问题1
如果有一个热点数据到了过期时间,被删掉了,不巧的是随后就有对这个数据的大量查询请求来了,redis已经删了,所以大量请求将会访问数据库,造成数据库压力过大,甚至宕机。这就是常说的缓存击穿
和缓存雪崩
。
解决
设置了热点数据永不过期,还把键值的过期时间随机了一下,别让大量数据集体失效。
A 请求先将数据库的数据更新为 1,然后在更新缓存前,请求 B 将数据库的数据更新为 2,紧接着也把缓存更新为 2,然后 A 请求更新缓存为 1。
此时,数据库中的数据是 2,而缓存中的数据却是 1,出现了缓存和数据库中的数据不一致的现象
A 请求先将缓存的数据更新为 1,然后在更新数据库前,B 请求来了, 将缓存的数据更新为 2,紧接着把数据库更新为 2,然后 A 请求将数据库的数据更新为 1。
此时,数据库中的数据是 1,而缓存中的数据却是 2,出现了缓存和数据库中的数据不一致的现象。
无论是「先更新数据库,再更新缓存」,还是「先更新缓存,再更新数据库」,这两个方案都存在并发问题,当两个请求并发更新同一条数据的时候,可能会出现缓存和数据库中的数据不一致的现象。
因此在更新数据时,不更新缓存,而是删除缓存中的数据。然后,到读取数据时,发现缓存中没了数据之后,再从数据库中读取数据,更新到缓存中。这个方法是叫 Cache Aside 策略
,中文是叫旁路缓存策略
。
读策略的步骤:
方案3: 先删除缓存,再更新数据库
请求A先将缓存删除,然后在更新数据库前,B 请求来了,查询缓存发现未命中后,会从数据库中读取到值为 20,并将缓存的数据更新为 20,然后请求 A 继续更改数据库, 将数据更新为 21。
此时,数据库中的数据是21,而缓存中的数据却是 20,出现了缓存和数据库中的数据不一致的现象。
假如数据在缓存中不存在,请求 A 读取数据时从数据库中查询到年龄为 20,在未写入缓存中时另一个请求 B 更新数据。它更新数据库中的年龄为 21,并且清空缓存。这时请求 A 把从数据库中读到的年龄为 20 的数据写入到缓存中。
此时,缓存中的数据是 20(旧值),数据库中是 21(新值),出现了缓存和数据库中的数据不一致的现象。
从上面的理论上分析,先更新数据库,再删除缓存也是会出现数据不一致性的问题,但是在实际中,这个问题出现的概率并不高。
因为缓存的写入通常要远远快于数据库的写入,所以在实际中很难出现请求 B 已经更新了数据库并且删除了缓存,请求 A 才更新完缓存的情况。 所以,「先更新数据库 + 再删除缓存」的方案,是可以保证数据一致性的。
而一旦请求 A 早于请求 B 删除缓存之前更新了缓存,那么接下来的请求就会因为缓存不命中而从数据库中重新读取数据,所以不会出现这种不一致的情况。为了确保万无一失,还给缓存数据加上了 「过期时间」 ,就算在这期间存在缓存数据不一致,有过期时间来兜底,这样也能达到最终一致。
先更新数据库, 再删除缓存」其实是两个操作,前面的所有分析都是建立在这两个操作都能同时执行成功,而这次的问题就在于,在删除缓存(第二个操作)的时候失败了,导致缓存中的数据是旧值。好在之前给缓存加上了过期时间,所以才会出现客户说的过一段时间才更新生效的现象,假设如果没有这个过期时间的兜底,那后续的请求读到的就会一直是缓存中的旧数据,这样问题就更大了。
如何保证「先更新数据库 ,再删除缓存」这两个操作能执行成功?
举个例子,来说明下。
应用要把数据 X 的值从 1 更新为 2,先成功更新了数据库,然后在 Redis 缓存中删除 X 的缓存,但是这个操作却失败了,这个时候数据库中 X 的新值为 2,Redis 中的 X 的缓存值为 1,出现了数据库和缓存数据不一致的问题。
那么,后续有访问数据 X 的请求,会先在 Redis 中查询,因为缓存并没有 诶删除,所以会缓存命中,但是读到的却是旧值 1。其实不管是先操作数据库,还是先操作缓存,只要第二个操作失败都会出现数据一致的问题。
问题原因知道了,该怎么解决呢?有两种方法:
重试机制
我们可以引入消息队列,将第二个操作(删除缓存)要操作的数据加入到消息队列,由消费者来操作数据。
- 如果应用删除缓存失败,可以从消息队列中重新读取数据,然后再次删除缓存,这个就是重试机制。当然,如果重试超过的一定次数,还是没有成功,我们就需要向业务层发送报错信息了。
- 如果删除缓存成功,就要把数据从消息队列中移除,避免重复操作,否则就继续重试。
订阅 MySQL binlog,再操作缓存
「先更新数据库,再删缓存」的策略的第一步是更新数据库,那么更新数据库成功,就会产生一条变更日志,记录在 binlog 里。
于是我们就可以通过订阅 binlog 日志,拿到具体要操作的数据,然后再执行缓存删除,阿里巴巴开源的 Canal 中间件就是基于这个实现的。
Canal 模拟 MySQL 主从复制的交互协议,把自己伪装成一个 MySQL 的从节点,向 MySQL 主节点发送 dump 请求,MySQL 收到请求后,就会开始推送 Binlog 给 Canal,Canal 解析 Binlog 字节流之后,转换为便于读取的结构化数据,供下游程序订阅使用。
下图是 Canal 的工作原理:
所以,如果要想保证「先更新数据库,再删缓存」策略第二个操作能执行成功,我们可以使用「消息队列来重试缓存的删除」,或者「订阅 MySQL binlog 再操作缓存」,这两种方法有一个共同的特点,都是采用异步操作缓存。
redis是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失。所以redis提供了持久化功能,且分为RDB、AOF两种方式
RDB模式原理
在指定的时间间隔内将内存中的数据库快照写入磁盘,再次恢复时再将快照文件直接读到内存里。
在此期间,redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何io操作的。
这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。但RDB存在缺陷是最后一次持久化的数据可能丢失。当我们安装好的redis,其默认持久化模式是RDB模式【一般情况下不需要修改】,RDB保存的文件是dump.rdb。都是在redis配置文件中快照中进行配置的。
简单可记住,RDB默认方式,不需要进行配置,默认就使用这种机制,在一定的间隔时间中,检测key的变化情况,然后持久化数据。
触发机制
三种情况下会触发RDB规则:
恢复机制
只需要将rdb文件放在redis启动目录下即可,redis启动的时候回自动检测dump.rdb,恢复数据。
相关配置
#如果至少有一个键更改,在900秒(15分钟)后保存
save 900 1 after 900 sec (15 min) if at least 1 key changed
save 300 10 after 300 sec (5 min) if at least 10 keys changed
save 60 10000 after 60 sec if at least 10000 keys changed
RDB模式的优势是适合大规模的数据恢复、且对数据的完整性不高。但与之相对,不足之处是需要一定的时间间隔进程操作,如果redis意外宕机,这个最后一次修改数据就没有了,且fork进程的时候,会占用一定的内存空间。
AOF模式原理
【append only file】将开发者操作redis的所有命令都记录下来,恢复的时候就把文件内所有写的操作执行一遍。
它以日志的形式来记录每个写操作,将redis执行过的所有指令记录下来 (读操作不记录),且只许追加文件但不可以改写文件。 当redis启动之初会读取该文件重新构建数据。换句话说,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
aof模式保存的文件名是appendonly.aof。在redis配置中,默认是不开启的,开发者需要手动配置,只需要将appendonly改为yes即可开启、再进行重启redis,就可以生效了。
如果aof文件有错位,这时候redis是启动不起来的,开发者需要修复aof文件,redis为开发者提供了一个工具,也就是bin目录下的redis-check-aof,开发者只需在redis bin目录下执行redis-check-aof --fix appendonly.aof即可
如果文件正常了,重启后就可以直接恢复了。
简单理解aof是日志记录的方式,可以记录每一条命令的操作。可以每一次命令操作后,持久化数据
重写规则
aof默认就是文件的无限追加,文件会越来越大,如果aof文件大于64m,redis会fork一个新的进程来将文件进行重写。
相关配置
appendfsync no (关闭aof,不进行持久化)
appendonly yes (开启aof)
appendfsync always (每一次操作都进行持久化)
appendfsync everysec (每间隔一秒进行一次持久化)
AOF模式的优势是每一次修改都同步时,文件的完整性会更好;每秒同步一次方式时,可能会丢失1s的数据;从不同步时,效率最高。
相对于数据文件来说,AOF文件远远大于RDB;修复的速度也比RDB慢;AOF运行效率要比RDB慢,所以redis默认的配置就是RDB持久配置
1.redis是一个内存数据库,当redis 服务器重启,获取电脑重启,数据会丢失,我们可以将redis 内存中的数据持久化保存到硬盘的文件中。
2.修改后,重启redis服务器,并制定配置文件的名称。
同时开启两种持久化方式
在这种情况下,当redis重启的时候会优先载入aof文件来恢复原始的数据,因为在通常情况下aof文件保存的数据要比rdb文件保存的数据要完整,而rdb的数据不实时。
同时使用两者时服务器重启也只会找aof文件,那要不要只使用aof呢,这里建议不要,因为rdb更适合用于备份数据库(aof在不断改变不好备份),快速重启时,而且不会有aof可能潜在的bug,留着作为一个万一的手段。
性能建议
因为rdb文件只用作后备用途,建议只在Slave上持久化rdb,而且只要15分钟备份一次就够了,只保留save 900 1 这一条规则
扩展
1.RDB持久化方式能够在指定的时间间隔内对开发者的数据进行快照
2.AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会
重新执行这些命令来恢复原始的数据,
AOF命令以redis协议追加保存每次写的操作到文件末尾,
redis还能对aof文件进行后台重写,使得 aof文件的体积不至于过大
3.只做缓存,如果开发者希望数据在服务器运行的时候存在,开发者可以不适用任何持久化
本质
一组命令的集合。一个事务中的所有命令都会被序列化,在事务执行过程中,
会按照顺序执行。
特性
一次性、顺序性、排他性。
注意
1、redis事务没有隔离级别的概念。所有的命令在事务中,并没有直接执行,
只有发起执行命令的时候才会执行(Exec)
2、redis单条命令是保证原子性的,但是事务不保证原子性
操作
开启事务(multi)
命令入队(正常命令集合)
执行事务(exec)
所有情况
正常执行事务
放弃事务
编译型异常(代码有问题命令出错,事务中所有的命令都不会被执行)
运行时异常(IO异常,如果事务队列中存在逻辑问题,那么执行命令的时候,
其他命令是可以正常执行的,错误命令抛出异常)
基础
jedis是一款java操作redis的工具,使用需要引入jedis的Jar包
示例
public void redisTest(){
//获取连接
Jedis jedis = new Jedis("127.0.0.1",6379);
//输入密码
jedis.auth("123456");
//选择操作库
jedis.select(0);
System.out.println("连接成功");
System.out.println("服务正在运行: "+jedis.ping());
//查看库里所有Key
Set<String> keys = jedis.keys("*");
for (String key : keys) {
System.out.println(key);
}
//查看指定Key类型
System.out.println(jedis.type("myhash"));
System.out.println(jedis.type("mysort"));
System.out.println(jedis.type("mylist"));
System.out.println(jedis.type("name"));
System.out.println(jedis.type("myset"));
//操作
jedis.set("username","zhangsan");
jedis.lpush("ferao",string); //从左边存
jedis.rpush("ferao",string,string1,string2); //从右边存
jedis.hset("user","name","lisa");
jedis.hmset("addr_lib", map);
jedis.sadd("myset","java","php","c++");
jedis.zadd("mysortedset",3,"lisea");
//获取
String username = jedis.get("username");
List<String> mylist = jedis.lrange("ferao",0,-1);
String username = jedis.hget("user","name");
Set<String> myset = jedis.smembers("myset");
Set<String> mysortedset = jedis.zrange("mysortedset",0,-1);
//获取某类别中全部
//获取hash类别中所有map中的元素
Map<String,String> user = jedis.hgetAll("user");
Set<String> keySet = user.KeySet();
for(String key : keySet){
String value= user.get(key);
System.out.println(key +":" + value);
}
//关闭连接
jedis.close();
}
jedis.flushDB() 清空数据
boolean jedis.exists(String key) 判断某键是否存在
jedis.set(String key,String value) 新增键值对(key,value)
Set<String> jedis.keys("*") 获取所有key
jedis.del(String key) 删除键为key的项
jedis.expire(String key,int i) 设置键为Key的项过期时间为i秒
int jedis.ttl(String key) 获取键为Key的项剩余生存时间(s)
jedis.persist(String key) 移除键为Key的项的生存时间限制
jedis.type(String key) 查看键为Key的项所对应value的
数据类型
jedis.set(String key,String value) 增加(或覆盖)数据项
jedis.setnx(String key,String value) 增加数据项(不覆盖),重复不插入
jedis.setex(String key,int t,String value) 增加数据项并设置有效时间
Jedis.del(String key) 删除键为Key的数据项
Jedis.get(String key) 获取键为Key对应的value
jedis.append(String key,String s) 在key对应的value后面扩展字符s
jedis.mset(String k1,String v1,String k2,String v2..)
增加多个键值对
String[] jedis.mget(String k1,String k2...)
获取多个key对应的value
Jedis.del(new String[]{String k1,String k2..})
删除多个Key对应的数据项
String jedis.getSet(String key,String value)
获取key对应value并更新value
jedis.lpush(String key,String v1,String v2..)
添加一个list列表
jedis.lpush(String key,String vn) 在key值对应的列表左插入一个元素
jedis.lrange(String key,int i,int j) 获取key对应的列表,区间在[i,j]
jedis.lrem(String key,int num,String val) 删除指定元素val,个数num
jedis.ltrim(String key,int i,int j) 删除列表区间[i,j]之外的元素
jedis.lpop(String key) key对应的列表左出栈一个元素
jedis.rpush(String key,String Vn) key对应的列表右插入一个元素
jedis.rpop(String key) key对应的列表右出栈一个元素
jedis.lset(String key,int index,String val) 修改Key对应的列表指定下标元素
jedis.llen(String key) 获取key对应的列表长度
jedis.lindex(String key,int index) 获取key对应的列表下标为index值
jedis.sort(String key) key对应列表内的元素从小到大排序
jedis.sadd(String key,String v1,String v2..)
添加一个集合
jedis.smembers(String key) 获取key对应的集合所有元素
jedis.srem(String key,String val) 删除一个值为val的元素
jedis.srem(String key,String v...) 删除值为v1,v2..的元素
jedis.spop(String key) 随机弹出集合中一个元素
jedis.scard(String key) 获取set中元素个数
jedis.smove(String k1,String k2,String val)
将元素val从集合k1剪贴到k2
jedis.sinter(String k1,String k2) 获取集合k1和集合k2的交集
jedis.sunion(String k1,String k2) 获取集合k1和集合k2的并集
jedis.sdiff(String k1,String k2) 获取集合k1和集合k2的差集
jedis.hmet(String key,Map map) 同时将多个field-value设置到
哈希表中,此命令会覆盖哈希表中
已存在的字段,如果不存在创建
jedis.hset(String key,String key,String value)
往hash插入一个(k-v)元素
jedis.hgetAll(String key) 获取hash的所有(k-v)元素
jedis.hkeys(String key) 获取hash所有元素的key
jedis.hvals(String key) 获取hash所有元素的value
jedis.hincrBy(String key,String k,int i) 把哈希中k对应的元素val+=i
jedis.hdecrBy(String key,String k,int i) 把hash中k对应的元素val-=i
jedis.hdel(String key,String k1,String k2..)
从hash中删除一个或多个元素
jedis.hlen(String key) 获取hash中元素个数
jedis.hexists(String key,String k1) 判断hash是否存在k1对应元素
jedis.hmget(String key,String k1,String k2..)
获取hash中一个或多个元素value
jedis.zadd(String key,Map map) 添加一组ZSet集合
jedis.hset(String key,int score,String val) 插入一个元素(Score-Val)
jedis.zrange(String key,int i,int j) 获取ZSet中下标[i,j]区间元素
jedis.zrangeWithScores(String key,int i,int j)
获取ZSet里sore[i,j]区间元素
jedis.zscore(String key,String value) 获取ZSet里val为value元素
的score
jedis.zrank(String key,String value) 获取ZSet里val为value元素的
score排名
jedis.zrem(String key,String value) 删除ZSet里val为value的元素
jedis.zcard(String key) 获取ZSet的元素个数
jedis.zcount(String key,int i,int j) 获取ZSet中score在[i,j]区间
元素个数
1. 关系型数据库
关系型数据库 Mysql、Oralce
特点 数据之间有关联
数据存储在硬盘上
效率 操作关系型数据库非常耗时
2. 非关系型数据库
非关系型数据库 redis、hbase
存储 key:value
特点 数据之间没有关联关系
数据存储在内存中
缓存思想 从缓存中获取数据,有数据时,直接返回
没有数据时,从数据库中查询,将数据放
入到缓存,返回数据
1.关系型数据库与非关系型数据库是互补的关系
2.通常情况下使用关系型数据库,在适合使用NOSQL的时候使用NOSQL数据库,让NOSQL数据库对关系型数据库的不足进行弥补
3.一般会将数据存储在关系型数据库中,在nosql数据库中备份存储关系型数据库的数据。
3. 主流的NOSQL产品
相关产品
Tokyo Cabinet/Tyrant ,Redis ,Voldmort , Berkeley DB
典型应用
内容缓存,主要用于处理大量数据的高访问负载
数据模型
一系列键值对
优势
快速查询
劣势
存储的数据缺少结构化
相关产品
Cassandra, HBase ,Riak
典型应用
分布式的文件系统
数据模型
以列簇式存储,将同一列数据存在一起
优势
查找速度快,可扩展性强,更容易进行分布式扩展
劣势
功能相对局限
相关产品
CouchDB,MongoDB
典型应用
Web应用(与key-value类似,Value是结构化的)
数据模型
一系列键值对
优势
数据结构要求不严格
劣势
数据结构要求不严格
nosql
阿里巴巴架构演进
nosql数据模型
Nosql四大分类
CAP
BASE
Redis入门
Redis安装(WIndows & Linux服务器)
五大基本数据类型
String
List
Set
Hash
ZSet
三大特殊数据类型
geo
hyperloglog
bitmap
Redis配置详解
Reids持久化
RDB
AOF
Redis事务操作
Redis实现订阅发布
Redis主从复制
Redis哨兵模式(现在公司中所有的集群都用哨兵模式)
缓存穿透及解决方案
缓存击穿及解决方案
缓存雪崩及解决方案
基础API之Jedis详解
Springboot集成Redis操作
Redis的实践分析