当前phpstudy中能直接安装的只有3.0.504

redisson 版本性能对比 redis哪个版本好_java

这个版本老实说新手还好 , 但是如果在本地写一些企业级应用时 , 会出现一些小问题

而且如果你想体验一下redis一些特性等东西时,3.0.504根本不够用

这时, 就需要手动安装了, 但是会存在一下几点:

  1. 很难找到windows的版本 , 因为redis官方不做windows😒
  2. 下载的redis必须先启动一个redis-serve的小黑框, 很容易误关

redisson 版本性能对比 redis哪个版本好_Redis_02

但是在2016年以后就不更新了 , 如今redis都出到7.0了,这......

但是别方 , 哪里有需求, 哪里就有大佬站出来

于是:


安装到phpstudy

其实很简单的 , 首先复制出来一个备份,并清空原文件夹

然后把下载的包解压到redis3.0.504的空文件夹里 , 注意:这里文件夹不能改名

然后面板启动看下是否正常(我的这个配置文件第一行是空白的,删掉就能启动了)

redisson 版本性能对比 redis哪个版本好_redis_03

 最后,打开redis-cli , 输入 info ,查看版本信息

redisson 版本性能对比 redis哪个版本好_redis_04

 

redis5特性

  1.新增加的Stream(流)数据类型,这样redis就有了6大数据类型,另外五种是String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sorted set有序集合)。它弥补了其它5种数据类型不能实现的功能,比如List数据类型只能先进先出,或者后进先出,不能从中间去数据,但是Stream可以实现。

  1)创建Stream

    命令:XADD

    用法:XADD key ID field string  (id可以自定义)

实例


127.0.0.1:6379> XADD key1 * month month_value #*代表默认id "1563893367304-0"                  #返回值说明:前面是UNIX毫秒时间戳 后面是序列号   127.0.0.1:6379> XADD key2 0-1 car car_value #自定义ID为 0-1 "0-1"


  2) 查看Stream长度

    命令:XLEN    返回stream中元素的个数

    用法:XLEN key 

127.0.0.1:6379> XLEN key1 (integer) 1

  Stream 详情介绍 : streams 介绍 -- Redis中国用户组(CRUG)

   2.新的Redis模块api : Times  and Cluster api,是一个抽象的集群消息总线,用于方便开发分布式系统。

   3.RDB(redis datebase)现在用于存储 LFU(最近最少使用淘汰算法) 和 LRU(最近不经常使用淘汰算法)元数据信息。

4、集群管理器从Ruby移植到C代码
集群删除从节点

redis-cli --clusterdel-node 192.168.0.100:5008 ID

分片操作

redis-cli --cluster reshard 192.168.0.100:5007

动态添加节点

redis-cli --cluster add-node 添加节点host:port 被添加的host:port

添加从节点

cluster replicate 做谁的节点id

5、新的sorted set 命令:ZPOP/MIN/MAX 和阻塞变种
ZPOPMAX

删除返回集合中分值最高的元素

ZPOPMAX key [count]

ZPOPMIN

删除返回集合中分值最低的元素

ZPOPMIN key [count]

BZPOPMAX

BZPOPMIN

应用场景举例:

1、成绩排名,第一名和最后一名

2、网站热搜,当下最火搜索

6、主动碎片整理V2
配置项:

activedefrag yes

# 内存浪费超过100M时候整理

active-defrag-ignore-bytes 100mb

active-defrag-threshold-lower 10

 
1、在运行期进行自动的内存碎片整理,释放内存空件

2、通过内存报告了解整个系统的内存使用情况

7、增强HyperLogLog实现

什么是UV?
Unique Visitor,独立访客,一般理解为客户端IP,需要去重考虑

什么是PV?
Page View,页面浏览量,不用去重

什么是DAU?
Daily Active User 日活跃用户量

去重复统计功能的基数估计算法-就是HyperLogLog

基数:
是一种数据集,去重复后的真实个数

去重复统计的方式?
1.HashSet
2.bitmap: 如果数据显较大亿级统计,使用bitmaps同样会有这个问题。
bitmap是通过用位bit数组来表示各元素是否出现,每个元素对应一位,所需的总内存为N个bit。
基数计数则将每一个元素对应到bit数组中的其中一位,比如bit数组010010101(按照从零开始下标,有的就是1、4、6、8)。
新进入的元素只需要将已经有的bit数组和新加入的元素进行按位或计算就行。这个方式能大大减少内存占用且位操作迅速。
But,假设一个样本案例就是一亿个基数位值数据,一个样本就是一亿如果要统计1亿个数据的基数位值,大约需要内存100000000/8/1024/1024约等于12M,内存减少占用的效果显著。
这样得到统计一个对象样本的基数值需要12M。
如果统计10000个对象样本(1w个亿级),就需要117.1875G将近120G,可见使用bitmaps还是不适用大数据量下(亿级)的基数计数场景,
但是bitmaps方法是精确计算的。

