1、NoSQL数据库简介

  • 能解决cpu和io压力
  • 能直接作为缓存使用,减少io操作,

    1、session问题多实例之后解决方案

  • 存储到客户端cookie(有安全问题)

  • session复制(会导致内存浪费等问题)
  • 存储到nosql数据库

    2、解决IO压力

    image.png

    3、NoSQLS数据库概述

    NoSQL即不仅仅是SQL

  • 不遵循SQl

  • 不支持ACID
  • 远超与SQL的性能

    4、NoSQL适用场景

  • 对数据高并发的读写

  • 海量数据的读写
  • 对数据高可扩展性的

    5、NoSQl不适用场景

  • 需要事物支持

  • 基于sql的结构化查询存储,处理复杂的关系,需要即席查询
  • (用不着sql的和用了sql也不行的情况,亲高考了用NoSql)

    2、安装

    1、概述

  • Redis是一个开源的key-value存储系统

  • 和Memcached类似,它支持存储的value类型相对更多,包括sring(字符串)、list(链表)set(集合),zset(sorted set —有序集合)和hash(哈希类型)
  • 这些数据类型都支持 push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的
  • 在此基础上,Redis支持各种不同方式的排序
  • 与memCache一样,为了保存效率,数据都是缓存在内存中
  • 区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件。
  • 并且在此基础上实现了master-slave同步

    2、应用场景

  • 高频次、访问热门的数据,降低数据库IO

  • 分布式架构,做session共享

image.png

3、安装

1、环境搭建 (mac安装)

1、下载资源

https://redis.io/download

2、解压

  1. tar zxvf redis-6.2.5.tar.gz

3、切换进入解压目录

  1. cd /usr/local/redis-5.0.4/

4、编译

  1. sudo make

编译成功后,会有一个提示: It’s a good idea to run ‘make test’
(这里可能会有“invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at:/Library/Developer/CommandLineTools/usr/bin/xcrun”问题,解决方法很简单,就是在命令行中执行 xcode-select —install,然后下载,安装完成后,再重新编译即可)

5、编译test

sudo make test

成功后提示: All tests passed without errors

6、安装

sudo make install

成功后提示: It’s a good idea to run ‘make test’!

7、运行

redis-server

4、Redis 客户端AnotherRedisDesktopManager(mac)

https://github.com/qishibo/AnotherRedisDesktopManager/releases 工具下载安装

2、安装(linux)

1、下载

https://redis.io/download

2、上传到linux压缩包

解压文件

tar -xvf xxx.tar

3、安装gcc编译文件

yum install gcc

4、进入解压文件夹进行 make命令操作

  • 如果出现了一个—Jemalloc/jemalloc 没有那个文件
    • 原因是可能没有gcc环境
  • 就运行make distclean

    sudo make
    

    5、安装编译好的文件

    sudo make install
    

    安装一般会安装在/usr/local/bin/下
    可以使用

    which 命令进行查看命令位置
    

    4、查看目录下各个文件

  • redis-benchmark:性能测试工具,可以再自己本机运行,看看自己本机性能如何

  • redis-check-aof:修复有问题的AOF文件
  • redis-check-dump:修复有问题的dump.rdb文件
  • redis-sentinel:Redis集群使用
  • redis-server:Redis服务器启动命令
  • redis-cli:客户端,操作入口

    5、启动

    1、前台启动

    直接开打命令工具,运行命令

    redis-server
    

    2、后台启动

    1、使用cp命令把redis.conf文件进行一个复制

  • 先进入刚刚解压的文件夹中,文件夹根目录下有一个redis.conf文件

    cp redis.conf /etc/
    

    2、修改redis.conf文件 daemonize 为yes

    vi redis.conf
    修改文件
    /daemon    输入进行搜索
    esc+:wq进行保存
    

    image.png

    3、启动redis

  • 启动刚刚我们修改过的redis.conf文件

    redis-server /etc/redis.conf
    

    4、使用ps命令进行进程查看

    ps -aux | grep redis
    

    image.png

    5、redis-cli命令进行客户端

  • 本机登录比较简单如下

