redis学习总结

1. 入门

我们都知道redis是用来做缓存的一个工具,但是如果问你哪些业务场景下要用到缓存呢?

数据从使用的角度来分可以分成静态的数据,例如个人的基本信息呀,商品的类别信息等,这种数据访问频繁,但是改动却不频繁,必须做缓存减轻数据库的压力;
还有就是实时的动态的,例如同城好友的推荐,热门话题的推荐,这些带有个性化的数据,也就是需要根据基本数据进行推算的数据,由于基本数据不常变属性,同样的这种数据也可以使用缓存,减少推算的次数。

但是redis除了做缓存还可以做的就是利用本身的存储数据的数据结构的特点,做像排行榜这样的功能。

还有就是做计算器,常用来统计并发场景下的一些活跃的状态,例如,粉丝数,点赞数,个人主页浏览量呀,还有借阅数,下单数等等这些要经常加一减一的实时的动态的数据,也可以做成缓存,不然的话,如果并发量很大,数据库的压力就会很大,这时做成缓存在数据库不忙的时候,异步刷新到数据库,就可以大大减少数据库的访问压力。

redis:
是解决磁盘io性能低下和数据关系复杂的一种技术,也就是用内存存储数据并去除数据的关系。

可扩容可伸缩
大数据量下读写性能高
灵活的数据类型

除了redis还有哪些非关系型数据库:
memcache
Hbase
mangoDB

举一个模型列子:
在这里插入图片描述

常用的命令:
功能型命令:
清屏命令:
clear、cls
帮助信息命令:
help 命令名称
help @群组
退出命令:
quit
exit

操作后的提示信息:
在redis中,操作无异常的情况成功和失败的标识都是Integer
表示value为空就是nil
出异常就是error

2. 数据类型

2.1 数据类型介绍

五种:
五种怎么来的?
是根据业务需求来定义的。

数据类型指的是value,key永远是字符串

2.2 String类型

数字也是字符串,但是可当数字用
set key value --增改
get key --取
del key --删

添加/修改多个数据:
mset key1 value1 key2 value2 …
追加
append key value

取多个
mget key1 key2 …
取value的长度
strlen key(返回值是strlen)

扩展操作:

分表时保证id的唯一性,mysql不像Oracle具有sequence设定,所以mysql就要注意分表时怎么让表的id依旧保持唯一。
incr key :每次自增的数值(默认是1)
decr key : 自减1
incrby key 值: 指定自增值
decrby key 值: 指定自减值
还有一个特殊的
incrbyfloat key 小数值:指定自增的值,但是可以是小数。

set数据时同时指定改key的存活时间。
setex key seconds value

String类型的注意事项:

512mb(最大的数据量)
数字的最大值和long类型一致

key的命名规范

表名:主键名:主键值:字段名

2.3 hash类型

一个存储空间存放多个键值对数据
底层就是一个哈希表的结构
对应java中的hashset,双列集合
很明显这种数据结构就是存放一个普通javaBean最方便的结构。
一个key对应多个field and value

存一个field:
hset key field value
存多个field:
hmset key field1 value1 field2 value2 …

取一个field:
hget key field
取多个field:
hmget key field1 field2 …

全取:
hgetall key

删一个key:
hdel key
删一个field:
hget key field
删多个field:
hdel key field1 field2 …

获取哈希表中字段的数量:
hlen key

判断一个key中是否存在该字段
hexist key field

基于哈希的基本特征,hash类型有些扩展操作

获取所有的field:
hkeys key

获取所有的value:
hvals key

和String类型一样思路的自增操作
hincrby key field 指定值

注意事项

value只能是string,所以不存在嵌套

每一个key中只能存放2的23次方-1个键值对

切记,hash类型设计的初衷不是为了存储大量的对象,不可滥用.

切记,hgetall的效率很低,尽量别用.

hash常见的应用场景一:购物车

用户id作为key
商品id作为field
商品数量作为value

获取商品的数量: hget key field
商品数量的设置: hset key field + hincrby key field 指定值
删除某个商品: hdel key field1 field2 …
全选商品: hgetall key
获取商品种类量: hlen key
清空购车: hdel key
获取下单的商品id: hkeys key

现在仅仅是将数据存放到了redis中,并没有起到真正的加速购物车的呈现,因为商品信息还要二次查询数据库.

