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) 与范围查询, bitmaps, hyperloglogs 和 地理空间(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笔记-入门篇的主要内容,如果未能解决你的问题,请参考以下文章