image.png

  • 远程登录
    redis-cli -h host -p port -a password
    -h 服务器地址 -p 端口号 -a 密码
    

    6、关闭

    1、可以使用ps 查看进程号 然后使用kill -9 进程号进行关闭

    [root@localhost etc]# ps -aux | grep redis
    root     20845  0.1  0.1 162400  9912 ?        Ssl  16:49   0:00 redis-server 127.0.0.1:6379
    root     21091  0.0  0.0 112720   968 pts/0    S+   16:49   0:00 grep --color=auto redis
    [root@localhost etc]# kill -9 20845
    [root@localhost etc]# ps -aux | grep redis
    root     21425  0.0  0.0 112720   972 pts/0    S+   16:50   0:00 grep --color=auto redis
    [root@localhost etc]#
    

    2、也可以使用redis-cli 登录进去 然后shutdown命令进行关闭

    ```shell [root@localhost etc]# redis-cli 127.0.0.1:6379> ping PONG 127.0.0.1:6379> shutdown
<a name="zyczk"></a>
# 3、相关知识
<a name="7qACI"></a>
## 1、默认端口6379

- 由来 Alessia Merz
- Merz在键盘手机的键盘上对应的是6379
<a name="WCISz"></a>
## 2、默认16个数据库

- 类似数组下表从0开始,初始默认使用0号库
- 使用命令select <dbid>来切换数据库 如select 8
- 统一密码管理,所以库同样密码
- dbsize 查看当前数据库的key的数量
- flushdb 清空当前库
- flushall通杀全部库
<a name="2G4n0"></a>
## 3、Redis是单线程+多路IO复用技术
概念分析

- 串行:阻塞IO,一件事一件事的做,在做当前事时,不能做其他事,有等待
- 多线程+锁:非阻塞IO,一直重复做当前的事,没有等待
- 单线程+多路IO复用:做某件事情需要一定的时间,可以监视这件事,我们可以做其他的事

![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1629080485380-8862f658-deac-4f3c-a333-6fc3bfdb8f91.png#crop=0&crop=0&crop=1&crop=1&height=599&id=bwbyd&margin=%5Bobject%20Object%5D&name=image.png&originHeight=599&originWidth=939&originalType=binary&ratio=1&rotation=0&showTitle=false&size=155565&status=done&style=none&title=&width=939)
<a name="CojqU"></a>
# 4、常用5大数据类型操作
<a name="1ylrr"></a>
## 1、命令
<a name="YrNJz"></a>
### 1、set(设置值)
```shell
set key value

2、keys(列出键)

127.0.0.1:6379> keys *
1) "k3"
2) "k1"
3) "/login"
4) "k2"

3、exists

  • 判断某个key是否存在

    127.0.0.1:6379> exists k1
    (integer) 1
    

    4、type

  • 判断key的存储类型 ```shell 127.0.0.1:6379> type k1 string

<a name="atWxD"></a>
### 5、del

- 删除某个key
```shell
127.0.0.1:6379> del k1
(integer) 1

6、unlink

  • 根据value选择非阻塞删除

    127.0.0.1:6379> unlink k2
    (integer) 1
    

    7、expire

  • 设置key的过期时间

    127.0.0.1:6379> expire k3 20
    (integer) 1
    

    8、ttl

  • 查看还有多少秒过期

  • 值类型

    • -2表示已经过期
    • -1表示永远不过期
    • 其他值表示还有多少秒过期时间
      127.0.0.1:6379> ttl k3
      (integer) -2
      

      9、select

  • 切换库

  • 库中0号库开始

    127.0.0.1:6379> select 2
    OK
    

    10、dbsize

  • 查看数据库的key数量

    127.0.0.1:6379> dbsize
    (integer) 2
    

    11、flushdb和flushall

  • flushdb 清空当前库

  • flushall通杀全部库

    127.0.0.1:6379> flushdb
    OK
    127.0.0.1:6379> flushall
    OK
    

    2、字符串(String)

    1、简介

  • String是Redis最基本的类型,String类型是二进制安全的,意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象

  • String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M

    2、命令

  • set:设置值

  • get:获取值
  • append:追加值
  • strlen:获取长度
  • setnx:只有key不存在的时候才能设置成功,不然设置不了
  • incr:可以对存储的数值进行加一操作
    • 如果值是空的就直接为1 ,其他情况加1
  • incrby key 2:可以自定义加的操作的一次加的步数 ```shell 127.0.0.1:6379> set number 11 OK 127.0.0.1:6379> incrby number 13 (integer) 24 127.0.0.1:6379> get number “24”

- decr:只对数值类型减一操作
   - 对空的值减一操作,就是直接变成-1
- decrby:自定义一次减多少
   - 对空的值直接就是直接一次减多少的设置
- mset k1 v1 k2 v2 k3 v3:设置多个值
- mget k1 k2 k3:获取多个值
- msetnx k1 v1 k2 v2:如果有一个值存在,那都设置失败,原子性操作
- getrange key 3 10:表示取key这个键的从index 3-10 包含头和尾巴
- setex key 过期时间(秒):在设置值的时候就可以设置过期时间
   - setex key seconds value
```shell
127.0.0.1:6379> setex change 10 jfewjfjfajfda 
OK
127.0.0.1:6379> ttl change

