redis 五大数据类型使用
- nosql介绍,由来
- 什么是nosql
- 阿里巴巴的架构
- nosql 四大分类
- redis入门
- 概述
- redis 安装 (docker)
- 基础的知识
- redis五大数据类型
- Redis-Key
- String
- List (列表)
- Set (集合)
- Hash(哈希)
- Zset 有序集合
nosql介绍,由来
1. 单机mysql~ 数据量太大,一个机器放不下~ 数据的索引(B+ tree) 一个机器的内存也放不下~ 访问量(读写混合) 一个服务器承受不了读写分离(垂直拆分),读是很多的,1号myql被读了,下个用户又来读。
2. memcached(缓存) + mysql + 垂直拆分
网站80%都是在读,每次都要查询数据库十分麻烦,为例减轻服务器的压力,使用缓存来保证效率。发展过程:优化数据结果和索引--> 文件缓存(io) -->memcached(当时火热的技术)3. 分库分表 水平拆分 mysql集群
技术和业务在发展的同时,对人的要求也越来越高。
本质:读,写
早年myisam:表锁,整个表锁住
转战innodb:行锁
so.. 使用分库分表的方式解决写的压力, 表分区。
user --> 拆分.
mysql集群,满足当时的需求4. 最近的年代
技术爆炸: 2010-2020 (定位, 音乐,热榜)
mysql 已经满足不了需求了。数据多,变化快。
mysql 有的使用它来存储一些比较大的文件,博客,图片。数据库表很大,效率就低了。使用redis,nosql可处理这种数据。
mysql 压力就变得十分小(如何处理) 大数据io的压力下,表几乎没法更改。5 为什么要使用nosql?用户的个人信息,社交网络,地理位置。
用户自己产生的数据,用户日志等 爆发式增长。
需要nosql来解决~
什么是nosql
nosql = not only sql
关系型数据库:表格,行,列
泛指非关系型数据库的,web2.0, 传统的关系型数据库很难对付web2.0时代,尤其是超大规模的高并发社区。暴露出来很多难以客服的问题,nosql在当今大数据环境下发展迅速,redis是发展最快的。
很多的数据类型,用户的个人信息,社交网络,地理位置。这些数据类型的存储不需要一个固定的格式。是可横向扩展的。Map<String, Object>, kv control.
nosql 特点
1、方便扩展(数据直接没有关系,很好扩展)
2、大数据量高性能(redis 1s写8万次,1s读取11万次,nosql的缓存记录级,细粒度,性能高)
3、数据类型多样。8 无需设计数据库。
4、传统rdbms和nosql
rdbms (非关系型数据库)
- 结构化阻止
- sql
- 数据和关系存在单独的表中
- 数据操作,数据定义语言
- 严格的一致性
- 基础的事务 acid
,,,
阿里巴巴的架构
架构师:没有什么是加一层解决不了的。
1. 商品的基本信息名称,价格,商家信息关系型数据库高i的搞定。 mysql/oracle (taobao 去ioe,王坚 阿里云的这群疯子)2. 商品的描述,评论(文字多)文档型数据库,mogodb3. 图片分布式文件系统 fastdfs淘宝 tfsgoogle gfshadoop hdfsaliyun oss4. 商品的关键字(搜索)搜索引擎 solr, elasticsearchisearch 多隆5 商品的波段信息内存数据库redis tair memache6. 商品的交易,外部的支付接口
问题:
- 数据类型太多了
- 数据源繁多,经常重构
- 数据要改造,大面积改造
解决:
udsl, 数据服务层
nosql
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储,列存储,文档存储,图形数据库(社交关系)
- 最终一致性
- cap定理 和 base (异地多活)
- 性能,可用,可扩
...
nosql 四大分类
kv键值对:
- 新浪 redis
- meituan: redis + tair
- ali,baidu redis + memecache
文档型数据库
- mogodb 掌握
- 是基于分布式文件存储的数据库,c++编写,主要处理大量的文档
- 是一个介于关系数据库和非关系型数据中间的产品。它是非关系型数据库中功能最丰富,最像关系型数据库的。
- conthDB
列存储数据库
- hbase
- 分布式文件系统oss
图关系数据库
- 不是存图形,放的是关系。比如,朋友圈设计网络,广告推荐
- neo4j, infoGrid;
redis入门
概述
redis 远程字典服务 Remote Dictionary Server1. 是什么
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。free, open-source, 是当下最热门的nosql技术之一,也被人们称之为结构化数据库。2.能干吗
- 内存存储,持久化,内存中是断电即失,所以说持久化很重要(rdb, aof)
- 效率高,可用告诉缓存
- 发布订阅系统
- 地图信息分析
- 计时器,计数器(浏览量)
...3. 特性
- 多样的数据类型
- 持久化
- 集群
- 事务
...4. 文档redis.io
redis.cn
redis 安装 (docker)
docker 容器/usr/local/bin 配置文件
docker pull redis:6.0.9docker run -d -p 6379:6379 --name myredis redis:6.0.9docker exec -it myredis /bin/bash
启动镜像时需要手动指定配置文件。我这没指定。
基础的知识
- redis有16个数据库- 切换数据库
select 1- 查看数据库大小
DBSIZE- 清除当前的数据库
flushdb- 查看所有的键
keys *- 清空所有的数据
FLUSHALLREDIS 是单线程的!
redis是很快的!官方表示, redis是基于内存操作的,cpu不是redis性能瓶颈,redis的性能是由机器的内存和网络带宽决定的。redis是由c语言编写的,官方数据为100000+的qps,不比memeCache差。redis为什么单线程很快?误区1: 高性能的服务器一定是多线程的。。
误区2: 多线程(cpu上下文切换)一定比单线程效率高。cpu 内存 硬盘的速度核心:redis将所有的数据放到内存里面的。使用单线程去操作效率就是高。多线程切换耗时。
对于内存系统来说,如果没有上下文切换,效率就是最高的。多次读写都是在一个cpu上的。
redis五大数据类型
# 官网简介:used as a database, cache, and message broker.Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams.
Redis-Key
# 1 true, 0 false
exists some_keymove some_key# made smoe key 10 second ---> 单点登录,热点记录
expire name 10# see the time when expire
ttl name# see the type of key
type key
https://redis.io/commands
String
# string demo
set key1 v1
get key1
keys *exists key1# stringBuffer 不存在就创建key
append key1 "hello"# remove
move key1 0 # 0为下标# get length of string
strlen key1####################################set views 1
# increase the value 1
incr viewsincr views # -1
decr views# + 10 步长
incrby views 10# -10
decrby views 10#########################
# 字符串截取
getRange key 0 3 # [0, 3]getRange key 0 -1 # get key # 字符串替换, 替换指定位置的字符串
setRange key offset value## demo
get key1
"aaadorable, here"
127.0.0.1:6379[1]> SETRANGE key1 0 bb
(integer) 16
127.0.0.1:6379[1]> get key1
"bbadorable, here"
127.0.0.1:6379[1]> SETRANGE key1 0 bbb # 往后覆盖。。
(integer) 16
127.0.0.1:6379[1]> get key1
"bbbdorable, here"
127.0.0.1:6379[1]>###########################
# setex (set with expire) # 设置过期时间
# setnx (set if not exist) # 不存在就设置 (分布式锁中会常用)setex key 30 'hello' # 设置key 值为hello存在30妙ttl keysetnx key1 'adorable' # 不存在就设置,存在的话,设置不了,能保证数据不被覆盖。######################
# 同时设置或者获取多个值
# mset k1 v1 k2 v2
# mget k1 k2# 原子性 不存在就设置,多个键
set k1 v1
# 下面的都不会成功,k1存在了
msetnx k1 v1 k2 v2# 对象 bastard 有错误。。 TODO: .... bullshit
set user:1 {name:jj, age:3} # 设置一个user:1# user:{id}:{filed} value ---->user后面可以多层套娃
mset user:1:name zhangshan user:1:age 18# 获取值
mget user:1:name user:1:age# demo
127.0.0.1:6379[1]> mset user:1:name adorable user:1:age 19
OK
127.0.0.1:6379[1]> keys *
3) "user:1:age"
4) "user:1:name"
127.0.0.1:6379[1]> mget user:1:name user:1:age
1) "adorable"
2) "19"
127.0.0.1:6379[1]>##############################
getset # 先get然后在set# 如果存在值,获取原来的值,并设置新值
getset db redis # 不存在,则返回nullgetset db hhhh # 获取到redis这个值然后再设置成hhhhstring类型的使用场景:value可是字符串或者数字
- 计数器
- 统计多单位的数量
- 粉丝数
- 对象缓存存储
List (列表)
redis 栈(头),队列(头,尾),阻塞队列
所有的list命令都是以l开头的。
## base opration# left push
lpush list onelpush list twolpush list threelrange list 0 -1
'three', 'two', 'one'lrange list 0 1 # 获取头部
three# right push 插入到右边
rpush list right# 移除左边的第一个 (first)
lpop # 移除右边的第一个 (last)
rpop# 通过下标获取值
lindex someKey index
lindex somekey 0# list长度
Llen someKey# 移除list集合中指定的值
lrem key count value#########################
# list的截取操作
ltrim mylist 1 2 # 根据下标截取~ mylist只剩下被截取的元素#########################
# rpoplpush # 移除一个元素并添加到新的list中
rpush mylist "value1"
rpush mylist "value2"
rpush mylist "value3"# 将value3 添加到newlist
rpoplpush mylist newlist#########################
# 判断list中是否存在值
exists list# 根据index 更新值
# 不存在列表报错,无此index下标越界
lset list 0 item############################
# linsert
linsert mylist before/after "originValue" currentValue
小总结:
-
实际上是一个链表,before node after, left right to insert
-
如果key不存在,创建
-
key存在,新增内容
-
如果移除了所有值,空链表,也代表不存在~
-
再两边插入或者改动值,效率最高!中间元素,相对来说,效率会第一点。
消息排队。消息队列(Lpush, Rpop) , 栈(Lpush Lpop) .
Set (集合)
##########################
# set sth~ s
sadd myset 'hello'
sadd myset 'world'
sadd myset 'adorable'# 查看set集合中的内容
smembers myset# 判断set集合中的值是否存在, 存在返回1, 不存在返回0
sismembers myset hello# 获取myset中的元素个数
scard myset# 移除指定的元素值
srem myset 'hhh'##################################
set 无序不重复集合。抽随机。# 随机抽选一个元素
SRANDMEMBER myset (count)# 随机删除元素
spop myset (count)################################### 将一个指定的值移动到另外一个集合中
127.0.0.1:6379[1]> sadd myset cc
(integer) 1
127.0.0.1:6379[1]> smembers myset
1) "hh"
2) "bb"
3) "aa"
4) "cc"
127.0.0.1:6379[1]> sadd myset1 hello
(integer) 1
127.0.0.1:6379[1]> smove myset myset1 cc
(integer) 1
127.0.0.1:6379[1]> smembers myset
1) "hh"
2) "bb"
3) "aa"
127.0.0.1:6379[1]> smembers myset1
1) "cc"
2) "hello"# 哈哈哈 weibo,b站共同关注的..
# set的差集sdiff,交集sinter,并集sunion127.0.0.1:6379[1]> SMEMBERS myset1
1) "cc"
2) "hello"
127.0.0.1:6379[1]> SMEMBERS myset
1) "hh"
2) "bb"
3) "aa"
4) "cc"
127.0.0.1:6379[1]> sdiff myset1 myset # 以myset1为参照
1) "hello"
127.0.0.1:6379[1]> sinter myset1 myset # 交集
1) "cc"
127.0.0.1:6379[1]> sunion myset1 myset # 并集
1) "bb"
2) "hh"
3) "hello"
4) "aa"
5) "cc"
set的应用:
微博,a用户将所有关注的人放在一个set集合中。将其粉丝也放在一个集合中。
共同关注,共同爱好,二度好友,推荐好友…
Hash(哈希)
map集合。key-map 值是map集合。
set myhash field
# base garam
# set myhash field value127.0.0.1:6379[1]> hset myhash name 'bitqian' age 19 # 同时设置多个值
(integer) 2
127.0.0.1:6379[1]> hget myhash name # 获取单个值
"bitqian"
127.0.0.1:6379[1]> hget myhash age
"19"
127.0.0.1:6379[1]> hgetall myhash # 获取所有
1) "name"
2) "bitqian"
3) "age"
4) "19"
127.0.0.1:6379[1]> hmget myhash name age # 批量获取
1) "bitqian"
2) "19"# 删除hash中指定的键, 删除后value也消失了。
hdel myhash age# 获取长度
hlen myhash# 查看哈希中的某个键是否存在
hexists myhas name# 获取所有的keys, vals
hkeys myhash
hvals myhas # 类型string操作。 值新增 或者 不存在才新增
hincrBy
hsetnx
小总结:
- hash存储变更的数据 user, name, age,尤其存储用户信息之类的。经常变动的信息。hash更适合于对象的存储,string更适合字符串存储。
Zset 有序集合
在set的基础上增加了一个值。键是有序的。
# 新增操作127.0.0.1:6379[1]> zadd myzset 1 one
(integer) 1
127.0.0.1:6379[1]> zadd myzset 2 two
(integer) 1
127.0.0.1:6379[1]> zadd myzset 3 three
(integer) 1
127.0.0.1:6379[1]> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"# 排序如何实现# 新增三个人
127.0.0.1:6379[1]> zadd salary 6000 xiaoMing
(integer) 1
127.0.0.1:6379[1]> zadd salary 9000 jack
(integer) 1
127.0.0.1:6379[1]> zadd salary 5000 rose
(integer) 1
# 按薪资从小到大排序
127.0.0.1:6379[1]> zrangebyscore salary -inf +inf
1) "rose"
2) "xiaoMing"
3) "jack"# 显示用户和薪资
127.0.0.1:6379[1]> zrangebyscore salary -inf +inf withscores
1) "rose"
2) "5000"
3) "xiaoMing"
4) "6000"
5) "jack"
6) "9000"# 薪水小于8000的
127.0.0.1:6379[1]> zrangebyscore salary -inf 8000 withscores
1) "rose"
2) "5000"
3) "xiaoMing"
4) "6000"### 上面都是升序。# zreverange# 降序 value
127.0.0.1:6379[1]> ZREVRANGE salary 0 -1
1) "jack"
2) "xiaoMing"
3) "rose"
# 降序
127.0.0.1:6379[1]> ZREVRANGEBYSCORE salary +inf -inf withscores
1) "jack"
2) "9000"
3) "xiaoMing"
4) "6000"
5) "rose"
6) "5000"# 移除元素
zrem salary127.0.0.1:6379[1]> ZCARD salary
(integer) 3# 查看元素的长度
zcard salary127.0.0.1:6379[1]> zadd salary 0 demo
(integer) 1
127.0.0.1:6379[1]> zrem salary demo
(integer) 1# zcount 获取指定区间的成员数量127.0.0.1:6379[1]> zadd myset 1 aa 2 bb 3 cc
(integer) 3
127.0.0.1:6379[1]> zcount myset 0 1
(integer) 1
127.0.0.1:6379[1]> zcount myset 1 3
(integer) 3
多查看官网文档。。。
应用:set排序,存储成绩表,工资表排序。
普通消息:1. 重要消息 2. 带权重进行判断
排行榜应用实现:取top n测试。
kuangshenSayJava…