办法?
概率算法:
通过牺牲准确率来换取空间,对于不要求绝对准确率的场景下可以使用,因为概率算法不直接存储数据本身,
通过一定的概率统计方法预估基数值,同时保证误差在一定范围内,由于又不储存数据故此可以大大节约内存。
HyperLogLog就是一种概率算法的实现。
原理说明:只是进行不重复的基数统计,不是集合也不保存数据,只记录数量而不是具体内容。
有误差,非精确统计,牺牲准确率来换取空间,误差仅仅只是0.81%左右

为什么redis集群的最大槽数是16384个?
Redis集群并没有使用一致性hash而是引入了哈希槽的概念。Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。但为什么哈希槽的数量是16384(2^14)个呢?
CRC16算法产生的hash值有16bit,该算法可以产生2^16=65536个值。
换句话说值是分布在0~65535之间。那作者在做mod运算的时候,为什么不mod65536,而选择mod16384?

说明1
正常的心跳数据包带有节点的完整配置,可以用幂等方式用旧的节点替换旧节点,以便更新旧的配置。
这意味着它们包含原始节点的插槽配置,该节点使用2k的空间和16k的插槽,但是会使用8k的空间(使用65k的插槽)。
同时,由于其他设计折衷,Redis集群不太可能扩展到1000个以上的主节点。
因此16k处于正确的范围内,以确保每个主机具有足够的插槽,最多可容纳1000个矩阵,但数量足够少,可以轻松地将插槽配置作为原始位图传播。请注意,在小型群集中,位图将难以压缩,因为当N较小时,位图将设置的slot / N位占设置位的很大百分比。

说明2
(1)如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为65536时,这块的大小是: 65536÷8÷1024=8kb
因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。
(2)redis的集群主节点数量基本不可能超过1000个。
集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者不建议redis cluster节点数量超过1000个。 那么,对于节点数在1000以内的redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。
(3)槽位越小,节点少的情况下,压缩比高,容易传输
Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),bitmap的压缩率就很低。 如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。

网站首页亿级UV的Redis统计方案:
hash

说明:
redis——hash = <keyDay,<ip,1>>
按照ipv4的结构来说明,每个ipv4的地址最多是15个字节(ip = “192.168.111.1”,最多xxx.xxx.xxx.xxx)
某一天的1.5亿 * 15个字节= 2G,一个月60G,redis死定了。

hyperloglog:

先看个场景:统计网站中每个页面的UV,分每天,每周,每月。
由于UV和PV不同,UV要去重,同一个用户每天点某个页面多次,也只算一次,所以可以用集合来存。每个页面加一个时间做一个key,里面存用户id。如果网站流量非常大,则要占用非常多的内存。
为了这个小功能花费巨大的内存,未必划算。对于运营来说,某个页面200000的UV 和 199838的UV 区别不大,不需要绝对的精确。
这时我们就可以考虑使用HyperLogLog来储存。
HyperLogLog 提供不精确的去重计数方案,虽然不精确但是也不是非常不精确,标准误差是 0.81%。
它的优点是效率高,省空间,真的很省。
HyperLogLog 提供了三个常用命令:pfadd,pfcount ,pfmerge。我们来实验下。
加10个用户

127.0.0.1:6379> pfadd uv user1
(integer) 1
127.0.0.1:6379> pfadd uv user2
(integer) 1
127.0.0.1:6379> pfadd uv user3
(integer) 1
127.0.0.1:6379> pfadd uv user4
(integer) 1
127.0.0.1:6379> pfadd uv user5
(integer) 1
127.0.0.1:6379> pfadd uv user6
(integer) 1
127.0.0.1:6379> pfadd uv user7
(integer) 1
127.0.0.1:6379> pfadd uv user8
(integer) 1
127.0.0.1:6379> pfadd uv user9
(integer) 1
127.0.0.1:6379> pfadd uv user10
(integer) 1
127.0.0.1:6379> pfadd uv user1
(integer) 1
127.0.0.1:6379> pfadd uv user2
(integer) 1
127.0.0.1:6379> pfadd uv user3
(integer) 1
127.0.0.1:6379> pfadd uv user4
(integer) 1
127.0.0.1:6379> pfadd uv user5
(integer) 1
127.0.0.1:6379> pfadd uv user6
(integer) 1
127.0.0.1:6379> pfadd uv user7
(integer) 1
127.0.0.1:6379> pfadd uv user8
(integer) 1
127.0.0.1:6379> pfadd uv user9
(integer) 1
127.0.0.1:6379> pfadd uv user10
(integer) 1