所以这套方案还要优化:
一个商品应该有两个键值对,而不是一个
第一个键值对就是如上的只保存数量, field就是商品id:num
第二个就要保存商品信息的json数据, field就是商品id:info
每次添加一个商品: hmset key 商品id:id value1 商品id:info value

hash常见的应用场景二:抢购

以商家id作为key
将商品id作为field
将参与抢购的商品数量作为对应的value
抢购时使用降值的方式控制产品数量

为什么能这样子设计,而不用考虑并发的问题呢?
因为redis速度够快而且是单线程的操作.

2.4 list类型

对数据的关注点是数据的顺序, 和一次性过来多个数据

是对String类型的直接升级

底层是使用的双向链表

为什么不用顺序表呢? 因为顺序表查询快, 但是插入和删除效率实在太低

存数据:
lpush key value1 …
rpush key value1 …

取:
lrange key start stop(范围取, stop可以用-1, 意思就是到结尾)
lindex key index (指定取)
取头一个并移除:
lpop key
rpop key
规定时间内获取并移除数据:
blpop key1 … 指定时间值
brpop key1 … 指定时间值

获取list的长度
llen key

扩展操作

删除list中某一value
lrem key count value
(list中value是可以重复多个的)

基于list的数据结构特点实现栈或者队列

就是
lpush key value1 …
配合
lpop key
实现左进左出,并且是后进的就会先出.

如果是配合rpop key
就是实现的左进右出, 并且是先进的先出.

基于list的数据结构特点实现消息队列

就是使用blpop指定取的时间范围,只要在这个时间范围内,有数据就取出并移除.

基于list的数据结构特点实现朋友圈点赞和消赞

点赞就是为一个朋友圈id创建list
key就是朋友圈id, 而每一个value就是点赞人,同时保留点赞顺序.

消赞利用lrem key count value
key就是朋友圈id
value同样是点赞人
count是value的个数(这里自然是一)

注意事项

同样的value的数据类型是String, 同样不存在嵌套的现象

每一个key的value个数是有限的, 最多只有2的32次方减一个

list可以辅助做分页,通常第一页就是从list中取, 第二页开始才是从数据库.

2.5 set类型

先理一下现在的数据结构
String可以存放一个字符串
hash可以存放一个对象(一堆键值对)
list可以存放一列有顺序的字符串

那如果现在的需求是要能像list一样存储大量的数据,又要像hash一样便于查询

于是有了set

其实就是将hash微微的变一下型, 使得value一直为空(nil), 我们只要field.

使得key中不再存放键值对, 只存放键

有人就说, 那这样不就还是list吗, 不一样, 首先hash的键有不可重复性, 其次它不维护顺序.

添加:
sadd key member1 member2 …

获取全部成员:
smembers key

删除成员:
srem key member1 member2 …

获取key中的成员总数
scard key

判断集合中是否包含指定数据
sismember key member

扩展操作

随机获取集合中指定数量的成员
srandmember key count

随机获取某个成员并移除
spop key

求两个集合的交并差集
sinter key1 key2
sunion key1 key2
sdiff key1 key2(得到key1中key2没有的成员)

求两个指定集合的交并差集并存储到另一个set
sinter key0 key1 key2
sunion key0 key1 key2
sdiff key0 key1 key2

将成员从一个集合转移到另一个集合
smove key1 key2 member

基于set数据结构特点的业务场景: 根据用户的爱好标签并随机推送该标签的内容

利用srandmember key count
随机的获取一个标签
(试想一下,随机推送并配合hash结构不就可以统计偏好标签了吗)

基于set数据结构特点的业务场景:展示共同关注

sinter key1 key2
sunion key1 key2
sdiff key1 key2(得到key1中key2没有的成员)
利用set的这些操作

基于set数据结构特点的业务场景: 统计用户的角色以及对应的业务权限

依赖于set不会重复的特点
每一个用户都应该有一个set存放自己的角色
而每一角色都应该有自己的set存放所有的权限
那么所有的角色权限的set的并集就是该用户的所有权限.
最后使用判断集合中是否包含指定数据
sismember key member操作就可以判断是否具有某一项权限

基于set数据结构特点的业务场景: 统计网站的访问量

