盘锦市网站建设,邢台学校网站建设费用,百度seo优化技巧,网站建设与管理教学视频下载一、Reids概述
1.1 为什么要使用NoSQL 单机Mysql的美好年代
在90年代#xff0c;一个网站的访问量一般都不大#xff0c;用单个数据库完全可以轻松应付。在那个时候#xff0c;更多的都是静态网页#xff0c;动态交互类型的网站不多。 遇到问题#xff1a; 随着用户数的…一、Reids概述
1.1 为什么要使用NoSQL 单机Mysql的美好年代
在90年代一个网站的访问量一般都不大用单个数据库完全可以轻松应付。在那个时候更多的都是静态网页动态交互类型的网站不多。 遇到问题 随着用户数的增长Tomcat和数据库之间竞争资源单机性能不足以支撑业务。 Tomcat与数据库分开部署
Tomcat和数据库分别独占服务器资源显著提高两者各自性能。 新的问题: 随着用户数的增长并发读写数据库成为瓶颈。 引入本地缓存和分布式缓存
通过缓存能把绝大多数请求在读写数据库前拦截掉大大降低数据库压力。其中涉及的技术包括使用memcached作为本地缓存使用Redis作为分布式缓存。 注意 缓存抗住了大部分的访问请求随着用户数的增长并发压力主要落在单机的Tomcat上响应逐渐变慢。 引入反向代理实现负载均衡
在多台服务器上分别部署Tomcat使用反向代理软件Nginx把请求均匀分发到每个Tomcat中。 新的挑战 反向代理使应用服务器可支持的并发量大大增加但并发量的增长也意味着更多请求穿透到数据库单机的数据库最终成为瓶颈。 数据库读写分离
由于数据库的写入压力增加Memcached只能缓解数据库的读取压力。读写集中在一个数据库上让数据库不堪重负大部分网站开始使用主从复制技术来达到读写分离以提高读写性能和读库的可扩展性。Mysql的master-slave模式成为这个时候的网站标配了. 新的挑战 业务逐渐变多不同业务之间的访问量差距较大不同业务直接竞争数据库相互影响性能。读取数据从从库读取写数据时写到主库。 数据库按业务分库
把不同业务的数据保存到不同的数据库中使业务之间的资源竞争降低对于访问量大的业务可以部署更多的服务器来支撑。 为什么用NoSQL
用户的个人信息社交网络地理位置用户生成的数据和用户操作日志已经成倍的增加。我们如果要对这些用户数据进行挖掘那SQL数据库已经不适合这些应用了, NoSQL数据库的发展也却能很好的处理这些大的数据。 1.2 什么是NoSQL NoSQL(NoSQL Not Only SQL)意即“不仅仅是SQL”泛指非关系型的数据库。随着互联网web2.0网站的兴起传统的关系数据库在应付特别是超大规模和高并发类型纯动态网站已经显得力不从心暴露了很多难以克服的问题。
结构化数据和非结构化数据 结构化数据指的是由二维表结构来逻辑表达和实现的数据严格遵循数据格式与长度规范也称作为行数据。非结构化数据指的是数据结构不规则或不完整没有任何预定义的数据模型不方便用二维逻辑表来表现的数据例如办公文档Word、文本、图片、HTML、各类报表、视频音频等。 NoSQL的四大分类 KV型NoSql代表----Redis
KV型NoSql顾名思义就是以键值对形式存储的非关系型数据库是最简单、最容易理解也是大家最熟悉的一种NoSql因此比较快地带过。 特点 数据基于内存读写效率高KV型数据时间复杂度为O(1)查询速度快 注意 KV型NoSql最大的优点就是高性能利用Redis自带的BenchMark做基准测试TPS可达到10万的级别性能非常强劲。 列式NoSql代表----HBase
列式NoSql大数据时代最具代表性的技术之一了以HBase为代表。
关系行数据库数据 注意 看到每行有name、phone、address三个字段这是行式存储的方式且可以观察id 2的这条数据即使phone字段没有它也是占空间的。 列式数据库数据 注意 查询时只有指定的列会被读取不会读取所有列列数据被组织到一起一次磁盘IO可以将一列数据一次性读取到内存中 文档型NoSql代表----MongoDB
什么是文档型NoSql呢文档型NoSql指的是将半结构化数据存储为文档的一种NoSql文档型NoSql通常以JSON或者XML格式存储数据。 注意 关系型数据库是按部就班地每个字段一列存在MongDB里面就是一个JSON字符串存储。 搜索型NoSql代表----ElasticSearch 传统关系型数据库主要通过索引来达到快速查询的目的但是在全文搜索的场景下索引是无能为力的like查询一来无法满足所有模糊匹配需求二来使用限制太大且使用不当容易造成慢查询搜索型NoSql的诞生正是为了解决关系型数据库全文搜索能力较弱的问题ElasticSearch是搜索型NoSql的代表产品。 1.3 关系型数据库和非关系型数据及其区别
关系型数据库 关系型数据库最典型的数据结构是表由二维表及其之间的联系所组成的一个数据组织 优点
易于维护都是使用表结构格式一致使用方便SQL语言通用可用于复杂查询复杂操作支持SQL可用于一个表以及多个表之间非常复杂的查询。 缺点读写性能比较差尤其是海量数据的高效率读写固定的表结构灵活度稍欠
非关系型数据库 优点
格式灵活存储数据的格式可以是key,value形式、文档形式、图片形式等等文档形式、图片形式等等使用灵活应用场景广泛而关系型数据库则只支持基础类型。速度快nosql可以使用硬盘或者随机存储器作为载体而关系型数据库只能使用硬盘高扩展性成本低nosql数据库部署简单基本都是开源软件。
缺点 不提供sql支持学习和使用成本较高 无事务处理 数据结构相对复杂复杂查询方面稍欠。
1.4 当下NoSQL经典应用 当下应用是SQL和NoSQL一起使用 淘宝商品信息如何存放 商品基本信息
名称、价格、出厂信息、生产厂商商家信息等 关系型数据库就可以解决。 注意 注意淘宝内部用的Mysql是里面的大牛自己改造过的。 商品描述、详情、评论 多文件信息描述类IO读写性能变差不能使用Mysql数据库使用MongDB。
商品的图片 图片放在分布式文件系统中
淘宝自己的TFSGoogle的GFSHadoop的HDFS阿里云的OSS
商品关键字 搜索引擎 elasticsearch 或者 ISerach
商品热门的波段信息
内存数据库 Redis Tair Memache 遇到的问题 数据类型太多数据源繁多数据要改造 发现问题 难点 数据类型多样性数据源多样性和变化重构数据源改造而数据服务平台不需要大面积重构 解决问题
UDSL统一数据服务平台 UDSL热点缓存设计 1.5 什么是Redis Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对分布式缓存数据库。
特性
基于内存运行性能高效支持分布式理论上可以无限扩展key-value存储系统开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库并提供多种语言的API
谁在用Redis Github 京东 微博 阿里巴巴 百度 美团 搜狐
二、Redis安装
2.1 Linux下安装Redis 下载地址
Redis官方网址Redis
下载Redis安装包源文件 鼠标右键选择复制连接地址在linux下使用wget下载安装包或者直接下载到win,再上传到Linux
wget https://github.com/redis/redis/archive/6.2.6.tar.gz 将安装包解压到/usr/local目录下
安装C语言编译环境GCC
#查看是否安装了gcc
gcc --version#安装gcc
yum install -y gcc
编译Redis
在redis-6.2.6文件下执行编译命令将redis源码编译成可执行的文件
[rootlocalhost redis-6.2.6]# make安装Redis
在redis-6.2.6目录下执行
[rootlocalhost redis-6.2.6]# make install打开src文件发现绿色的命令文件 注意 redis-benchmarkRedis自带的基准性能测试工具 redis-check-aof对有问题的 AOF 文件进行修复AOF和RDB文件后面会说明 redis-check-rdb对有问题的 RDB文件进行修复 redis-sentinelRedis集群使用 redis-cli客户端 redis-server服务器启动 服务启动
前台启动/usr/local/redis-2.6.2/src下执行
./redis-server后台启动
修改redis.conf文件,在resid-6.2.6根目录下
daemonize yes #由no改为yes在src下启动服务
[rootlocalhost src]# ./redis-server ../redis.conf
进入redis数据库
[rootlocalhost src]# ./redis-cli
2.2 Docker安装Redis 下载最新Redis镜像
docker pull redis注意 可以用docker pull redis命令下载最新版本的Redis镜像也可 以用“docker pull redis:标签”命令下载指定版本的Redis。 启动Redis容器
docker run -itd --name myFirstRedis -p 6379:6379
redis:latest观察Redis启动效果
docker logs myFirstRedis 注意 如果直接在Linux等环境上启动Redis服务器就能直接看到启动后的效果。 查看Redis的版本
先确保myFirstRedis容器处于Up状态。进入容器的命令行交互窗口。
docker exec -it myFirstRedis /bin/bash
redis-server --versionRedis服务器和客户端
Redis是基于键值对存储的NoSQL数据库其中的数据是存储在 Redis服务器里的。和传统的MySQL数据库服务器相似一个Redis服务器可以同多个客户端创建连接。
docker exec -it myFirstRedis /bin/bash
redis-cli
2.3 基础知识 默认16数据库
Redis是一个字典结构的存储服务器一个Redis实例提供了多个用来存储数据的字典客户端可以指定将数据存储在哪个字典中。
这与在一个关系数据库实例中可以创建多个数据库类似如下图所示所以可以将其中的每个字典都理解成一个独立的数据库。 Redis默认支持16个数据库可以通过调整Redis的配置文件redis/redis.conf中的databases来修改这一个值设置完毕后重启Redis便完成配置。 Redis 使用的到底是多线程还是单线程
因为Redis是基于内存的操作CPU不是Redis的瓶颈Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现而且CPU不会成为瓶颈那就顺理成章地采用单线程的方案了。
IO多路复用技术
redis 采用网络IO多路复用技术来保证在多连接的时候 系统的高吞吐量。
这里“多路”指的是多个网络连接“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求尽量减少网络IO的时间消耗且Redis在内存中操作数据的速度非常快内存内的操作不会成为这里的性能瓶颈主要以上两点造就了Redis具有很高的吞吐量。 大白话解释 假设你是一个机场的空管 你需要管理到你机场的所有的航线 包括进港出港 有些航班需要放到停机坪等待有些航班需要去登机口接乘客。最简单的做法就是你去招一大批空管员然后每人盯一架飞机 从进港接客排位出港航线监控直至交接给下一个空港全程监控。 遇到的问题 很快你就发现空管塔里面聚集起来一大票的空管员交通稍微繁忙一点新的空管员就已经挤不进来了。空管员之间需要协调屋子里面就1, 2个人的时候还好几十号人以后 基本上就成菜市场了。空管员经常需要更新一些公用的东西比如起飞显示屏比如下一个小时后的出港排期最后你会很惊奇的发现每个人的时间最后都花在了抢这些资源上。 切换数据库
select number示例
# 默认使用 0 号数据库
redis 127.0.0.1:6379 SET db_number 0
OK
# 使用 1 号数据库
redis 127.0.0.1:6379 select 1
OK
127.0.0.1:6379[1]
为当前数据库添加数据
127.0.0.1:6379 set k3 30
OK清空当前库
Redis Flushdb 命令用于清空当前数据库中的所有 key。
127.0.0.1:6379flushdb
通杀全部库
Redis Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )。
redis 127.0.0.1:6379 FLUSHALL 为什么默认端口6379
意大利的一位广告女郎名字叫Merz全名Alessia Merz。
6379 Merz 三、Redis数据类型
3.1 key键类型 keys
查看当前库中所有的key 。
keys *有3个通配符 *, ? ,[] *: 通配任意多个字符?: 通配单个字符[]: 通配括号内的某1个字符 但是在实际生产环境中不建议使用该命令。新版本也进行了替代
[rootlocalhost src]# ./redis-cli --scan *
k1
exists
判断某个key是否存在返回1表示存在0不存在。
exists key示例
#查看k1是否存在如果存在返回1
127.0.0.1:6379 exists k1
(integer) 1# 查看k1 k2 k3是否存在如果k1 k2存在k3不存在则返回2
127.0.0.1:6379 exists k1 k2 k3
(integer) 2 注意 可以设置多个key只返回存在的个数但不返回哪一个存在/不存在。 type
查看当前key 所储存的值的类型。返回当前key所储存的值的类型如string 、list等。
type key示例
127.0.0.1:6379 type k1
stringdel
删除已存在的key不存在的 key 会被忽略。
del key示例
可以设置多个key返回删除成功的个数。
# 删除k1如果成功返回1失败返回0
del k1
# 删除k1 k2 k3如果k1 k2存在k3不存在则返回2
del k1 k2 k3
expire
给key设置time秒的过期时间。设置成功返回 1 。 当 key 不存在返回 0。
expire key time示例
# 给k1设置30秒后删除
127.0.0.1:6379 expire k1 30
(integer) 1应用场景是手机验证码 ttl
以秒为单位返回 key 的剩余过期时间。
ttl key示例
127.0.0.1:6379 ttl k1
(integer) 25注意 当 key 不存在时返回 -2 。 当 key 存在但没有设置剩余生存时间时返回 -1 。 否则以秒为单位返回 key 的剩余生存时间。 persist
移除给定 key 的过期时间使得 key 永不过期。
persist key
示例
persist k1
3.2 String类型 简介
String是Redis最基本的类型一个key对应一个value。String是二进制安全的意味着String可以包含任何数据比如序列化对象或者一张图片。String最多可以放512M的数据。
set
用于设置给定 key 的值。如果 key 已经存储其他值 set 就重写旧值且无视类型。
set key value
示例
127.0.0.1:6379 set k1 v1
OK
get
用于获取指定 key 的值。如果 key 不存在返回 nil 。
get key示例
127.0.0.1:6379 get k1
v1
append
将给定的value追加到key原值末尾。
append key value
示例
127.0.0.1:6379 append k2 aaa
(integer) 5
127.0.0.1:6379 get k2
20aaa注意 如果 key 已经存在并且是一个字符串 append 命令将 value 追加到 key 原来的值的末尾。如果 key 不存在 append 就简单地将给定 key 设为 value 就像执行 set key value 一样。 strlen
获取指定 key 所储存的字符串值的长度。当 key 储存的不是字符串值时返回一个错误。
127.0.0.1:6379 strlen k2
(integer) 5
setex
给指定的 key 设置值及time 秒的过期时间。如果 key 已经存在 setex命令将会替换旧的值并设置过期时间。
setex key time value 示例
#向Redis中设置一个k1的键值对并且10秒后过期
127.0.0.1:6379 setex k1 10 v1
OK 应用场景是短信验证码 setnx
只有在key不存在时设置key的值
setnx key value
示例
127.0.0.1:6379 setnx k1 v1
(integer) 0
127.0.0.1:6379 setnx k4 v4
(integer) 1
getrange
获取指定区间范围内的值类似between........and 的关系
getrange key start end
示例
127.0.0.1:6379 set k5 abcd123xxx
OK
127.0.0.1:6379 getrange k5 2 4
cd1
setrange
获取指定区间范围内的值类似between........and 的关系
setrange key offset value
示例
127.0.0.1:6379 set k6 abcd1234
OK
127.0.0.1:6379 setrange k6 1 xxx
(integer) 8
127.0.0.1:6379 get k6
axxx1234
incr
将 key 中储存的数字值增一。
incr key
示例
#因为Redis中不存在k1所以先初始化为0再递增值为1
127.0.0.1:6379 incr k1
(integer) 1
# incr k1 存在k1递增后k1的值为2
127.0.0.1:6379 incr k1
(integer) 2
# 如果value不是数字就会报错
127.0.0.1:6379 set k2 v2
OK
127.0.0.1:6379 INCR k2
(error) ERR value is not an integer or out of range 注意 如果 key 不存在那么 key 的值会先被初始化为 0 然后再执行 incr 操作。如字符串类型的值不能表示为数字、或者是其他类型那么返回一个错误。 decr
将 key 中储存的数字值减一。
decr key
示例
127.0.0.1:6379 decr k1
(integer) 1
127.0.0.1:6379 decr k1
(integer) 0
127.0.0.1:6379 decr k1
(integer) -1
127.0.0.1:6379 decr k1
(integer) -2
#如果
set k2 v2
decr k2 因为k2不为数值Redis返回一个错误 注意 如果 key 不存在那么 key 的值会先被初始化为 0 然后再执行 decr 操作。如字符串类型的值不能表示为数字、或者是其他类型那么返回一个错误。 incrby/decrby key step
将key存储的数字值按照step进行增减。
127.0.0.1:6379 incrby k1 10
(integer) 20 注意 如果 key 不存在那么 key 的值会先被初始化为 0 然后再执行 incrby/decrby 命令。如字符串类型的值不能表示为数字、或者是其他类型那么返回一个错误。 mset
同时设置一个或多个 key-value 。
mset key1 value1 key2 value2 示例
127.0.0.1:6379 mset k1 v1 k2 v2 k3 v3
OKmget
返回所有(一个或多个)给定 key 的值。
mget key1 key2示例
127.0.0.1:6379 mget k1 k2 k3
1) v1
2) v2
3) v3 注意: 如果给定的 key 里面有某个 key 不存在那么这个 key 返回特殊值 nil 。 getset
将给定key值设为value并返回key的旧值old value简单一句话先get然后立即set。
getset key value
示例
127.0.0.1:6379 getset k1 wcc
v1
127.0.0.1:6379 get k1
wcc
使用场景
value 除了是字符串以外还可以是数字。
计数器统计多单位的数量粉丝数对象缓存存储分布式锁
3.3 List类型 简介
List是简单的字符串列表按照插入顺序排序。你可以添加一个元素到列表的头部左边或者尾部右边。底层是一个双向链表对两段操作性能极高通过索引操作中间的节点性能较差。 lpush/rpush
从左边头部/右边尾部插入一个或多个值。
lpush/rpush key1 value1 value2 value3……示例
#从左边放入v1 v2 v3
127.0.0.1:6379 lpush k1 v1 v2 v3
(integer) 3 #从右边放入v4 v5 v6
127.0.0.1:6379 rpush k1 v4 v5 v6
(integer) 6 lrange
返回key列表中的start和end之间的元素包含start和end。 其中 0 表示列表的第一个元素-1表示最后一个元素。
lrange key start end
示例
127.0.0.1:6379 lrange k1 0 -1
1) v3
2) v2
3) v1
127.0.0.1:6379 lpop/rpop
移除并返回第一个值或最后一个值。
lpop/rpop key
示例
127.0.0.1:6379 lpop k1
v3
127.0.0.1:6379 rpop k1
v1注意 值在键在值光键亡。 lindex
获取列表index位置的值(从左开始)。
lindex key index 示例
127.0.0.1:6379 lindex k1 0
v2llen
获取列表长度。
llen key
示例
127.0.0.1:6379 llen k1
(integer) 1lrem
从左边开始删除与value相同的count个元素。
lrem key count value
示例
#从左边开始删除k1列表中2个v2元素
127.0.0.1:6379 lrange k1 0 -1
1) v7
2) v6
3) v5
4) v4
5) v3
6) v2
7) v1
8) v2
127.0.0.1:6379 lrem k1 2 v2
(integer) 2
127.0.0.1:6379 lrange k1 0 -1
1) v7
2) v6
3) v5
4) v4
5) v3
6) v1linsert
在列表中value值的前边/后边插入一个new value值从左开始。
linsert key before/after value newvalue
示例
# 在v1前面插入一个v8
127.0.0.1:6379 linsert k1 before v1 v8
(integer) 7
127.0.0.1:6379 lrange k1 0 -1
1) v7
2) v6
3) v5
4) v4
5) v3
6) v8
7) v1lset
将索引为index的值设置为value
lset key index value
示例
#将索引为0的值改为aaa
127.0.0.1:6379 lset k1 0 aaa
OK
127.0.0.1:6379 lrange k1 0 -1
1) aaa
2) v6
3) v5
4) v4
5) v3
6) v8
7) v1
使用场景
消息队列排行榜最新列表 3.4 Set类型 简介
与List类似是一个列表功能但Set是自动排重的当需要存储一个列表数据又不希望出现重复数据时Set是一个很好的选择。
Set是String类型的无序集合它底层其实是一个value为null的hash表所以添加、删除、查找的时间复杂度都是O(1)。 sadd
将一个或多个元素添加到集合key中已经存在的元素将被忽略。
sadd key value1 value2……
示例
#向集合中添加值最终只有v1 v2 v3 v4 v5 v6
127.0.0.1:6379 sadd k1 v1 v2 v2 v3 v4 v5 v6
smembers
取出该集合的所有元素。
smembers key
示例
127.0.0.1:6379 smembers k1
1) v2
2) v1
3) v3sismember
判断集合key中是否含有value元素如有返回1否则返回0。
sismember key value
示例
127.0.0.1:6379 sismember k1 v1
(integer) 1
127.0.0.1:6379 scard
返回该集合的元素个数。
scard key
示例
127.0.0.1:6379 scard k1
(integer) 3
127.0.0.1:6379 srem
删除集合中的一个或多个成员元素不存在的成员元素会被忽略。
srem key value1 value2……
示例
# 删除v1 v2
srem k1 v1 v2
spop
随机删除集合中一个元素并返回该元素。
spop key
示例
spop k1 随机删除一个元素并返回
srandmember
随机取出集合中count个元素但不会删除。
srandmember key count
示例
#随机取出集合中的2个元素
srandmember k1 2
smove
将value元素从sourcekey集合移动到destinationkey集合中。
smove sourcekey destinationkey value
示例
smove k1 k2 v5 将元素v5从集合k1中移动到集合k2 注意 如果 sourcekey集合不存在或不包含指定的 value元素则 smove 命令不执行任何操作仅返回 0 。 sinter
返回两个集合的交集元素。
sinter key1 key2
sunion
返回两个集合的并集元素。
sunion key1 key2
sdiff
返回两个集合的差集元素key1中的不包含key2
sdiff key1 key2
使用场景
黑白名单随机展示好友关注人粉丝感兴趣的人集合 3.4 Hash类型 简介
Hash是一个键值对的集合。Hash 是一个 String 类型的 field字段 和 value值 的映射表hash 特别适合用于存储对象。 Hash存储结构优化 如果field数量较少存储结构优化为类数组结构如果field数量较多存储结构使用HashMap结构
hset
给key集合中的field赋值value。相当于是为实体类的属性赋值此时的属性就相当于是key属性的值相当于是value。
hset key field value
示例
#为实体类user的属性name赋值为zhangsan
127.0.0.1:6379 hset user name zhangsan 注意 如果哈希表不存在一个新的哈希表被创建并进行 HSET 操作。如果字段已经存在于哈希表中旧值将被重写。 hget
从key哈希中取出field字段的值。相当于是获取实体类哪个属性的值。
hget key field
示例
#获取实体类user的name属性
127.0.0.1:6379 hget user name
zhangsanhmset
批量设置哈希的字段及值。
hmset key field1 value1 field2 value2……
示例
#为user实体类设置name、age、addres属性并赋值
127.0.0.1:6379 hmset user name zhangsan age 19 address shandong
OKhexists
判断指定key中是否存在某个属性。
hexists key field
示例:
#判断user实体类中是否存在name属性
127.0.0.1:6379 hexists user name
(integer) 1 注意 如果哈希表含有给定字段返回 1 。 如果哈希表不含有给定字段或 key 不存在返回 0 。 hkeys
获取该哈希中所有的field。获取该实体类的属性。
#获取user实体类的全部属性
127.0.0.1:6379 hkeys user
1) name
2) age
3) addresshvals key
获取该哈希中所有的value。获取该实体类的属性值。
hvals key示例
127.0.0.1:6379 hvals user
1) zhangsan
2) 19
3) shandonghincrby
为哈希表key中的field字段的值加上增量increment。
hincrby key field increment
示例
#为实体类user的属性age增1
127.0.0.1:6379 hincrby user age 1
(integer) 20hdel
删除哈希表 key 中的一个或多个指定字段不存在的字段将被忽略。
hdel key field1 field2……
示例
#删除user实体类的age和address属性
127.0.0.1:6379 hdel user age address
(integer) 2hsetnx
给key哈希表中不存在的的字段赋值 。
hsetnx key field value
示例
#为user中不存在的属性age赋值因为age属性不存在所以可以赋值。
127.0.0.1:6379 hset user age 10
(integer) 1#因为name属性不存在所以无法为该属性赋值
127.0.0.1:6379 hset user name zhangsan
(integer) 0 注意 如果哈希表不存在一个新的哈希表被创建并进行 hsetnx 操作。如果字段已经存在于哈希表中操作无效。如果 key 不存在一个新哈希表被创建并执行 hsetnx 命令。 使用场景
购物车存储对象 3.5 Zset 简介
Zset与Set非常相似是一个没有重复元素的String集合。不同之处是Zset的每个元素都关联了一个分数score这个分数被用来按照从低分到高分的方式排序集合中的元素。集合的元素是唯一的但分数可以重复。- 注意 因为元素是有序的所以可以根据分数score或者次序position来获取一个范围内的元素。 zadd
将一个或多个元素value及分数score加入到有序集key中。
zadd key score1 value1 score2 value2……
示例
#java分数是100c分数200c分数300
127.0.0.1:6379 zadd k1 100 java 200 c 300 C
(integer) 3注意 如果某个元素已经是有序集的元素那么更新这个元素的分数值并通过重新插入这个元素来保证该元素在正确的位置上。分数值可以是整数值或双精度浮点数。如果有序集合 key 不存在则创建一个空的有序集并执行 zadd 操作。 zrange
返回key集合中的索引start和索引end之间的元素包含start和end。
zrange key start end [withscores]
示例
#返回集合中全部的元素
127.0.0.1:6379 zrange k1 0 -1
1) java
2) c
3) C#返回集合中的元素和分数
127.0.0.1:6379 zrange k1 0 -1 withscores
1) java
2) 100
3) c
4) 200
5) C
6) 300注意 其中元素的位置按分数值递增(从小到大)来排序。 其中 0 表示列表的第一个元素-1表示最后一个元素。withscores是可选参数是否返回分数。 zrangebyscore
返回key集合中的分数minscore 和分数maxscore 之间的元素包含minscore 和maxscore 。其中元素的位置按分数值递增(从小到大)来排序。
zrangebyscore key minscore maxscore [withscores]示例
127.0.0.1:6379 zrangebyscore k1 100 300 [withscores]
1) java
2) c
3) Czincrby
为元素value的score加上increment的值。
zincrby key increment value
示例
#给Java加50
127.0.0.1:6379 zincrby k1 50 java
150zrem
删除该集合下value的元素。
zrem k1 php 删除php
zcount
统计该集合在minscore 到maxscore分数区间中元素的个数。 zcount key minscore maxscore
示例
zcount k1 100 300 统计100分到300分中间元素的个数
zrank
返回value在集合中的排名从0开始。
zrank key value
示例
zrank k1 c 返回c排名
使用场景
延时队列排行榜限流 3.6 itmaps类型较难理解 简介
在计算机中用二进制位作为存储信息的基本单位1个字节等于8位。
例如 abc 字符串是由 3 个字节组成计算机存储时使用其二进制表示abc分别对应的ASCII码是97、98、99对应的二进制是01100001、01100010、01100011在内存中表示如下 合理地使用位能够有效地提高内存使用率和开发效率。
Redis提供了Bitmaps这个 “数据结构” 可以实现对位的操作 setbit
设置Bitmaps中某个偏移量的值。
setbit key offset value
示例
redis中bitmaps可以用来统计用户信息eg活跃天数、打卡天数、登录天数
bitmaps位图都是操作二进制来进行记录就只有0和1两个状态
统计zhangsan4月份考勤情况第二个数字代表的是天第三个数字代表是否迟到1未迟到0迟到
127.0.0.1:6379 bitcount zhangsan
(integer) 0
127.0.0.1:6379 setbit zhangsan:4 1 1
(integer) 1
127.0.0.1:6379 setbit zhangsan:4 2 1
(integer) 1
127.0.0.1:6379 setbit zhangsan:4 3 0
(integer) 0
127.0.0.1:6379 setbit zhangsan:4 4 1
(integer) 1 注意 最后一个数字是偏移量的值倒数第二个叫偏移量。 getbit
获取Bitmaps中某个偏移量的值。
getbit key offset
示例
获取key的offset 的值。
127.0.0.1:6379 getbit zhangsan 3
(integer) 0bitcount
统计字符串被设置为1的bit数量。一般情况下给定的整个字符串都会被进行统计可以选择通过额外的start和end参数指定字节组范围内进行统计包括start和end0表示第一个元素-1表示最后一个元素。
bitcount key [start end]
示例
bitcount sign 获取整个字符串被设置为1的bit数量结果为3
如当前存在一个key为k1的bitmaps存储着[00000001,00000001,00000010,00000011]分别对应[1,1,2,3]。
setbit num 7 1
setbit num 15 1
setbit num 22 1
setbit num 30 1
setbit num 31 1bitcount num 1 2 统计索引1、2两个字节组中bit1的数量即统计00000001,00000010中bit1的数量结果为2
bitcount num 1 3 统计索引1、2、3三个字节组中bit1的数量即统计00000001,00000010,00000011中bit1的数量结果为4
bitcount num 0 -1 统计所有的字节组中bit1的数量结果为5
setbit设置或获取的是bit位的位置bitcount计算的是byte字节位置。
bitop
将多个bitmaps通过求交集/并集方式合并成一个新的bitmaps。
bitop and/or destkey sourcekey1 sourcekey2……
示例
bitop and k3 k1 k2 通过求交集将k1 k2合并成k3
bitop or k3 k1 k2 通过求并集将k1 k2合并成k3 使用场景
活跃天数打卡天数登录天数用户签到统计活跃用户统计用户是否在线实现布隆过滤器 3.7 Geospatia 简介
GEOGeographic,地理信息的缩写。该类型就是元素的二维坐标在地图上就是经纬度。Redis基于该类型提供了经纬度设置、查询、范围查询、距离查询、经纬度Hash等常见操作。
geoadd
用于存储指定的地理空间位置可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中。
geoadd key longitude latitude member
示例
# 将北京的经纬度和名称添加到china
geoadd china 116.405285 39.904989 beijing
# 将成都和上海的经纬度、名称添加到china
geoadd china 104.065735 30.659462 chengdu 121.472644 31.231706 shanghai geopos
从给定的 key 里返回所有指定名称(member)的位置经度和纬度不存在的返回 nil。
geopos key member [member ……]
示例
#返回china中名称为shanghai和beijing的经纬度
geopos china shanghai beijing
geodist
用于返回两个给定位置之间的距离。 geodist key member1 member2 [m|km|ft|mi] 参数说明 m 米默认单位。km 千米。mi 英里。ft 英尺。 # 返回shanghai和beijing之间的距离结果1067597.9668单位米
geodist chinacity shanghai beijing
# 返回shanghai和chengdu之间的距离结果1660.0198单位是千米
geodist chinacity shanghai chengdu km georadius
以给定的经纬度longitude latitude为中心 返回键包含的位置元素当中 与中心的距离不超过给定最大距离radius 的所有位置元素。 georadius key longitude latitude radius m|km|ft|mi 示例
#获取经纬度110 30为中心在china内1200公里范围内的所有元素。
georadius china 110 30 1200 km
使用场景 附近的电影院 附近的好友 离最近的火锅店 前提是将这些商铺的坐标放到redis 3.8 HyperLogLog 简介
在我们做站点流量统计的时候一般会统计页面UV(独立访客:unique visitor)和PV(即页面浏览量page view)。redis HyperLogLog是用来做基数统计的算法HyperLogLog的优点是在输入元素的数量或者体积非常非常大时计算基数所需的空间总是固定的、并且使很小的。
什么是基数
比如数据集{1,3,5,7,5,7,8}那么这个数据集的基数集为{1,3,5,7,8},基数(不重复元素)为5.基数估计就是在误差可接受的范围内快速计算基数。
pfadd
将所有元素参数添加到 Hyperloglog 数据结构中。
pfadd key element1 element2……
示例
如果至少有个元素被添加返回 1 否则返回 0。
pfadd book1 uid1 uid2 uid3 注意 添加元素到HyperLogLog中如果内部有变动返回1没有返回0。 pfcount
计算Hyperloglog 近似基数可以计算多个Hyperloglog 统计基数总数。
pfcount key1 key2……
示例
pfcount book1 #计算book1的基数结果为3
pfadd book2 uid3 uid4 #添加两个元素到book2中
pfcount book1 book2 #统计两个key的基数总数结果为5pfmerge
将一个或多个Hyperloglogsourcekey1 合并成一个Hyperloglog destkey 。
pfmerge destkey sourcekey1 sourcekey2……示例
比如每月活跃用户可用每天活跃用户合并后计算。
#将book1和book2合并成book结果为5
pfmerge book book1 book2 使用场景
基数不大数据量不大就用不上会有点大材小用浪费空间有局限性就是只能统计基数数量而没办法去知道具体的内容是什么和bitmap相比属于两种特定统计情况简单来说HyperLogLog 去重比 bitmaps 方便很多一般可以bitmap和hyperloglog配合使用bitmap标识哪些用户活跃。
网站PV统计网站UV统计统计访问量(IP数)统计在线用户数统计每天搜索不同词条的个数统计文章真实阅读数
四、Redis可视化工具Redis Destktop Manager带时间 4.1 下载Redis Desktop Manager
官网RESP.app (formerly Redis Desktop Manager) - GUI for Redis ® available on Windows, macOS, iPad and Linux. 或者使用文章配套的安装包。
4.2 连接Redis服务
关闭防火墙
systemctl stop firewalld.service在redis配置文件中关闭保护模式
protected-mode no开启远程访问
redis默认只允许本地访问要使redis可以远程访问可以修改redis.conf。 注释掉bind 127.0.0.1 可以使所有的ip访问redi 重启redis服务
#查看redis端口
lsof -i:6379#杀死redis进程
kill -9 PID#重启reids服务
[rootlocalhost src]# ./redis-server ../redis.conf- 出现16个库代表连接成功 五、Java整合Redis
5.1 Jedis操作 什么是Jedis
Jedis是Redis官方推荐的Java连接开发工具。
创建maven工程引入maven依赖
dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion3.6.0/version
/dependency
dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope
/dependencyJedis连接到redis并操作redis
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;import java.util.List;
import java.util.Set;public class TestJedis {Jedis jedis;//1.创建连接实例Beforepublic void init(){/** 第一个参数redis服务的ip* 第二个参数redis服务的端口*/jedis new Jedis(192.168.66.100,6379);}//2.Jedis-API:StringTestpublic void stringTest(){//设置一个键值对jedis.set(k1,v1);//通过key获取valueString k1 jedis.get(k1);System.out.println(k1);//对某一个key自增Long ires jedis.incr(k2);}//2.Jedis-API:KeysTestpublic void keysTest(){//返回所有的keySetString keys jedis.keys(*);//返回该key剩余过期时间Long time jedis.ttl(k1);}//3.Jedis-API:ListTestpublic void listTest(){//向list中添加数据jedis.lpush(list1,v1,v2,v3);//返回list全部数据ListString list jedis.lrange(list1,0,-1 );}//4.Jedis-API:SetTestpublic void setTest(){//向set中添加数据jedis.sadd(set1 ,v1,v2,v2,v3);//查看该集合中有多少个元素jedis.smembers(set1);}//4.Jedis-API:HashTestpublic void hashTest(){//设置一个hashjedis.hset(user,age,25);//获取该key的所有valuejedis.hvals(user);}//4.Jedis-API:ZsetTestpublic void zsetTest(){//向zset中添加一条数据jedis.zadd(zset1,100,java);//获取所有的值jedis.zrange(zset1,0,-1);}//5.Jedis-API:BitmapsTestpublic void bitmapsTest(){//将b1偏移量为0的位设置为1jedis.setbit(b1,0, 1);//获取b1偏移量为0的位jedis.getbit(b1,0);}//6.Jedis-API:GeospatiaTestpublic void geospatiaTest(){//添加一条地理信息数据jedis.geoadd(chinacity,130,110,beijing);}//7.Jedis-API:HyperloglogTestpublic void hyperloglogTest(){//将所有元素参数添加到 Hyperloglog 数据结构中。jedis.pfadd(book,c,java,php);}Afterpublic void close(){//1.关闭连接实例jedis.close();}
}注意 其实jedis中的方法基本同redis命令一致。 5.2 Spring-Data-Reids 简介
Spring-Data-Redis是spring大家族的一部分通过简单的配置访问Redis服务对Reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装RedisTemplate提供了Redis各种操作、异常处理及序列化支持发布订阅。
RedisTemplate介绍
Spring封装了RedisTemplate对象来进行对Redis的各种操作它支持所有的Redis原生的api。
org.springframework.data.redis.core
Class RedisTemplateK,V注意 K模板中的Redis key的类型模板中的Redis key的类型通常为String如RedisTemplateString, Object。V模板中的Redis value的类型 RedisTemplate中定义了对5种数据结构操作 redisTemplate.opsForValue();//操作字符串 redisTemplate.opsForHash();//操作hash redisTemplate.opsForList();//操作list redisTemplate.opsForSet();//操作set redisTemplate.opsForZSet();//操作有序set StringRedisTemplate与RedisTemplate 两者的关系是StringRedisTemplate继承RedisTemplate。 两者的数据是不共通的也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据RedisTemplate只能管理RedisTemplate中的数据。 SDR默认采用的序列化策略有两种一种是String的序列化策略一种是JDK的序列化策略。 StringRedisTemplate默认采用的是String的序列化策略保存的key和value都是采用此策略序列化保存的。 RedisTemplate默认采用的是JDK的序列化策略保存的key和value都是采用此策略序列化保存的。 创建springboot项目并添加依赖 dependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis-reactive/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdio.projectreactor/groupIdartifactIdreactor-test/artifactIdscopetest/scope/dependency/dependencies在application.properties中配置
#Redis服务器连接地址
spring.redis.host192.168.56.31
#Redis服务器连接端口
spring.redis.port6379
#连接池最大连接数使用负值表示没有限制
spring.redis.pool.max-active8
#连接池最大阻塞等待时间使用负值表示没有限制
spring.redis.pool.max-wait-1
#连接池中的最大空闲连接
spring.redis.pool.max-idle8
#连接池中的最小空闲连接
spring.redis.pool.min-idle0
#连接超时时间毫秒
spring.redis.timeout30000自定义序列化
RedisTemplate默认采用的是JDK的序列化策略保存的key和value都是采用此策略序列化保存的。该配置是将其序列化的方式改为json序列化。
package com.zj.redis.conf;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** 自定义序列化方式*/
Configuration
public class RedisConfig {Beanpublic RedisTemplateString,Object redisTemplate(RedisConnectionFactory redisConnectionFactory){RedisTemplateString, Object redisTemplate new RedisTemplate();redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.setConnectionFactory(redisConnectionFactory);return redisTemplate;}
}没有配置自定义序列化之前 配置自定义序列化之后注意此时是json类型 package com.zj.redis;import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;import javax.annotation.Resource;
import java.util.Set;SpringBootTest
class RedisApplicationTests {Resourceprivate RedisTemplate redisTemplate;/** 使用RedisTemplate实例操作redis* *///操作字符串Testvoid contextLoads() {//添加数据(key是name,value是zhangsan)redisTemplate.opsForValue().set(name, zhangsan);//获取数据System.out.println(redisTemplate.opsForValue().get(name));}//操作listTestvoid contextLoads2(){//添加数据redisTemplate.opsForList().rightPush(age,23);redisTemplate.opsForList().rightPush(age,24);redisTemplate.opsForList().rightPush(age,25);//获取最右边的数据System.out.println(redisTemplate.opsForList().rightPop(age));}//操作HashTestvoid contextLoads3(){//添加redisTemplate.opsForHash().put(user,name,张三);redisTemplate.opsForHash().put(user,age,12);redisTemplate.opsForHash().put(user,address,临沂市);//获取System.out.println(redisTemplate.opsForHash().get(user, name));}//操作setTestvoid contextLoads4(){//添加redisTemplate.opsForSet().add(verse,两岸猿声啼不住轻舟已过万重山。,莫愁前路无知己天下谁人不识君。,大鹏一日同风起扶摇直上九万里。);//获取Set verse redisTemplate.opsForSet().members(verse);System.out.println(verse);//获取元素长度System.out.println(redisTemplate.opsForSet().size(verse));}//操作ZSetTestvoid contextLoads5(){//添加元素redisTemplate.opsForZSet().add(programmer,Dennis MacAlistair Ritchie,100);redisTemplate.opsForZSet().add(programmer,Linus Benedict Torvalds,99);redisTemplate.opsForZSet().add(programmer,Bjarne Stroustrup ,98);redisTemplate.opsForZSet().add(programmer,Brain Wlison Kernighan,97);//获取元素Set programmer redisTemplate.opsForZSet().range(programmer, 0, -1);System.out.println(programmer);//通过分数获取元素Set programmer1 redisTemplate.opsForZSet().rangeByScore(programmer, 90, 100);System.out.println(programmer1);}}