Redis笔记-入门篇

Posted 似水流年it

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis笔记-入门篇相关的知识,希望对你有一定的参考价值。

Nosql概述

为什么要用Nosql

大数据时代,

大数据 一般的数据库无法进行分析处理了!

1、单机mysql的年代

90年代,一个基本的访问量一般不会太大,单个数据库完全足够!

那个时候,更多的去使用静态网页html~服务更本没有太大的压力!

思考一下,这个情况下:整个网页的瓶颈是什么?

1、数据量如果太大,一个机器放不下了!

2、数据的超过300万,就要建立索引, 数据的索引(B+Tree),一个机器内存也放不下

3、访问量(读写混合),性能问题,一个服务器也承受不了~

只要开始出现以上三种情况之一,就必须要晋级!

2、Memcached(缓存) + MySQL + 垂直拆分 (读写分离)

网站80%的情况都是在读,每次都要去查询数据库的话就十分的麻烦!所以希望减轻服务器的压力,可以使用缓存来保证效率!

发展过程:优化数据结构和索引–>文件缓存(IO)–>Memcached(当时最热门的技术!)

3、分库分表 + 水平拆分 + MySQL集群

本质:数据库(读,写)

早些年MyISAM: 表锁,十分影响效率!查询表里面的一个东西,会锁整个表,高并发情况下会出现严重的锁问题

转战Innodb:行锁,

慢慢的就开始使用分库分表来解决写的压力!Mysql在那个年代推出了表分区!这个并没有被多少公司使用!

MySQL的集群,很好的满足了那个年代的需求!

4、如今的年代

2010-2020 十年之间,世界已经发生翻天覆地的变化;(定位,也是一种数据,音乐,热榜!)

MySQL等关系型数据库就不够用了!数据量很多,变化很快~!

MySQL有的使用它来存储一些比较大的文件,博客,图片!数据库很大,效率就低了!如果有一种数据库来专门处理这种数据,MySQL的压力就会小了(研究如何处理这些问题)大数据的IO压力下,表几乎无法更改!

目前一个基本的互联网项目!

为什么要用NoSQL!

用户的个人信息,社交网络,地理位置。用户自己产生的数据,用户日志等等爆发式增长!

这时候用NoSQL数据库可以很好的处理以上的情况!

什么是NoSQL

NoSQL

NoSQL = Not Only SQL(不仅仅是SQL)

关系型数据库:表格,行,列

泛指非关系型数据库,随着web2.0互联网的诞生!传统的关系型数据库很难对付web2.0时代!尤其是超大规模的高并发的社区!暴露出来很多难以克服的问题,NoSQL在当今大数据环境下发展的十分迅速,Redis是发展最快的,而且是当下必须要掌握的一个技术!

很多的数据类型用户的个人信息,社交网络,地理位置。这些数据类型的存储不需要一个固定的格式!不需要多余的操作就可以横向扩展的!Map<String,Object>键值对来控制!

NoSQL特点

Java为什么要用接口 解耦!

1、方便扩展(数据之间没有关系,很好扩展)

2、大数据量 高性能(Redis 1s写八万次,读11万次,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高!)

3、数据类型是多样性的!(不需要事先设计数据库!随取随用,很多人无法开始就设计一个很好的数据库)

4、传统RDBMS和NoSQL

传统的RDBMS(关系型数据库)
- 结构化组织
- SQL
- 数据和关系都存在单独的表中 row col
- 数据操作语言,数据定义语言
- 严格的一致性 数据的ACID
- 基础的事务
- .....
NoSQL
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储,列存储,文档存储,图形数据库(社交关系)
- 最终一致性, 最终!!!
- CAP定理和BASE (异地多活)  初级架构师
- 高性能,高可用,高可扩
- .....

了解:3V + 3高

大数据时代的3V:主要是描述问题的

海量 Volume

多样 Variety

实时 Velocity

大数据时代的3高:主要是对程序的要求

高并发

高可扩(随时可以水平拆分,机器不够了,可以扩展机器来解决)

高性能

真正在公司中的实践:NoSQL + RDBMS一起使用才是最强的。

阿里巴巴演进分析

这么多的数据都是在一个数据库中么?

敏捷开发、极限编程 了解

敏捷开发以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。

极限编程是一个轻量级的、灵巧的软件开发方法;同时它也是一个非常严谨和周密的方法。它的基础和价值观是交流、朴素、反馈和勇气;即,任何一个软件项目都可以从四个方面入手进行改善:加强交流;从简单做起;寻求反馈;勇于实事求是。