3、数据结构(Value值)

String的数据结构为简单动态字符串(Simple Dynamic String,缩写SDS)。是可以修改的字符串,内部结构实现上雷士Java的ArrayList,采用预分配冗余空间的方式来减少内存的平凡分配
image.png
如图中所示,内部为当前字符串实际分配的空间capacity一般要高于实际字符串长度len。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。需要注意的是字符串最大长度为512M。

3、原子性:

incr原子性
所谓原子操作是指不会被线程调度机制打断的操作:
这种操作一旦开始,就一直运行到结束,中间不会有任何context switch(切换到另一个线程)

  • (1)在单线程中,能够在单条指令中完成的操作都可以认为是原子操作,因为中断只能发生于指令之间
  • (2)在多线程中,不能被其他进程(线程)打断的操作就叫原子操作。Redis单命令的原子性主要得益于Redis的单线程

    4、单键多值

    1、简介

    Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
    他的底层实际是一个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能灰比较差
    image.png

    2、常用命令

  • lpush k1 v1 v2 v3 :从左边加入值,想象一下是拥入的放入的话是按照顺从左开始放入的 v3 v2 v1

  • lrange k1 0 -1 :表示取所有的值 取的话是从左边开始取的
    • lrange k1 0 2 表示取 第一 第二 第三个值 如果里面只有1个值 那就只取出一个值
  • lindex k1 0:表示取某个下标的值,从左到右
  • llen k1 获取长度

    127.0.0.1:6379> lpush h 1 2 3 4
    (integer) 4
    127.0.0.1:6379> lrange h 0 -1 
    1) "4"
    2) "3"
    3) "2"
    4) "1"
    
  • rpush k2 v1 v2 v3:从右边放入,从左边取出来就是 v1 v2 v3

    127.0.0.1:6379> rpush h1 1 2 3 4
    (integer) 4
    127.0.0.1:6379> lrange h1 0 -1
    1) "1"
    2) "2"
    3) "3"
    4) "4"
    
  • lpop :从左边吐出一个值,值在键在,值光键亡

  • rpop:从右边吐出一个值,值在键在,值光键亡
  • rpoplpush 从key的右边取出一个值 插入到key2的左边
  • linsert: before/after :插入某个值,在某个键的前面或者后面插入值

    127.0.0.1:6379> linsert h before "3" 哈哈
    (integer) 7
    127.0.0.1:6379> lrange h 0 -1
    1) "13"
    2) "\xe5\x93\x88\xe5\x93\x88"
    3) "3"
    4) "2"
    5) "1"
    6) "11"
    7) "12"
    
  • lrem 删除个数 从左边开始删除某个值,并且删除几个

    127.0.0.1:6379> lpush tmp 33 22 22 11 33 22 44 22
    (integer) 13
    127.0.0.1:6379> lrange tmp 0 -1
    1) "22"
    2) "44"
    3) "22"
    4) "33"
    5) "11"
    6) "22"
    7) "22"
    8) "33"
    127.0.0.1:6379> lrem tmp 2 22
    (integer) 2
    127.0.0.1:6379> lrange tmp 0 -1
    1) "44"
    2) "33"
    3) "11"
    4) "22"
    5) "22"
    6) "33"
    
  • lset 当列表key下表为index的值替换成value

    127.0.0.1:6379> lrange tmp 0 -1
    1) "44"
    2) "33"
    127.0.0.1:6379> lset tmp 0 11
    OK
    127.0.0.1:6379> lrange tmp 0 -1
    1) "11"
    2) "33"
    

    3、数据结构

    List的数据结构为快速链表quickList,首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即使压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next
    image.png
    Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余

    5、集合Set

    1、简介

    Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择 ,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。Redis的Set是string类型的无序集合。它底层其实是一个value为null的的hash表,所以添加删除,查找的复杂度都是O(1)
    一个算法,随着数据的增加,执行时间的长短,如果是O(1),数据增加,查找数据的时间不变

    2、命令

  • sadd 添加一个或多个值加入,已经存在的值被忽略

  • smembers取出该集合的所有值
  • sismember判断集合是否为含有该值,有1,没有0

    127.0.0.1:6379> sadd name 11 22
    (integer) 2
    127.0.0.1:6379> smembers name
    1) "11"
    2) "22"
    127.0.0.1:6379> sismember name 11
    (integer) 1
    127.0.0.1:6379> sismember name 23
    (integer) 0
    
  • scard:返回元素个数

  • srem:删除集合中的某个元素
  • spop随机从该集合中吐出一个值
  • srandmember随机从该集合中取出n个值。不会从集合中删除
  • smovevalue 把集合中一个值从一个集合移动到另一个集合

    127.0.0.1:6379> smembers name
    1) "11"
    127.0.0.1:6379> smove name name1 11
    (integer) 1
    127.0.0.1:6379> smove name name1 22
    (integer) 0
    127.0.0.1:6379> smembers name1
    1) "11"
    127.0.0.1:6379> smembers name
    (empty array)
    127.0.0.1:6379>
    
  • sinter 返回两个集合的交集元素 (交集就是两个集合都有的数组)

  • sunion 返回两个集合的并集元素(并集就是两个集合所有的数据)
  • sdiff返回两个集合的差集元素(key1中的,不包含key2中的)

    3、数据结构

    Set数据结构是dict字典,字典是用哈希表实现的

  • Java中HansSet的内部实现使用的是HansMap,只不过所有的value都指向同一个对象。

  • Redis的set结构也是一样,它的内部也使用hash结构,所有的value都指向同一个内部值

