java相关之Redis关系型数据库 自学篇

Redis

数据库分类

关系型数据库

Oracle,MySQL,SqlServer,DB2

NoSQL数据库

NoSQL最常见的解释是“non-relational”, “Not Only SQL”也被很多人接受。NoSQL仅仅是一个概念,泛指非关系型的数据库,区别于关系数据库,它们不保证关系数据的ACID特性。NoSQL是一项全新的数据库革命性运动,其拥护者们提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入。

NoSQL_百度百科

非关系型数据库特点

1.数据模型比较简单.(主要) 2.需要灵活性更强的应用系统 3.对数据库性能要求较高(主要) 4.不需要高度的数据一致性(主要) 5.对于给定key,比较容易映射复杂值的环境.

与关系型数据库的区分

常见的关系型数据库和非关系型数据及其区别_aaronthon的博客-CSDN博客_关系型数据库和非关系型区别

关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织 优点: 1、易于维护:都是使用表结构,格式一致; 2、使用方便:SQL语言通用,可用于复杂查询; 3、复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。 缺点: 1、读写性能比较差,尤其是海量数据的高效率读写; 2、固定的表结构,灵活度稍欠;

3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。

非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。 优点: 1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。 2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘; 3、高扩展性; 4、成本低:nosql数据库部署简单,基本都是开源软件。

缺点: 1、不提供sql支持,学习和使用成本较高; 2、无事务处理; 3、数据结构相对复杂,复杂查询方面稍欠。

认识Redis

Redis简介:

是以key-value形式存储,和传统的关系型数据库不一样.不一定遵循传统数据库的一些基本要求.(非关系型的,分布式的,开源的,水平可拓展的)

优点:

对数据高并发读写(直接是内存中进行读写的) ​ 对海量数据的高效率存储和访问 ​ 对数据的可拓展性和高可用性. ​ 单线程操作,每个操作都是原子操作,没有并发相关问题(redis 6)

缺点:

redis(ACID处理非常简单) ​ 无法做太复杂的关系数据库模型

Redis是以key-value store存储. 键可以包含:(string)字符串,哈希,(list)链表,(set)集合,(zset)有序集合.这些数据集合都指出push/pop,add/remove及取交集和并集以及更丰富的操作.redis支持各种不同方式排序,为了保证效率,数据都是缓存在内存中.它可以从周期性的把更新的数据写入到磁盘或者把修改操作写入追加的文件中.

redis定位是缓存, 提高数据读写速度, 减轻对数据库存储与访问压力

redis的优势

性能极高 – Redis能支持超过 10W次每秒的读写频率。 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。 原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。 丰富的特性 – Redis还支持 publish/subscribe(发布/订阅), 通知, key 过期等等特性。

下面是官方的bench-mark数据: 测试完成了50个并发执行100000个请求。 设置和获取的值是一个256字节字符串。 Linuxbox是运行Linux2.6,这是X3320Xeon2.5ghz。 文本执行使用loopback接口(127.0.0.1)。 结果:读的速度是110000次/s,写的速度是81000次/s。

谁在用redis

比较著名的公司有: github、blizzard、stackoverflow、flickr

国内 新浪微博(全球最大的redis集群) 2200+亿 commands/day 5000亿Read/day 500亿Write/day 18TB+ Memory 500+ Servers in 6 IDC 2000+instances 淘宝 腾讯微博

怎么学redis

redis在线入门 : Try Redis redis 中文资料站: CRUG网站 Redis 教程 | 菜鸟教程

redis的安装

傻瓜式安装,下一步,下一步就可以了

Redis默认端口是: 6379

安装好后会自动启动服务器,并且没有密码

进入到安装目录下,使用cmd命令行运行redis-cli.exe程序,出现下面界面表示安装成功

数据类型

String类型

String类型包含多种类型的特殊类型,并且是二进制安全的.比如序列化的对象进行存储,比如一张图片进行二进制存储.,比如一个简单的

Map<String, String> map

map.put("name", Json.toJsonString(user));

类型命令 key 参数数据

set key value -> 存入键值对 get key -> 根据键取出值

incr key -> 把值递增1 decr key -> 把值递减1

del key -> 根据键删除键值对

setex key timeout value -> 存入键值对,timeout表示失效时间,单位s

ttl key->可以查询出当前的key还剩余多长时间过期