XP是一种近螺旋式的开发方法,它将复杂的开发过程分解为一个个相对比较简单的小周期;通过积极的交流、反馈以及其它一系列的方法,开发人员和客户可以非常清楚开发进度、变化、待解决的问题和潜在的困难等,并根据实际情况及时地调整开发过程。

想当一个架构师:没有什么是加一层解决不了的。 比如众多数据库 我们使用JDBC去差异化链接

# 1、商品的基本信息
	名称、价格、商家信息;
	关系型数据库就可以解决了! MysQL / oracle(淘宝早年就去TOE了!-王坚:推荐文章:阿里云的这群疯子:40分	 钟重要!)淘宝内部的MysQL不是大家用的MysQL

# 2、商品的描述、评论(文字比较多)
	文档型数据库中,MongoDB
	
	# 3、图片
	分布式文件系统 FastDFS
	- 淘宝自己的   TFS
	- Gooale的   GFS
	- Hadoop    HDFS
	- 阿里云的    oss
	
# 4、商品的关键字(搜索)
	- 搜索引擎so1r elasticsearch
	- Iserach:多隆(多去了解一下这些技术大佬!)
	所有牛逼的人都有一段苦逼的岁月!但是你只要像SB一样的去坚持,终将牛逼! 
	
# 5、商品热门的波段信息
	- 内存数据库
	- Redis   Tair   Memache...

# 6、上品的交易,外部的支付接口
	- 三方应用

一个简单的网页背后的技术一定不是大家所想的那么简单!

大型互联网应用的问题:

  • 数据类型太多了!
  • 数据源繁多,经常重构!
  • 数据要改造,大面积啊改造?

解决问题:

NoSQL四大分类

KV键值对:

  • 新浪: Redis
  • 美团: Redis + Tair
  • 阿里、百度: Redis + memcache

文档型数据库(bson格式和Json一样):

  • MongoDB(一般需要掌握)
    • MongoDB是一个基于分布式文件存储的数据库, C++编写,主要用来处理大量的文档!
    • MongoDB是一个介于关系型数据库和非关系型数据库中间产品,MongoDB是非关系数据库中功能最丰富,最像关系型数据库的!
  • ConthDB

列存储数据库

  • HBase
  • 分布式文件系统

图关系数据库

  • 不是存图形的,放的是关系,比如,朋友圈的社交网络,广告推荐!
  • Neo4j,InfoGrid;

四者对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JlFVnrDt-1638932737594)(Redis.assets/image-20210106125514634.png)]

Redis入门

概述

Redis是什么?

Redis(Remote Dictionary Server ),即远程字典服务

一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。免费和开源!是当下最热门的NoSQL技术之一!也被人们称之为结构化数据库!

Redis能干嘛

1、内存存储,持久化,内存断电即失,所以说持久化很重要(rdb、aof)

2、效率高,可以用于高速缓存

3、发布订阅系统

4、地图信息分析

5、计时器、计数器(浏览量!)

6、…

特性

1、多样的数据类型

2、 持久化

3、 集群

4、 事务

学习中需要用到的东西

1、狂神的公众号:狂神说

2、官网: https://redis.io/

3、中文网: http://www.redis.cn/、

4、下载:通过官网下载

注意:Windows在Github上下载(停更很久)

Redis推荐都是在Linux服务器上搭建的,我们是基于Linux学习!

Windows安装

1、下载安装包:https://github.com/dmajkic/redis/releases

2、下载完毕后得到压缩包

3、解压到自己电脑上的环境目录下就可以!Redis十分的小,只有5M

4、开启Redis,双击运行服务即可

5、使用Redis客户端链接redis

Window下使用确实简单,但是Redis推荐使用Linux

Linux安装

1、下载安装包

2、解压Redis的安装包!程序放在/opt

3、进入解压后的文件,可以看到Redis的配置文件

4、基本的环境安装

yum install gcc-c++
make #安装  过长较长
make #确定 确定安装是否成功
make install#确定安装是否成功

5、redis的默认安装路径usr/local/bin

6、将redis配置文件,复制到当前目录下 出问题了 用原来的配置文件直接拿过来 保证安全

7、redis默认不是后台启动的 改为yes 就是后台启动了

8、启动Redis

通过自定义的配置文件启动

9、测试连接

redis-cli -h(默认是本机不用写) -p 端口

keys * 查看所有的key

10、查看redis进程是否开启!

11、如何关闭Redis服务shotdown