6、Redis哈希(Hash)

1、简介

Redis hash是一个键值对集合。
Redis hash是一个sring类型的field和value的映射表,hash特别适合用于存储对象。类似Java里面的Map
用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储主要有以下2中存储方式:
image.png
image.png

2、命令

  • hset 存储数据

    127.0.0.1:6379> hset user:1 id 1
    (integer) 1
    
  • hget 取值

    127.0.0.1:6379> hget user:1 id
    "1"
    
  • hmset 批量设置值

  • hexists查看哈希表中key 给定的field是否存在
  • hkeys 列出该hash集合的所有field
  • hvals 列表该hash集合的所有value
  • hincrby 为哈希表key中的域field的值加上增量

    127.0.0.1:6379> hget user:1 id
    "1"
    127.0.0.1:6379> hincrby user:1 id 2
    (integer) 3
    127.0.0.1:6379> hget user:1 id
    "3"
    
  • hsetnx 将哈希表key中的域key中的field的值设置为value,当且仅当域field不存在

3、数据结构

Hash类型对应的数据结构是两种:ziplist(压缩列表),hshtable(哈希表)。当field-value长度较短且个数较少时,使用ziplist,否者使用hashtable

7、有序集合Set

1、简介

Redis有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合。不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复了。因为元素是有序的,所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。
访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的只能列表。