setnx key value -> 如果key已经存在,不做操作, 如果key不存在,直接添加

incrby key num -> 偏移值 mset k1 v1 k2 v2 ... -> 批量存入键值对 mget k1 k2 ... -> 批量取出键值 append key 'value' -> 原值后拼接新内容 setnx key value -> 存入键值对,键存在时不存入 setex key timeout value -> 存入键值对,timeout表示失效时间,单位s ttl ->可以查询出当前的key还剩余多长时间过期 setrange key index value -> 修改键对应的值,index表示开始的索引位置

应用场景

计数器:许多运用都会使用redis作为计数的基础工具,他可以实现快速计数、查询缓存的功能, 同时数据可以异步落地到其他的数据源。 如:视频播放数系统就是使用redis作为视频播放数计数的基础组件。

incr viewnum 1

共享session:出于负载均衡的考虑,分布式服务会将用户信息的访问均衡到不同服务器上, 用户刷新一次访问可能会需要重新登录,为避免这个问题可以用redis将用户session集中管理, 在这种模式下只要保证redis的高可用和扩展性的,每次获取用户更新或查询登录信息

hsah类型

Hash类型是String类型的field和value的映射表.或者说是一个String集合.它特别适合存储对象,相比较而言,讲一个对象存储在Hash类型里要比存储在String类型里占用更少的内存空间,并方便存储整个对象 Mp<string, Map<string, ?>> map hset key hashkey hashvalue -> 存入一个hash对象 hget key hashkey -> 根据hash对象键取去值 hexists key hashkey -> 判断hash对象是含有某个键 hdel key hashkey -> 根据hashkey删除hash对象键值对 hincrby key hashkey 递增值 -> 递增hashkey对应的值 hlen key -> 获取hash对象键的数量 hkeys key -> 获取hash对象的所有键 hvals key -> 获取hash对象的所有值 hgetall key -> 获取hash对象的所有数据 同样有hsetnx,其作用跟用法和setnx一样

list类型

Redis中的List类似Java中的queue,也可以当做List来用. List类型是一个链表结构的集合,其主要功能有push,pop,获取元素等.更详细的说,List类型是一个双端链表的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除元素,list的设计非常简单精巧,即可以作为栈,又可以作为队列.满足绝大多数需求. Map<String, List> rpush key value -> 往列表右边添加数据 lrange key start end -> 范围显示列表数据,全显示则设置0 -1 lpush key value -> 往列表左边添加数据 lpop key -> 弹出列表最左边的数据 rpop key -> 弹出列表最右边的数据 llen key -> 获取列表长度 linsert key before/after refVal newVal -> 参考值之前/后插入数据 lset key index value -> 根据索引修改数据 lrem key count value -> 在列表中按照个数删除数据 ltrim key start end -> 范围截取列表 lindex key index -> 根据索引取列表中数据

set类型

Set集合是string类型的无序集合,set是通过hashtable实现的,对集合我们可以取交集,并集,差集. sadd key value -> 往set集合中添加元素 smembers key -> 列出set集合中的元素 srem key value -> 删除set集合中的元素 spop key count -> 随机弹出集合中的元素 sdiff key1 key2 -> 返回key1中特有元素(差集) sdiffstore var key1 key2 -> 返回key1中特有元素存入另一个set集合 sinter key1 key2 -> 返回两个set集合的交集 sinterstore var key1 key2 -> 返回两个set集合的交集存入另一个set集合 sunion key1 key2 -> 返回两个set集合的并集 sunionstore var key1 key2 -> 返回两个set集合的并集存入另一个set集合 smove key1 key2 value -> 把key1中的某元素移入key2中 scard key -> 返回set集合中元素个数 sismember key value -> 判断集合是否包含某个值 srandmember key count -> 随机获取set集合中元素

sort_set类型

zadd key score column -> 存入分数和名称 zincrby key score column -> 偏移名称对应的分数 zrange key start end -> 按照分数升序输出名称 zrevrange key start end -> 按照分数降序输出名称 zrank key name -> 升序返回排名 zrevrank key name -> 降序返回排名 zcard key -> 返回元素个数 zrangebyscore key min max [withscores] -> 按照分数范围升序输出名称 zrevrangebyscore key max min [withscores] -> 按照分数范围降序输出名称 zrem key name -> 删除名称和分数 zremrangebyscore key min max [withscores] -> 根据分数范围删除元素 zremrangebyrank key start end -> 根据排名删除元素 zcount key min max -> 按照分数范围统计个数