12、后面会使用单机多Redis启动集群测试!

测试性能

redis-benchmark是一个压力测试工具

官方自带的性能测试工具!

redis-benchmark 命令参数!

测试:

# 测试: 100个并发连接 100000请求
redis-benchmark -c 100 -n 100000

如何查看这些分析

基础的知识

Redis默认有16个数据库

默认使用的是第0个数据库

可以使用select进行切换数据库

127.0.0.1:6379> select 3 # 切换数据库
OK
127.0.0.1:637> DBSIZE # 查看DB大小
(integer) 0

清楚当前数据库内容flushdn

清楚全部数据库内容flushall

127.0.0.1:6379> keys * # 查询所以逇key
1) "key:__rand_int__"
2) "myset:__rand_int__"
3) "name"
4) "counter:__rand_int__"
5) "mylist"

127.0.0.1:6379[3]> flushdb  # 清空当前库  flushall 清空所有库
OK
127.0.0.1:6379[3]> keys *
(empty list or set)

Redis是单线程的 6.0版本之后变成了多线程

明白Redis是很快的,官方表示,Redis是基于内存操作的,CPU不是Redis性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就是用单线程。

Redis是C语言写的,官方提供的数据为100000+的QPS(每秒查询率),完全不比同样适用key-value的Memcache差!

Redis为什么单线程还这么快?

1、误区1:高性能的服务器一定是多线程的。

2、误区2:多线程(CPU上下文切换!消耗资源)一定比单线程效率高!

先CPU>内存>硬盘的速度有所了解

核心:redis是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的。多线程(CPU上下文切换!耗时的操作!!!),对于内存系统来说,如果没有上下文切换,效率就是最高的!多次读写都是在一个CPU上的,在内存情况下,这个就是最佳的方案!

五大数据类型

官网文档

全段翻译:Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings)散列(hashes)列表(lists)集合(sets)有序集合(sorted sets) 与范围查询, bitmapshyperloglogs地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication)LUA脚本(Lua scripting)LRU驱动事件(LRU eviction)事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

Redis-Key

exists xx # 查看xx存在不存在
EXISTS name
(integer) 1

move xx n #将xx移动到第n个数据库
127.0.0.1:6379[3]> select 0
OK
127.0.0.1:6379> keys *
1) "key:__rand_int__"
2) "myset:__rand_int__"
3) "name"
4) "counter:__rand_int__"
5) "mylist"
127.0.0.1:6379> move name 1
(integer) 1
127.0.0.1:6379> keys *
1) "key:__rand_int__"
2) "myset:__rand_int__"
3) "counter:__rand_int__"
4) "mylist"
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
1) "name"

127.0.0.1:6379> EXPIRE name 10 # 设置name销毁时间 默认s
(integer) 1
127.0.0.1:6379> ttl name #查看name 还有多少s销毁
(integer) 5
127.0.0.1:6379> ttl name
(integer) 4
127.0.0.1:6379> 
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> keys *
1) "key:__rand_int__"
2) "myset:__rand_int__"
3) "counter:__rand_int__"
4) "mylist"
127.0.0.1:6379> get name
(nil)

127.0.0.1:6379> type name # 查看当前key的类型
string 

后续可以查看官网的命令

String(字符串)

127.0.0.1:6379> set key1 v1
OK
127.0.0.1:6379> EXISTS key1
(integer) 1
127.0.0.1:6379> append key1 "hello"  # 给key1追加"hello" 
(integer) 7 # 总长度
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> EXISTS key1
(integer) 1
127.0.0.1:6379> STRLEN key1  # 查看key1长度
(integer) 7 

####################################################################################
127.0.0.1:6379> set views 0 
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> type views
string
127.0.0.1:6379> incr views   # 自增
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> decr views   # 自减
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> incrby views 10 # 自增  步长为10
(integer) 11
127.0.0.1:6379> incrby views 10
(integer) 21
127.0.0.1:6379> decrby views 10 # 自减  步长为10
(integer) 11
127.0.0.1:6379> get views
"11"
###################################################################################
getrange
127.0.0.1:6379> set key1 "helle,shijie" 
OK
127.0.0.1:6379> get key1
"helle,shijie"
127.0.0.1:6379> getrange key1 0 3 # 截取key1 下标0-3
"hell"
127.0.0.1:6379> getrange key1 0 -1 # 截取key1  和get key1一样
"helle,shijie"