2、命令

  • zadd ,将一个或多个member元素以及score值加入到有序key当中
  • zrange [WITHSCORES]返回有序集key中,下表在之间的元素

    127.0.0.1:6379> zadd h 20 java 30 c++ 40 bb
    (integer) 3
    127.0.0.1:6379> zrange h 0 -1
    1) "java"
    2) "c++"
    3) "bb"
    127.0.0.1:6379> zrange h 0 -1 withscores
    1) "java"
    2) "20"
    3) "c++"
    4) "30"
    5) "bb"
    6) "40"
    
  • zrangebyscore key min max [withscores][limit offset count]返回有序集key中,所有score值介于min和max之间(包括等于min或max)的成员。有序集成员按score值递增(从小到大)次序排列。

    127.0.0.1:6379> zrangebyscore h 10 500 WITHSCORES 
    1) "java"
    2) "20"
    3) "c++"
    4) "30"
    5) "bb"
    6) "40"
    
  • zrevrangebyscore key max min [withscores] [limit offset count]同上,改为从大道小排序

    127.0.0.1:6379> zrevrangebyscore h 500 10 withscores
    1) "bb"
    2) "40"
    3) "c++"
    4) "30"
    5) "java"
    6) "20"
    
  • zincrby 为元素的score加上增量

    127.0.0.1:6379> zincrby h 20 bb
    "60"
    127.0.0.1:6379> zrevrangebyscore h 500 10 withscores
    1) "bb"
    2) "60"
    3) "c++"
    4) "30"
    5) "java"
    6) "20"
    
  • zrem 删除指定值的值

  • zcount 统计该集合,分数区间内的元素个数
  • zrank 返回该值在集合中的排名,从0开始

    127.0.0.1:6379> zrevrangebyscore h 500 10 withscores
    1) "bb"
    2) "60"
    3) "c++"
    4) "30"
    5) "java"
    6) "20"
    127.0.0.1:6379> zrank h java
    (integer) 0
    127.0.0.1:6379> zrank h bb
    (integer) 2
    127.0.0.1:6379> zrank h c++
    (integer) 1
    

    3、数据结构

    SortedSet(zset)是Redis提供的一个非常特别的数据结构,一方面它等价于Java的数据结构Map,可以给每个元素value赋予一个权重score,另一方面它又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过score的范围来获取元素的列表。
    zset底层使用了两个数据结构
    (1)hash,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。
    (2)跳跃表,跳跃表的目的在于给元素value排序,根据score的范围获取元素列表

    8、跳跃表(跳表)

    1、简介

    有序集合在生活中比较常见,例如根据成绩对学生排名,根据得分对玩家排名等。对于有序集合的底层实现,可以用数组,平衡树,链表等。数组不便元素的插入、删除;平衡树或红黑树虽然效率高但结构复杂;链表查询需要遍历所有效率低,Redis采用的是跳跃表。跳跃表效率堪比红黑树,实现远比红黑树简单

    2、示例

    对比有序链表和跳跃表,从链表中查询出51
    (1)有序链表
    image.png
    要查找值为51的元素,需要从第一个元素开始依次查找,比较才能找到,共需要6次比较
    (2)跳跃表
    image.png

  • (1)从第二次开始,1节点比51节点小,向后比较

  • (2)21节点比51节点小,继续向后比较,后面就是NULL了,所以从21节点向下到1层
  • (3)在第一层,41节点比51节点小,继续向后,61节点比51节点大,所以从41向下
  • (4)在第0层,51节点为要查找的节点,节点被找到,共查了4次

从此可以看出跳跃表比有序链表效率要高

5、详细配置

1、配置远程访问

  • bind 127.0.0.1 -::1注释掉
  • protected-mode改为no

    1、bind 127.0.0.1 -::1

  • 用来绑定某个id能访问,当前表示只能自己本机访问,所以注释掉

image.png

2、protected-mode

默认是保护模式开的,就不能被外部访问,所以我们改为no
image.png

2、密码设置

1、方式一

配置文件中找到requirepass(默认是没密码的)
注释打开,修改为自己想要的密码,然后保存重启redis服务器
image.png

2、方式二

登录redis-cli(登录在第2章5小节中有介绍)客户端然后使用命令修改

  • 获取当前密码

    192.168.1.154:6379> config get requirepass
    1) "requirepass"
    2) "qwerasdf123"
    
  • 设置密码(修改的密码不需要重新登录)

    192.168.1.154:6379> config set requirepass 123
    OK
    192.168.1.154:6379> config get requirepass
    1) "requirepass"
    2) "123"
    
  • 密码修改之后重新授权

    192.168.1.154:6379> auth 123
    OK
    

    3、满内存相关配置

    1、maxclients

  • 最大连接数,默认是不设置的10000

image.png

2、maxmemory-policy