统计下

127.0.0.1:6379> pfcount uv
(integer) 10

增加另一个组,看下合并统计

127.0.0.1:6379> pfadd uv2 u1
(integer) 1
127.0.0.1:6379> pfadd uv2 u2
(integer) 1
127.0.0.1:6379> pfadd uv2 u3
(integer) 1
127.0.0.1:6379> pfadd uv2 u4
(integer) 1
127.0.0.1:6379> pfadd uv2 u5
(integer) 1
127.0.0.1:6379> pfmerge uv uv2 #把uv2的合并到uv
OK
127.0.0.1:6379> pfcount uv
(integer) 15

这里测试的是小数目,我们通过脚本批量导入20万条数据测试下

#!/usr/bin/env python
#coding:utf8
import redis
client = redis.StrictRedis()
for i in range(200000):
    client.pfadd("uv", "user%d" % i)

手动统计下结果

127.0.0.1:6379> pfcount uv
(integer) 200106

误差在0.81%。
看下占用了多少内存

127.0.0.1:6379> MEMORY USAGE uv
(integer) 12356

没超过12k。
我们测试下集合占用多少内存

import redis
client = redis.StrictRedis()
for i in range(200000):
    client.lpush("set_uv", "user%d" % i)
127.0.0.1:6379> memory usage set_uv
(integer) 1877563

差不多要1.8M了。
为什么redis的HyperLogLog这么省空间,有兴趣的可以看下:
神奇的HyperLogLog算法

布隆过滤器

HyperLogLog可以满足精度要求不高的统计需求,但它不能判断某个值是否存在。
如果我们想判断值是否存在时,可以用布隆过滤器(redis版本4.0及以上)
布隆过滤器是redis4.0之后的一个插件,默认没有,需要手动安装下:

git clone git://github.com/RedisLabsModules/rebloom
cd rebloom
make
在当前路径下会有个rebloom.so文件
在redis的配置中增加一行配置
loadmodule /path/to/rebloom.so #后面这个路径是rebloom.so文件的完整路径
重启redis,即可使用

布隆过滤器有二个基本指令,bf.add 添加元素,bf.exists 查询元素是否存在。如果想要一次添加多个,用 bf.madd 指令,如果需要一次查询多个元素是否存在,用 bf.mexists 指令。
我们实验下:

127.0.0.1:6379> bf.add users user1
(integer) 1
127.0.0.1:6379> bf.add users user2
(integer) 1
127.0.0.1:6379> bf.add users user3
(integer) 1
127.0.0.1:6379> bf.exists users user1
(integer) 1
127.0.0.1:6379> bf.exists users user3
(integer) 1
127.0.0.1:6379> bf.exists users user100
(integer) 0
127.0.0.1:6379> bf.madd users user100 user9 user23 user007
1) (integer) 1
2) (integer) 1
3) (integer) 1
4) (integer) 1
127.0.0.1:6379> bf.mexists users user7 user100 user2
1) (integer) 0
2) (integer) 1
3) (integer) 1

跑20万数据试试(现有封装没看到bf.add,先用shell简单跑下,耗时有点长,需等待下)

#!/bin/bash
for(( i = 1; i <= 200000; i = i + 1 ))
do
     redis-cli bf.add users $i
done

跑完后,看看用了多少

127.0.0.1:6379> memory usage users
(integer) 2796737

对布隆过滤器的数据结构感兴趣的可以看下:
Bloom Filter概念和原理

GEOHASH

Redis 在 3.2 版本以后增加了地理位置 GEO 模块,用这个模块可以来实现地理位置的一些功能
Redis提供了6个Geo指令:geoaddgeodistgeoposgeohashgeoradiusbymembergeoradius
1. 用geoadd增加几个坐标。
可以打开高德地图控制台来获取经纬度