总结

2: 如果确定使用redis, 此时需要考虑使用哪个数据类型 【偏redis原生数据结构】 1>如果要排序选用zset 2>如果数据是多个且允许重复选用list 3>如果数据是多个且不允许重复选用set 4>剩下的使用string hash ---> 转换成json格式 { key1:value1 key2:value2 ------> "{key1:value1, key2:value2}" }

JSON.toJsonString(map)

有些公司约定: 所有的redis的key跟value都使用字符串(排除使用zset场景) 【偏redis String类型json结构】 1>如果要排序选用zset 2>剩下的使用string

优点: java操作中如果使用各种类型: list set 其他的 操作redis时需要明确指定的泛型, 麻烦 所以有些公司统一规范, 统一使用字符串, 减少泛型操作

List<String>list = ... Set<String> set = .... Map<String, Object> map = ....

List<Object> list = redis对象.getList Set<Object> set =redis对象.getSet Map<Object, Object> map = redis对象.getMap

3:怎么设计 key 与 value值 key的设计 1:唯一性 2:可读性 设计keyvalue 缓存用户收藏文章列表 key value article_favor_list:uid1 [1,2,3,4] article_favor:uid2 [1,2,3,4] 3:灵活性 4:时效性

value值 根据需求决定

redis进阶

redis高级命令

返回满足的所有键 keys * (可以模糊查询) exists 是否存在指定key expire 设置某个key的过期时间.使用ttl查看剩余时间 persist 取消过期时间 flushdb 清空当前数据库,flushall清空所有数据库 select 选择数据库 数据库为0到15(一共16个数据库) 默认进入的是0数据库 move [key] [数据库下标] 讲当前数据中的key转移到其他数据库中 randomkey 随机返回数据库里的一个key rename重命名key echo 打印名 dbsize 查看数据库的key数量 info 获取数据库信息 config get 实时传储收到的请求(返回相关的配置信息) config get * 返回所有配置

redis安全性

因为redis速度非常快,所以在一台比较好的服务器下,一个外部用户在一秒内可以进行15w次的密码尝试,这意味你需要设定非常强大的密码来方式暴力破解. vi编辑redis.conf文件,找到下面进行保存修改 requirepass [密码] 重启服务器 pkill redis-server 再次进入127.0.01:6379>keys * (error)NOAUTH Authentication required. 会发现没有权限进行查询auth [密码] 输入密码则成功进入 每次进入的时候都需要输入免密,还有种简单的方式:

redis-cli -a [密码]

redis事务

Redis的事务非常简单,使用方法如下: 首先是使用multi方法打开事务,然后进行设置,这时设置的数据会放到队列里进行保存.最后使用exec执行.把数据依次存储到redis中.使用discard方法取消事务.

redis持久化操作机制

Redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中中的数据同步到硬盘来保证持久化. Redis持久化的两种方式:

reids内存淘汰机制及过期key处理


Redis内存淘汰机制及过期Key处理   “天长地久有时尽,此恨绵绵无绝期。”好诗!好诗啊!即使是天长地久,也总会有尽头,那么,Redis的内存是不是也会有时尽呢?答案是肯定的。那么,当Redis的内存满了以后,再来新的请求,我们该怎么办呢?这时候,大家就应该来了解Redis的内存淘汰策略了,了解了相关的知识点后,就能明白“Redis内存有时尽”后,会发生些什么。