127.0.0.1:6379> set key2 abcdefg
OK
127.0.0.1:6379> get key2
"abcdefg"
127.0.0.1:6379> SETRANGE key2 1 xx # 将key2 从下标1开始替换为 xx
(integer) 7
127.0.0.1:6379> get key2
"axxdefg"
#####################################################################################
# setex(set with expire) # 设置过期时间
# setnx(set if not exist) # 不存在再设置(在分布式锁中常常用到)

127.0.0.1:6379> setex key3 30 "hello" # 设置key3的值为hello 30s后过期
OK
127.0.0.1:6379> ttl key3
(integer) 26
127.0.0.1:6379> setnx mykey "redis" # 如果mykey不存在,创建mykey
(integer) 1
127.0.0.1:6379> keys *
1) "mykey"
2) "key3"
3) "key2"
4) "key1"
127.0.0.1:6379> ttl key3
(integer) -2
127.0.0.1:6379> setnx mykey "MongoDB" # 如果mykey存在,创建mykey失败
(integer) 0
127.0.0.1:6379> get mykey
"redis"
#####################################################################################
# mset
# mget
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 同时设置多个值k1 k2 k3
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"
127.0.0.1:6379> mget k1 k2 # 查询 k1 k2
1) "v1"
2) "v2"

127.0.0.1:6379> msetnx k1 vv1 k2 vv2 k4 v4 # 当k1 k2 k4 全部不存在时,才会创建  原子性操作
(integer) 0

# 对象
set user:1name:zhangsan,ang:3 #设置一个user1 值为json字符串来保存一个对象!
# 这里的key是一个巧妙的设计: user:id:filed,在redis中完全ok

127.0.0.1:6379> mset user:1:name zhangsan user:1:age 30
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "30"

####################################################################################
getset #先get 再set
127.0.0.1:6379> getset db redis # 如果不存在返回nil,设置新的值
(nil)
127.0.0.1:6379> getset db redis
"redis"
127.0.0.1:6379> getset db shijie # 存在返回原来的值,并且设置新的值
"redis"
127.0.0.1:6379> get db
"shijie"

string类似的使用场景: value除了是我们的字符串还可以是我们的数字!

  • 计数器
  • 统计多单位的数量
  • 粉丝数
  • 对象缓存存储!

List(列表)

基本的数据类型,列表

在redis里面,我们可以把list玩成栈,队列、阻塞队列!

所有的list命令都是用l开头的

127.0.0.1:6379> lpush list one #将一个值或者多个值插入到名为list的list头部  最左边 下标为0
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange 0 -1
(error) ERR wrong number of arguments for 'lrange' command
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 1 # 最后进来的下标为0
1) "three"
2) "two"
 
127.0.0.1:6379> rpush list four # #将一个值或者多个值插入到名为list的list尾部  最右边 下标最大
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "four"

####################################################################################
lpop # 左弹出
rpop # 右弹出

127.0.0.1:6379> lpop list # 移除最左边的一个元素  头部  下标0
"three"
127.0.0.1:6379> rpop list # 移除最右边的一个元素  尾部  下标最大
"four"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
####################################################################################
lindex # 获取 某个list 的第n个值

127.0.0.1:6379> lindex list 0
"two"
127.0.0.1:6379> lindex list 1
"one"

####################################################################################
llen
127.0.0.1:6379> llen list # 返回列表长度
(integer) 2

####################################################################################
# 移除指定的值!
# 取关 uid
lrem 

127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "two"
3) "one"
4) "three"
127.0.0.1:6379> lrem list 1 three # 移除list 中 1个元素 值为 three
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "two"
3) "one" 
127.0.0.1:6379> lrem list 2 two # 移除list 中 2个元素 值为 two ,也可以移除一个,不清楚是那一个应该是靠近头部的被移除
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "one"

####################################################################################
trim # 在java中修剪 
list # 截断

127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
127.0.0.1:6379> ltrim list 1 2 # 通过下标截取
OK
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "three"

####################################################################################
rpoplpush #移除列表的最后一个元素 并且给另一个表

127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "hello1"
(integer) 2
127.0.0.1:6379> rpush mylist "hello12"
(integer) 3
127.0.0.1:6379> RPOPLPUSH mylist myotherlist
"hello12"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"
127.0.0.1:637<

以上是关于Redis笔记-入门篇的主要内容,如果未能解决你的问题,请参考以下文章

Redis笔记-入门篇

PHP学习笔记——入门篇——语法&变量

PHP学习笔记——入门篇——语法&变量

Redis从入门到精通:初级篇

Redis详解入门篇

Redis——Redis入门和一些笔记