内存满的时候redis将会尝试移除内部数据
通过maxmemory-policy来设置规则

  • volatile-lru:使用LRU算法移除key,只对设置了过期时间的键:(最近最少使用)
  • allkeys-lru:在所有集合key中,使用LRU算法移除key
  • volatile-radom:在过期集合中移除随机的key,值对设置了过期时间的键
  • allkeys-random:在所有集合key中,移除随机的key
  • volatile-ttl:移除那些TTL值最小的key,即那些最近要过期的key
  • noeviction:不进行移除。针对写操作,只是返回错误信息 ```shell

    MAXMEMORY POLICY: how Redis will select what to remove when maxmemory

    is reached. You can select one from the following behaviors:

    #

    volatile-lru -> Evict using approximated LRU, only keys with an expire set.

    allkeys-lru -> Evict any key using approximated LRU.

    volatile-lfu -> Evict using approximated LFU, only keys with an expire set.

    allkeys-lfu -> Evict any key using approximated LFU.

    volatile-random -> Remove a random key having an expire set.

    allkeys-random -> Remove a random key, any key.

    volatile-ttl -> Remove the key with the nearest expire time (minor TTL)

    noeviction -> Don’t evict anything, just return an error on write operations.

    #

    LRU means Least Recently Used

    LFU means Least Frequently Used

    #

    Both LRU, LFU and volatile-ttl are implemented using approximated

    randomized algorithms.

    modify existing keys. A few examples are: SET, INCR, HSET, LPUSH, SUNIONSTORE,

    #

    Both LRU, LFU and volatile-ttl are implemented using approximated

    randomized algorithms.

    #

    Note: with any of the above policies, when there are no suitable keys for

    eviction, Redis will return an error on write operations that require

    more memory. These are usually commands that create new keys, add data or

    modify existing keys. A few examples are: SET, INCR, HSET, LPUSH, SUNIONSTORE,

    SORT (due to the STORE argument), and EXEC (if the transaction includes any

    command that requires memory).

    #

    The default is:

    #

    maxmemory-policy noeviction

<a name="BSPFl"></a>
### 3、maxmemory-samples(样本数量)

- 设置样本数量,URL算法和最小TTL算法并非是精确的算法,而是估算值,所以你可以设置样本的大小,redis默认会检查这么多个key并选择其中LRU的那个。
- 一般设置3到7的数字,数值越小样本越不准确,但性能消耗越小。
```shell
# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated
# algorithms (in order to save memory), so you can tune it for speed or
# accuracy. By default Redis will check five keys and pick the one that was
# used least recently, you can change the sample size using the following
# configuration directive.
#
# The default of 5 produces good enough results. 10 Approximates very closely
# true LRU but costs more CPU. 3 is faster but not very accurate.
#
# maxmemory-samples 5

4、端口号

1、port 端口号

image.png

5、后台启动配置

1、daemonize

  • 设置是否后台启动
    • yes:后台启动
    • no:不后台启动(默认)

image.png

5、其他配置

1、tcp-backlog

  • 设置tcp的backlog,backlog其实是一个连接队列,backlog队列总和=未完成三次握手队列+已经完成三次握手队列。
  • 在高并发环境下你需要一个高backlog值来避免慢客户端连接问题
  • 注意linux内核会将这个值减小到/proc/sys/net/core/somaxconn的值(128),所以需要确认增大/proc/sys/net/sore/somaxconn和/proc/sys/net/ipv4/tcp_max_syn_backlog(128)两个值来达到想要的效果

image.png

2、timeout

如果我们连接上多久不操作就会断开连接,如果0就是不会断开

3、tcp-keepalive

  • 心跳监测

image.png

4、pidfile

  • 保存进程号文件

image.png

5、loglevel

  • 日志级别
    • debug:开发阶段
    • verbose:有用的信息
    • notice:生产环境
    • warning:有用的

image.png

6、logfile

日志输出路径默认为空
image.png

7、database

数据库个数,默认使用的是0号库
image.png

6、Redis的发布和订阅

1、什么是发布和订阅

Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息
Redis客户端可以订阅任意数量的频道

2、命令

1、打开一个客户端订阅频道

192.168.1.154:6379> subscribe channel1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1

2、打开另外一个客户端发布频道消息

192.168.1.154:6379> publish channel1 11
(integer) 1