Redis内存淘汰机制

  Redis内存淘汰机制是指当内存使用达到上限(可通过maxmemory配置,0为不限制,即服务器内存上限),根据一定的算法来决定淘汰掉哪些数据,以保证新数据的存入。

  常见的内存淘汰机制分为四大类:

  1. LRU:LRU是Least recently used,最近最少使用的意思,简单的理解就是从数据库中删除最近最少访问的数据,该算法认为,你长期不用的数据,那么被再次访问的概率也就很小了,淘汰的数据为最长时间没有被使用,仅与时间相关。

  2. LFU:LFU是Least Frequently Used,最不经常使用的意思,简单的理解就是淘汰一段时间内,使用次数最少的数据,这个与频次和时间相关。

  3. TTL:Redis中,有的数据是设置了过期时间的,而设置了过期时间的这部分数据,就是该算法要解决的对象。如果你快过期了,不好意思,我内存现在不够了,反正你也要退休了,提前送你一程,把你干掉吧。

  4. 随机淘汰:生死有命,富贵在天,是否被干掉,全凭天意了。

  通过maxmemroy-policy可以配置具体的淘汰机制,看了网上很多文章说只有6种,其实有8种,可以看Redis5.0的配置文件,上面有说明:

  1. volatile-lru -> 找出已经设置过期时间的数据集,将最近最少使用(被访问到)的数据干掉。

  2. volatile-ttl -> 找出已经设置过期时间的数据集,将即将过期的数据干掉。

  3. volatile-random -> 找出已经设置过期时间的数据集,进行无差别攻击,随机干掉数据。

  4. volatile-lfu -> 找出已经设置过期时间的数据集,将一段时间内,使用次数最少的数据干掉。

  5. allkeys-lru ->与第1个差不多,数据集从设置过期时间数据变为全体数据。

  6. allkeys-lfu -> 与第4个差不多,数据集从设置过期时间数据变为全体数据。

  7. allkeys-random -> 与第3个差不多,数据集从设置过期时间数据变为全体数据。

  8. no-enviction -> 什么都不干,报错,告诉你内存不足,这样的好处是可以保证数据不丢失,这也是系统默认的淘汰策略。

Redis过期Key清除策略

  Redis中大家会对存入的数据设置过期时间,那么这些数据如果过期了,Redis是怎么样把他们消灭掉的呢?我们一起来探讨一下。下面介绍三种清除策略:

  惰性删除:当访问Key时,才去判断它是否过期,如果过期,直接干掉。这种方式对CPU很友好,但是一个key如果长期不用,一直存在内存里,会造成内存浪费。

  定时删除:设置键的过期时间的同时,创建一个定时器,当到达过期时间点,立即执行对Key的删除操作,这种方式最不友好。

  定期删除:隔一段时间,对数据进行一次检查,删除里面的过期Key,至于要删除多少过期Key,检查多少数据,则由算法决定。举个例子方便大家理解:Redis每秒随机取100个数据进行过期检查,删除检查数据中所有已经过期的Key,如果过期的Key占比大于总数的25%,也就是超过25个,再重复上述检查操作。

  Redis服务器实际使用的是惰性删除和定期删除两种策略:通过配合使用这两种删除策略,可以很好地在合理使用CPU和避免浪费内存之间取得平衡。

  好的,相关知识介绍完毕,希望这篇文章能对你有所帮助!

实际运用

jedis基本使用

导入Jedis相关的依赖:
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/>
    </parent>
​
   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
​
​
​
​
​
​
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
​
   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

普通API

​
@Test
public void testJedisPool() {
    // 1:创建Jedis连接池
    JedisPool pool = new JedisPool("localhost", 6379);
    // 2:从连接池中获取Jedis对象
    Jedis jedis = pool.getResource();
    /* 设置密码
    jedis.auth(密码); */
    // 3:TODO
    System.out.println(jedis);
    // 4:关闭资源
    jedis.close();
    pool.destroy();
}
---------------------------------------------
    @Test
    public void testTool(){
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        最大连接数, 默认8个
        config.setMaxTotal(100);
        最大空闲连接数, 默认8个
        config.setMaxIdle(20);
        //获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1
        config.setMaxWaitMillis(-1);
        //在获取连接的时候检查有效性, 默认false
        config.setTestOnBorrow(true);
        JedisPool pool = new JedisPool(config,"192.168.122.128",6379,5000,"wolfcode");
        Jedis j = pool.getResource();
        String name = j.get("name");
        System.out.println(name);
        j.close();
        pool.close();
        pool.destroy();
    }
​

集成SpringBoot

​
​
导入依赖:
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
​
   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
​
​
--------------------------------------------
​
#application.properties
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=admin
​
---------------------------------------
@Autowired
private StringRedisTemplate redisTemplate;
​
@Test
public void testRedisTemplate() {
    // 操作string
    redisTemplate.opsForValue().xx();
    // 操作hash
    redisTemplate.opsForHash().xx();
    // 操作list
    redisTemplate.opsForList().xx();
    // 操作set
    redisTemplate.opsForSet().xx();
    // 操作zset
    redisTemplate.opsForZSet().xx();
}
-----------------------------------------
redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值