这里引入几个概念:
PV: 网站被访问的次数, 刷新页面就会增
UV: 网站被不同用户访问的次数,通过cookie统计, 相同的用户用不同的ip访问, 不会增
IP: 网站被不同的ip地址访问,就会增,就算是同一个用户.

利用scard key就能统计

2.6 sorted_set类型

有没有一种数据结构, 自己能够实现一种排序的效果的

在set的结构基础上, 实现了sorted_set数据结构

每一个member都带着一个score

根据这个score就能对set中的member进行排序

注意score并不是数据

添加
zadd key score1 member1 …

获取全部数据
zrange key start stop [withscores]
zrevrange key start stop [withscore]

删除数据
zrem key member1 …

获取集合的数量
zcrad key
zcount key min max

集合交, 并操作
zinterstore 存放结果 操作数量 集合1 …(除了交并,还有一个score相加的操作, 这只是默认而已, 还有求交集的最大集什么的)
zunionstore 存放处 操作数量 集合1 …

由于sorted_set的特殊性
有一些关于score的特殊操作

按条件获取数据
zrangebyscore key min max [withscores] [limit]
zrevrangebyscore key max min [withscores]

按条件删除数据
zremrangebyrank key start stop(甚至拥有索引的概念)
zremrangebyscore key min max

扩展操作

获取该成员的索引(排名)
zrank key member
zrevrank key member

score值的获取和修改
zscore key member
zincrby key 指定值 member

注意事项

sorted_set的score值是有范围的

score保存的数据也可以是一个双精度的double值,基于双精度的浮点数的特征,可能有丢失精度,使用时要慎重。

score值是会根据key而被覆盖的。

2.7 数据类型实践案例

3. 通用命令

3.1 key有关

key使一个字符串,redis是通过的key获取的数据
那么
对于key自身的状态应该有相关的操作,例如删除,判断存在,获取类型等
对于key的有效性应该有相关的操作,例如有效期设定,判定是否有效,有效状态的切换等
对于key的快速查询操作,例如按指定的策略查询key

删除指定的key
del key

判断存在
exists key

获取key的类型
type key

为key设置有效期
expire key seconds
pexpire key milliseconds
expireat key timestamp(时间戳:在linux中一般用时间戳来控制)
pexpireat key milliseconds-timestamp

获取key的有效时间
ttl key (如果一个key不存在,返回值是-2;如果一个key存在,返回值是-1;如果设置了有限期,返回有效时间)
pttl key

切换key从失效性转换为永久性
persist key

查询key
keys pattern
在这里插入图片描述

为key改名
rename key newkey
renamenex key newkey (保险)

对key中元素排序
sort

其他的key操作
help @generic

3.2 数据库有关

解决key容易重复问题
redis为每一个数据库提供了16个数据库,编号从0-15
每一个数据库之间的数据相互独立

切换数据库
select index

其他操作
quit
ping
echo message

数据移动
move key db(注意:必须是这里有哪里没有)

数据清除
dbsize:看当前库里有多少key
flushdb:刷掉你现在的数据
flushall:所有数据

4. jedis

除了jedis还有
SpringData redis
lettuce
//明确哪一个数据库,说白了加载驱动呗
//创建连接
//操作数据库,说白了就是创建会话对象
//关闭资源
Jedis jedis = new Jedis(“127.0.0.1”, 6379); //redis要比mysql简单得多
jedis.set(“name”, “itdong”);
jedis.close();

jedis连接池
jedisPool:redis提供的

package com.itdong.utils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class JedisUtils {
    private static JedisPool jedisPool;

    static {
        //读取配置文件
        InputStream is = JedisUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
        //创建Properties对象
        Properties pro = new Properties();
        //关联文件
        try {
            pro.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取数据,设置到JedisPoolConfig中
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));
        config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle")));

        //初始化JedisPool
        jedisPool = new JedisPool(config,pro.getProperty("host"),Integer.parseInt(pro.getProperty("port")));
    }

    public static Jedis getJedis(){
        return jedisPool.getResource();
    }

    public static void main(String[] args) {
        Jedis resource = JedisUtils.jedisPool.getResource();
        System.out.println(resource);

    }
}

5. 持久化 – 从这里开始应该在Linux下学习

6. 配置信息

7. 事务

8. 集群

9. 企业级的解决方案

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值