3、接收到消息

192.168.1.154:6379> subscribe channel1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
1) "message"
2) "channel1"
3) "11"

7、Redis6新数据类型

1、Bitmaps

  • 统计用户活跃数据等

    1、简介

    image.pngimage.png

    2、命令

    1、setbit 设置值

    image.png
    192.168.1.154:6379> setbit user:2021 1101 1
    (integer) 0
    192.168.1.154:6379> setbit user:2021 1 1
    (integer) 0
    192.168.1.154:6379> setbit user:2021 12 1
    (integer) 0
    192.168.1.154:6379> setbit user:2021 12 1
    (integer) 1
    image.png

    2、getbit 获取值

    192.168.1.154:6379> getbit user:2021 12
    (integer) 1
    192.168.1.154:6379> getbit user:2021 10
    (integer) 0
    

    3、bitcount

    统计字符串被设置为1的bit数。一般情况下,给定的整个字符串都会被进行计数,通过制定额外的start或end参数,可以让计数值在特定的位上进行,start和end参数的设置,都可以使用负数值:比如-1表示最后一位,而-2表示倒数第二位,start、end是指bit组的字节的下标数,二者皆包含
    (1)格式
    bitcount[start end]统计字符串从start字节到end字节比特值为1的数量

    192.168.1.154:6379> bitcount user:2021 0 -1
    (integer) 3
    

    4、bitop

    bitop and(or/not/xor)
    bitop是一个复合操作,它可以做多个Bitmaps的and(交集)、or(并集)、not(非)、xor(异或)操作并将结果保存在destkey中

    192.168.1.154:6379> setbit users:20211104 1 1
    (integer) 0
    192.168.1.154:6379> setbit users:20211104 2 1
    (integer) 0
    192.168.1.154:6379> setbit users:20211104 23 1
    (integer) 0
    192.168.1.154:6379> setbit users:20211104 26 1
    (integer) 0
    192.168.1.154:6379> setbit users:20211105 26 1
    (integer) 0
    192.168.1.154:6379> setbit users:20211105 1 1
    (integer) 0
    

    计算出两天都访问过网站的用户数量

  • 如下代码就是把 把2021年11月04日的 和2021年11月05日的用户访问记录都保存进去

  • 并且用bitop and 把两天的数据合并保存到users:and:20211104_05这个key中,使用bitcount统计查看有2个用户都在这两天访问过

    192.168.1.154:6379> setbit users:20211104 1 1
    (integer) 0
    192.168.1.154:6379> setbit users:20211104 2 1
    (integer) 0
    192.168.1.154:6379> setbit users:20211104 23 1
    (integer) 0
    192.168.1.154:6379> setbit users:20211104 26 1
    (integer) 0
    192.168.1.154:6379> setbit users:20211105 26 1
    (integer) 0
    192.168.1.154:6379> setbit users:20211105 1 1
    (integer) 0
    192.168.1.154:6379> bitop and users:and:20211104_05 users:20211104 users:20211105
    (integer) 4
    192.168.1.154:6379> bitcount users:and:20211104_05
    (integer) 2
    

    两天都访问过的有2个用户

    3、Bitmaps与set对比

    假设网站有1亿用户,每天独立访问的用户有5千万,如果每天用集合类型和Bitmaps分别存储活跃用户可以得到表
    image.png很明显,这种情况下使用Bitmaps能节省很多的内存空间,尤其是随着时间推移节省的内存还是非常可观的
    image.png
    但是Bitmaps并不是万油金,假如该网站每天的独立访问用户很少,例如只有10万(大量的僵尸用户),那么两者的对比如下表所示,很显然,这时候使用Bitmaps就不太合适了,因为基本上大部分位都是0
    image.png

    2、HyperLogLog

  • 统计用户访问数,独立ip数等,搜索记录

    1、简介

  • 在工作当中,我们经常会遇到与统计相关的功能需求,比如统计网站PV(PageView页面访问量),可以使用Redis的incr,incrby轻松实现

  • 但是UV(UniqueVisitor,独立访客),独立IP数,搜索记录数等需要去重合计数的问题如何解决?这种求集合中不重复元素个数的问题称为基数问题。