127.0.0.1:6379> geoadd park 113.373055 23.124132 tit #tit创业园
(integer) 1
127.0.0.1:6379> geoadd park 113.323812 23.106376 gzt #广州塔
(integer) 1
127.0.0.1:6379> geoadd park 113.367586 23.129031 tianhe #天河公园
(integer) 1
127.0.0.1:6379> geoadd park 113.29978 23.172279 baiyun #白云山
(integer) 1

2.geodist 指令可以用来计算两个元素之间的距离,携带集合名称、2 个名称和距离单位。

127.0.0.1:6379> geodist park tit baiyun km #算下白云和tit距离有多少km
"9.2110"
127.0.0.1:6379> geodist park tit gzt m #算下广州塔和tit距离有多少m
"5411.0219"

3.geopos 指令可以获取集合中任意元素的经纬度坐标

127.0.0.1:6379> geopos park tit
1) 1) "113.37305635213851929"
   2) "23.12413313323070696"
127.0.0.1:6379> geopos park tianhe gzt
1) 1) "113.36758464574813843"
   2) "23.12903021451054286"
2) 1) "113.32381099462509155"
   2) "23.10637487678837232"

4.geohash 可以获取元素的经纬度编码字符串,可以使用这个编码值去 http://geohash.org/${hash}中进行直接定位

127.0.0.1:6379> geohash park tit
1) "ws0eeceezd0"

5.georadiusbymember 可以用来查询指定元素附近的其它元素,参数较多

# 范围 20 公里以内最多 3 个元素按距离正排,它不会排除自身
127.0.0.1:6379> georadiusbymember park tianhe 20 km count 3 asc
1) "tianhe"
2) "tit"
3) "gzt"

# 增加三个可选参数 withcoord withdist withhash
# withdist 很有用,它可以用来显示距离
127.0.0.1:6379> georadiusbymember park tianhe 20 km withcoord withdist withhash count 3 asc
1) 1) "tianhe"
   2) "0.0000"
   3) (integer) 4046534299263235
   4) 1) "113.36758464574813843"
      2) "23.12903021451054286"
2) 1) "tit"
   2) "0.7810"
   3) (integer) 4046534301371059
   4) 1) "113.37305635213851929"
      2) "23.12413313323070696"
3) 1) "gzt"
   2) "5.1382"
   3) (integer) 4046534096956439
   4) 1) "113.32381099462509155"
      2) "23.10637487678837232"

6.georadius显示附近的元素

127.0.0.1:6379> georadius park 113.36758 23.12903 20 km withdist count 3 asc
1) 1) "tianhe"
   2) "0.0005"
2) 1) "tit"
   2) "0.7813"
3) 1) "gzt"
   2) "5.1377"

对于GeoHash感兴趣的可以看下相关的解读GeoHash核心原理解析

SCAN

redis默认有个命令 keys , 可以用来看下有多少个key,如:

127.0.0.1:6379> keys *
1) "park"
2) "users"
127.0.0.1:6379> keys *use* #加关键字匹配
1) "users"

如果我们的key非常多的时候,keys就不适用了,可以用scan命令来代替
scan格式如下:

scan cursor [MATCH pattern] [COUNT count]

cursor: 表示起始值,第一次是0,查找后会返回一个cursor值,用于下一次的查找
pattern: 正则匹配部分
count: 一次遍历多少个
我们灌2万条数据进去,做下实验。

import redis
client = redis.StrictRedis()
for i in range(20000):
    client.set("user_%d" % i, i)

先查10条出来看看:

127.0.0.1:6379> scan 0 match user_* count 10
1) "5120"
2)  1) "user_17548"
    2) "user_7121"
    3) "user_10149"
    4) "user_3648"
    5) "user_11162"
    6) "user_7952"
    7) "user_11985"
    8) "user_12087"
    9) "user_13276"
   10) "user_1712"

再查5条

127.0.0.1:6379> scan 5120 match user_* count 5
1) "19456"
2) 1) "user_16993"
   2) "user_6395"
   3) "user_15940"
   4) "user_16429"
   5) "user_17265"
   6) "user_2003"

scan 指令是一系列指令,除了可以遍历所有的 key 之外,还可以对指定的容器集合进行遍历。比如 zscan 遍历 zset 集合元素,hscan 遍历 hash 字典的元素、sscan 遍历 set 集合的元素。

为什么是12Kb?

每个桶取6位,16384*6÷8 = 12kb,每个桶有6位,最大全部都是1,值就是63

8、更好的内存统计报告
9、许多带有子命令的命令现在都一个HTLP子命令
redis-cli --cluster help

xinfo help

xadd help

pubsub help

10、客户经常连接和断开连接时性能更好