解决基数问题有很多种方案:
(1)数据存储在MySql表中,使用distinct count计算不重复个数
(2)使用Redis提供的hash,set,bitmaps等数据结构来处理
以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大,对于非长大的数据集是不切实际的
能否能够降低一定的精度来平衡存储空间?Redis推粗了HyperLogLog

  • Redis HyperLogLog是用来做基数统计的算法,HyperLogLog的优点是:
    • 在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的,并且是很小的
  • 在Redis里面,每个HyperLogLog键只需要花费12kb内存,就可以计算接近2^64个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比
  • 但是,因为HyperLogLog只会根据输入元素来计算基数,而不会存储输入元素本身,所以HyperLogLog不能像集合那样,返回输入的各个元素。

    2、什么是基数

    比如数据集{1,3,5,7,5,7,8},那么这个数据集的基数集为{1,3,5,7,8},基数(不重复元素)为5。基数估计就是在误差可接受的范围内,快速计算基数

    3、命令

    1、pfadd

    格式
    pfadd [element] 可以加1个或多个

    192.168.1.154:6379> pfadd program java
    (integer) 1
    192.168.1.154:6379> pfadd program php
    (integer) 1
    192.168.1.154:6379> pfadd program java
    (integer) 0
    192.168.1.154:6379> pfadd program mysql redis
    (integer) 1
    

    2、pfcount(统计)

    统计

    192.168.1.154:6379> pfcount program
    (integer) 4
    

    3、pfmerge

    pfmerge [sourcekey…]将一个或多个HLL合并后的结果存储在另一个HLL中,比如每月活跃用户可以使用每天的活跃用户来合并计算可得

  • k1中添加了 11 12 13值

  • k2中添加 11 15 16值
  • 合并值保存在 k1_k2中得到 5个值

    192.168.1.154:6379> pfadd k1 11
    (integer) 1
    192.168.1.154:6379> pfadd k1 12
    (integer) 1
    192.168.1.154:6379> pfadd k1 13
    (integer) 1
    192.168.1.154:6379> pfadd k2 11
    (integer) 1
    192.168.1.154:6379> pfadd k2 15
    (integer) 1
    192.168.1.154:6379> pfadd k2 16
    (integer) 1
    192.168.1.154:6379> pfcount k1 k2
    (integer) 5
    192.168.1.154:6379> pfcount k1
    (integer) 3
    192.168.1.154:6379> pfcount k2
    (integer) 3
    192.168.1.154:6379> pfmerge k1_k2 k1 k2
    OK
    192.168.1.154:6379> pfcount k1_k2
    

    3、Geospatial

    1、简介

    Redis 3.2中增加了对GEO类型的支持。GEO,Geofraphic,地理信息的缩写。该类型,就是元素的2维坐标,在地图上就是经纬度。redis基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度Hash等常用操作

    2、命令

    1、geoadd

    geoadd [longitude latitude member…]添加地理位置(经度,纬度,名称)

    192.168.1.154:6379> geoadd chianLcity 121.47 31.23 shanghai
    (integer) 1
    192.168.1.154:6379> geoadd chianLcity 106.50 29.53 chongqing
    (integer) 1
    
  • 两级无法直接添加,一般会下载城市数据,直接通过java程序一次性导入

  • 有效的经度从-180度到180度。有效的纬度从-85.05112878度到85.05112878度
  • 当坐标位置超出指定范围时,该命令将会返回一个错误
  • 已经添加的数据,是无法再次往里面添加的

    2、geopos

    geopos 取出坐标

    192.168.1.154:6379> geopos chianLcity chongqing
    1) 1) "106.49999767541885376"
     2) "29.52999957900659211"
    

    3、geodist 获取两个位置直线距离

    geodist [m/km/mi/ft]

  • m是米(默认)

  • km千米
  • mi英里
  • ft英尺
    geodist chianLcity shanghai chongqing
    "1447673.6920"
    192.168.1.154:6379> geodist chianLcity shanghai chongqing km
    "1447.6737"
    

    4、georadius(以给定的经纬度为中心找出一定距离的范围内)

    georadius m|km|ft|mi [withcoord:显示经纬度][withhash:哈希值]
    192.168.1.154:6379> georadius chianLcity 110 48 10000 km
    1) "chongqing"
    2) "shanghai"