JT项目-3--数据分布式存储--hash一致性

DAY05

知识回顾+遗留问题

2018115

19:32

前4天的脉络

 

 

复习的顺序:将其中的所有非代码技术先复习

把代码敲一遍,分别的引入技术

 

1 nginx 一个服务器7万/秒 转发 并发 5万 3万

是京淘中提升并发的第一道关卡

20nginx集群就可以搞定每秒100万并发

 

2 属性注入

扩展Bean加载数据

后处理bean注入扩展类把数据传递给伪service

后台controller图片上传注入伪service使用属性

 

3 nginx的匹配规则(与优先级)

· 精确匹配=

· 字符串前缀匹配 ^~

· 按照配置顺序的正则匹配(AB都匹配上了,配置在前的匹配)

· 不带任何修饰的前缀匹配/images/

· 当所有匹配成功时,停止匹配,按照当前匹配规则处理请求

· 前缀匹配,有包含关系时,按最大匹配长度原则匹配

· 最低优先级是通配符 /

location = /images{

return 205;}

 

location ^~ /images {

   return 200;}

location ^~ /images/test.png {

return 201;}

location ~* \.png$ {

   return 203;}

location ~ \.(gif|jpg|png|js|css)$ {

return 202;}

location / {

   return 204;}

 

http://localhost/ 返回204

http://localhost/images 205204?

http://localhost/images/id 200

http://localhost/images/test.png 返回201 前缀最长匹配原则

http://localhost/haha.png 返回203 顺序正则原则

 

4 nginx负载均衡

轮询:将所有的访问平均分配给服务器库中配置的服务器;

 

 

 

 

nginx负载均衡

2018116

10:05

 

权重:

根据不同机器性能,计算相对的访问负载承受,从而使用权重配置

负载的量

upstream jt1710{

server 192.168.40.170:8081 ;

server 192.168.40.170:8082 ;

server 192.168.40.170:8080 ;

server 192.168.40.170:8081 ;

server 192.168.40.170:8081 ;

server 192.168.40.170:8081 ;

server 192.168.40.170:8081 ;

server 192.168.40.170:8081 ;}

权重的关键字

weight:权重的优先量级;数字越大,访问次数越多

down;宕机状态永不访问;

当服务器宕机不可恢复时,nginx会根据权重或者轮询配置

继续访问,连接超时访问失败,但是不会停止访问,

down一定程度的减少了资源的损耗

session黏着

负载均衡中的session共享问题

 

解决session共享问题

session黏着

当用户通过ngnix访问某一个tomcat后,使用session黏着,保证后续访问永远

访问者一台

1 ip_hash

利用客户端请求的ip和端口(192.168.40.170:661)获取其字符串的hash值

String str="192.168.40.160:8080";

str.hashCode();(未必是正值,&Integer.max_value)

System.out.println(user1.hashCode()&Integer.MAX_VALUE);

System.out.println(user2.hashCode()&Integer.MAX_VALUE);

System.out.println(user3.hashCode()&Integer.MAX_VALUE);

获取到字符串的整数然后对已有的负载均衡服务器库数量进行取余(三台为例)

哈希整数N%3=[0,1,2]

如果是4台呢?对4取余,依次类推

2 url_hash黏着(依赖第三方插件实现)

访问服务器的url地址字符串做hash取余运算

order.jt.com/*****/***.html

具有某一个固定功能的服务器,固定

 

springSession(HttpSession+redis)

 

将虚拟机中的后台系统做完全,还差访问数据库

需要修改war包中的jdbc.properties

需要获取linux系统访问windows系统的ip地址

 

 

 

 


 

 

 

 

商品描述

2018116

10:57

查看电商中的描述信息,需要大字段属性保存图片信息和文本信息

blob/text破坏表的索引,商品描述不能添加到商品列表中

单独创建一个商品描述表格 tb_item_desc

 

 

开发过程

pojo,mapper,service,controller

 

service不用单独编写,直接和ItemService一起保证事务的有效性

 

级联新增时从表(tb_item_desc),主表(tb_item)

关联的键是itemId

mybatis+mysql底层实现

调用sql

select last_insert_id;

 

商品描述的修改(包括数据回显和修改过程)

http://manage.jt.com/item/query/item/desc/1474391958

点击编辑按钮弹出item-edit页面,以上一个请求

$.getJSON('/item/query/item/desc/'+data.id,function(_data){

                                        if(_data.status == 200){                                                  itemEditEditor.html(_data.data.itemDesc);

                                        }

        });

第一个参数:'/item/query/item/desc/'+data.id

第二个参数:回调函数function(_data) _data就是SysResult 的json字符串

传递给controller的参数是data.id 以restFul形式传参

 

回显就是查询,在itemController和itemService中添加查询代码

 

修改部分

修改的前台js代码

$.post("/item/update",$("#itemeEditForm").serialize(), function(data){

if(data.status == 200){

$.messager.alert('提示','修改商品成功!','info',function(){

$("#itemEditWindow").window('close');

$("#itemList").datagrid("reload");

});

}

});

/item/update:请求地址

$("#itemeEditForm").serialize():参数将表单内所有标签封装成一个模拟的get请求参数

字符串传递

function(data):回调函数,data是SysResult的json转化的js对象

 

商品详情的删除工作

 

 

Redis

2018116

15:09

情景讨论

在后台功能已经完成了,

后台系统的高并发思路:

技术:tomcat集群+nginx

引入20台nginx --100万/s;

考虑一个问题:当100万个用同时增删改查操作时;

系统瓶颈在哪:数据库,尤其是查询

 

Redis

分布式,nosql,可以持久化,内存,数据库

分布式:数据被划分

nosql:not only sequence query language

不仅仅支持关系型数据--结构化的数据

还支持非关系型数据--非结构化数据

 

可持久化+内存:启动回复机制

数据库存储;

可以分布式的存储大量海量的数据,存放到内存中,

可以做缓存数据库

 

京淘中的缓存架构可以如何设计

缓存可以如何添加

 

 

数据库缓存

执行的过程包括sql,组织查询结果resultSet

根据sql可以创建缓存,存储已经查过的resultset,节省了

资源的调度重组resultSet

持久层缓存

减少从数据库获取的结果转化成对象的过程,缓存存在直接调用其中

保存的对象结果;

业务层缓存

减少调用层次

控制层缓存

较少调用层次

 

<问题>可不可以过多使用缓存

缓存是占用内存空间的,过多的缓存插入,容易造成数据的冗余

在内存不够时,清空逻辑会交叉导致数据失效

结论缓存引入的最终目的

1 减少数据库的访问压力

2 减少网络传输

3 减少封装层次

Redis这个技术就可以在京淘中实现提升性能的目的,缓存

 

介绍缓存

主流的缓存架构

1 ehcache (很多数据库底层缓存使用ehcache)并发量差

2 memoryCache,10年,高并发的100万/s; 缺点:不落地

3 Redis:持久化可以在宕机恢复后迅速解决数据丢失

 

<问题>:如果在缓存服务器宕机后,无法进行数据恢复/没有解决数据重新加载

的问题,会导致“雪崩”/”缓存击穿“

 

雪崩/缓存击穿

海量用户访问请求涌入,一旦缓存失效(宕机数据丢失);所有的访问

涌入数据库;数据库无法承受海量数据的查询,导致数据库服务器宕机;

重启数据库,请求查询没消失,数据库--宕机--重启循环,导致系统崩溃

 

解决雪崩:

1 缓存用不宕机;启动集群,永远让集群中的一部分起作用

2 缓存技术必须可以恢复数据,持久化

 

 

安装redis

2018116

15:47

1 下载安装包解压

使用对象存储的源站地址获取资源

wget "http://jt-xxw.cn-bj.ufileos.com/redis-3.2.11.tar.gz?UCloudPublicKey=ucloudzhaodong%40tarena.com.cn14442715760002074868321&Signature=5%2Fng5gQ8aUNTTOzY9u%2BEZzmHR8g%3D&Expires=1516091995

"

 

创建管理目录

[root@10-9-62-65 ~]# cd /home/

[root@10-9-62-65 home]# mkdir software

[root@10-9-62-65 home]# cd software/

[root@10-9-62-65 software]#

使用wget获取资源

 

解压

 

redis使用

make && make install

 

 

2 启动redis

启动redis的服务

#redis-server

 

使用redis需要启动redis客户端

#redis-cli

 

如果想在同一个操作控制台启动服务和客户端

启动客户端时可以使用后台运行命令

#redis-server &

停止redis服务

1 占用控制台的redis服务直接ctrl+c停止服务

2 在后台运行服务的时候,登陆客户端

shutdown;

 

3 检查后台运行的redis服务

ps -ef|grep redis;

 

redis-server 表示redis服务

*:表示能够访问当前redis服务的所有ip地址,都可以

如果列出一系列的ip地址,除这些ip意外的所有访问redis服务的请求

都被拒绝

 

Redis的基础命令

操作字符串

redis存储数据是以key-value的形式,key-{key,value},key-list

 

keys:查询当前的存储空中的所有存在key;

127.0.0.1:6379> keys *

(empty list or set)

127.0.0.1:6379>

 

set [key名] [value]

设置 key-value值,value是String字符串

127.0.0.1:6379> set name xiao

OK

127.0.0.1:6379> key *

(error) ERR unknown command 'key'

127.0.0.1:6379> keys *

1) "name"

127.0.0.1:6379>

 

get [key名]

获取key对应的value值

127.0.0.1:6379> keys *

1) "gender"

2) "name"

3) "age"

4) "city"

127.0.0.1:6379> get name

"xiao"

127.0.0.1:6379>

 

select [整数值[0-15]]

redis存在吗默认的0-15标号的数据分裤,默认使用0号;这个功能是早期

版本冗余的功能,现在都使用默认0号数据库;现在java的代码不支持分库

127.0.0.1:6379> select 1

OK

127.0.0.1:6379[1]> keys *

(empty list or set)

127.0.0.1:6379[1]>

 

exists [key名]

判断当前key是否存在;与get的却别

redis存储的key-value结构的字符串数据 512M,当逻辑判断只需要返回是与

否时,get命令获取的大字符串就占用了资源的调用

127.0.0.1:6379> exists name

(integer) 1

127.0.0.1:6379> exists xiao

(integer) 0

127.0.0.1:6379>

 

del [key名]

127.0.0.1:6379> del name

(integer) 1

127.0.0.1:6379> keys *

1) "gender"

2) "num"

3) "age"

4) "city"

 

type [key名]

127.0.0.1:6379> set num1 100

OK

127.0.0.1:6379> type num1

string

127.0.0.1:6379>

 

help type/help [命令名称]

127.0.0.1:6379> help set

  SET key value [EX seconds] [PX milliseconds] [NX|XX]

  summary: Set the string value of a key

  since: 1.0.0

  group: string

127.0.0.1:6379>

实际问题可以到官网查询对应的命令细节

 

flushall 将所有的当前内存数据(0-15号库),flush到持久化文件

127.0.0.1:6379> keys *

1) "num1"

2) "gender"

3) "num"

4) "age"

5) "city"

127.0.0.1:6379> flushall

OK

127.0.0.1:6379> keys *

(empty list or set)

 

flushdb flush当前redis某一个标号的库中的内容到持久化文件

127.0.0.1:6379> keys *

1) "name"

127.0.0.1:6379> selet

(error) ERR unknown command 'selet'

127.0.0.1:6379> selet 1

(error) ERR unknown command 'selet'

127.0.0.1:6379> select 1

OK

127.0.0.1:6379[1]> set name xiao

OK

127.0.0.1:6379[1]> keys *

1) "name"

127.0.0.1:6379[1]> flushdb

OK

127.0.0.1:6379[1]> keys *

(empty list or set)

127.0.0.1:6379[1]> select 0

OK

127.0.0.1:6379> keys *

1) "name"

127.0.0.1:6379>

 

===============================================================================

==========================================================================

DAY06

 

知识回顾

2018117

8:54

1 nginx负载均衡

权重;weight,down关键字

session黏着,解决session共享的负载均衡计算方式

ip_hash

 

url_hash,以来第三方插件;

2 商品描述

大字段内容,不破坏商品表的索引,单独使用一张表来记录

单独的desc表数据特别大的时候,分库,分表保存(早期)

现在几乎所有的可见查询功能都使用缓存

完成商品详情的增删改查

改和查一体(回显和修改)

3 Redis介绍

后台的访问并发量已经使用nginx+tomcat可以达到很高

程序性能未必能支持如此大的并发量请求

缓存的引入;

分布式,nosql,可持久化,内存,缓存,数据库

ehcache,

memoryCache

雪崩:缓存由于各种原因数据丢失,大量请求涌入数据库,数据库无法

承受,宕机重启,缓存没数据,请求未消失,数据库继续宕机,恶性循环

解决雪崩:没有持久化的功能,必须保证缓存集群永远保持部分可使用

在缓存技术中添加持久化,在宕机后可以读取持久化文件

恢复数据

4 安装redis+key-value类型数据使用的部分命令

keys*;get,set,exists,flushdb,flushall,type,help,select,del

 

 

 

Redis基础命令

2018117

9:28

 

incr decr 自增自减

127.0.0.1:6379> set n1 100

OK

127.0.0.1:6379> type n1

string

127.0.0.1:6379> incr n1

(integer) 101

127.0.0.1:6379> get n1

"101"

127.0.0.1:6379> set school bjdx

OK

127.0.0.1:6379> incr school

(error) ERR value is not an integer or out of range

127.0.0.1:6379>

 

incrby 数字 decrby 数字

127.0.0.1:6379> incrby n1 5

(integer) 106

127.0.0.1:6379>

 

append 在value后追加数据

127.0.0.1:6379> set name xiao

OK

127.0.0.1:6379> apend name laoshi

(error) ERR unknown command 'apend'

127.0.0.1:6379> append name laoshi

(integer) 10

127.0.0.1:6379> get name

"xiaolaoshi"

127.0.0.1:6379>

 

mset mget 获取或者设置一批key-value对

mset k1 v1 k2 v2

mget k1 k2

127.0.0.1:6379> mset n1 100 n2 200 n3 300

OK

127.0.0.1:6379> keys *

1) "name"

2) "n3"

3) "n2"

4) "n1"

127.0.0.1:6379> mget n1 n2 n3

1) "100"

2) "200"

3) "300"

127.0.0.1:6379>

支持的语言API不支持这个命令,这种群体操作k-v对的过程

无法进行分片和集群计算;早期redis版本遗留功能;

 

expire [key] 时间数字(单位秒)

设置当前key对应的value的过期时间

ttl 查看当前key-value对的存活时间

127.0.0.1:6379> set bomb c4

OK

127.0.0.1:6379> keys *

1) "name"

2) "n1"

3) "n2"

4) "n3"

5) "bomb"

127.0.0.1:6379> expire bomb 100

(integer) 1

127.0.0.1:6379> ttl

(error) ERR wrong number of arguments for 'ttl' command

127.0.0.1:6379> ttl bomb

(integer) 86

127.0.0.1:6379> ttl bomb

(integer) 85

127.0.0.1:6379> ttl bomb

(integer) 84

127.0.0.1:6379>

第二个案例

127.0.0.1:6379> set bread binbao

OK

127.0.0.1:6379> expire bread 5

(integer) 1

127.0.0.1:6379> ttl bread

(integer) 2

127.0.0.1:6379> ttl bread

(integer) 1

127.0.0.1:6379> ttl bread

(integer) 0

127.0.0.1:6379> ttl bread

(integer) -2

127.0.0.1:6379>

127.0.0.1:6379> ttl name

(integer) -1

127.0.0.1:6379>

-2代表过期,-1代表永久

可以使用数据中的过期来做倒计时

还可以秒杀;

 

pexpire [key] 时间数字(毫秒)

127.0.0.1:6379> pexpire bomb 5000

(integer) 1

127.0.0.1:6379> ttl bomb

(integer) 3

127.0.0.1:6379> ttl bomb

(integer) 2

 

 

 

HASH+LIST

2018117

9:47

1 HASH结构

key-value字符串类型中的key本身也是key-value对儿

 

HSET和HGET赋值和取值

HSET key field value

HGET key field

HMSET key field value [field value…]

HMGET key field value [field value…]

HGETALL key

 

127.0.0.1:6379> hset user username chenchen

(integer) 1

127.0.0.1:6379> hget user username

"chenchen"

127.0.0.1:6379> hset user username chen

(integer) 0

127.0.0.1:6379> keys user

1) "user"

127.0.0.1:6379> hgetall user

1) "username"

2) "chen"

127.0.0.1:6379>

127.0.0.1:6379> hset user age 30

(integer) 1

127.0.0.1:6379> hgetall user

1) "username"

2) "chen"

3) "age"

4) "30"

127.0.0.1:6379>

HSET命令不区分插入和更新操作,当执行插入操作时HSET命令返回1,当执行更新操作时返回0。

HMSET和HMGET设置和获取对象属性

127.0.0.1:6379> hmset person username tony age 18

OK

127.0.0.1:6379> hmget person age username

1) "18"

2) "tony"

127.0.0.1:6379> hgetall person

1) "username"

2) "tony"

3) "age"

4) "18"

127.0.0.1:6379>

注意:上面HMGET字段顺序可以自行定义

HEXISTS属性是否存在

127.0.0.1:6379> hexists killer

(error) ERR wrong number of arguments for 'hexists' command

127.0.0.1:6379> hexists killer a

(integer) 0

127.0.0.1:6379> hexists user username

(integer) 1

127.0.0.1:6379> hexists person age

(integer) 1

127.0.0.1:6379>

HDEL删除对象字段

127.0.0.1:6379> hdel user age

(integer) 1

127.0.0.1:6379> hgetall user

1) "username"

2) "chen"

127.0.0.1:6379> hgetall person

1) "username"

2) "tony"

3) "age"

4) "18"

127.0.0.1:6379>

只获取字段名HKEYS或字段值HVALS

127.0.0.1:6379> hkeys person

1) "username"

2) "age"

127.0.0.1:6379> hvals person

1) "tony"

2) "18"

获取字段数量HLEN

127.0.0.1:6379> hlen user

(integer) 1

127.0.0.1:6379> hlen person

(integer) 2

127.0.0.1:6379>

 

List

key-value(双向链表,左-上,右-下)

查看list

redis 127.0.0.1:6379> lrange mylist3 0 -1

lrange key start length

LPUSH

key对应list的头部添加字符串元素

redis 127.0.0.1:6379> lpush mylist "world"

(integer) 1

redis 127.0.0.1:6379> lpush mylist "hello"

(integer) 2

redis 127.0.0.1:6379> lrange mylist 0 -1

1) "hello"

2) "world"

redis 127.0.0.1:6379>

RPUSH

key对应list的尾部添加字符串元素

redis 127.0.0.1:6379> rpush mylist2 "hello"

(integer) 1

redis 127.0.0.1:6379> rpush mylist2 "world"

(integer) 2

redis 127.0.0.1:6379> lrange mylist2 0 -1

1) "hello"

2) "world"

redis 127.0.0.1:6379>

linsert

key对应list的特定位置之前或之后添加字符串元素

redis 127.0.0.1:6379> rpush mylist3 "hello"

(integer) 1

redis 127.0.0.1:6379> rpush mylist3 "world"

(integer) 2

redis 127.0.0.1:6379> linsert mylist3 before "world" "there"

(integer) 3

redis 127.0.0.1:6379> lrange mylist3 0 -1

1) "hello"

2) "there"

3) "world"

redis 127.0.0.1:6379>

lset

设置list中指定下标的元素值

redis 127.0.0.1:6379> rpush mylist4 "one"

(integer) 1

redis 127.0.0.1:6379> rpush mylist4 "two"

(integer) 2

redis 127.0.0.1:6379> rpush mylist4 "three"

(integer) 3

redis 127.0.0.1:6379> lset mylist4 0 "four"

OK

redis 127.0.0.1:6379> lset mylist4 -2 "five"

OK

redis 127.0.0.1:6379> lrange mylist4 0 -1

1) "four"

2) "five"

3) "three"

redis 127.0.0.1:6379>

大于0是正数

小于0倒数

lrem

key对应list中删除count个和value相同的元素,count>0时,

按从头到尾的顺序删除

redis 127.0.0.1:6379> rpush mylist5 "hello"

(integer) 1

redis 127.0.0.1:6379> rpush mylist5 "hello"

(integer) 2

redis 127.0.0.1:6379> rpush mylist5 "foo"

(integer) 3

redis 127.0.0.1:6379> rpush mylist5 "hello"

(integer) 4

redis 127.0.0.1:6379> lrem mylist5 2 "hello"

(integer) 2

redis 127.0.0.1:6379> lrange mylist5 0 -1

1) "foo"

2) "hello"

redis 127.0.0.1:6379>

count<0时,按从尾到头的顺序删除

redis 127.0.0.1:6379> rpush mylist6 "hello"

(integer) 1

redis 127.0.0.1:6379> rpush mylist6 "hello"

(integer) 2

redis 127.0.0.1:6379> rpush mylist6 "foo"

(integer) 3

redis 127.0.0.1:6379> rpush mylist6 "hello"

(integer) 4

redis 127.0.0.1:6379> lrem mylist6 -2 "hello"

(integer) 2

redis 127.0.0.1:6379> lrange mylist6 0 -1

1) "hello"

2) "foo"

redis 127.0.0.1:6379>

count=0时,删除全部

redis 127.0.0.1:6379> rpush mylist7 "hello"

(integer) 1

redis 127.0.0.1:6379> rpush mylist7 "hello"

(integer) 2

redis 127.0.0.1:6379> rpush mylist7 "foo"

(integer) 3

redis 127.0.0.1:6379> rpush mylist7 "hello"

(integer) 4

redis 127.0.0.1:6379> lrem mylist7 0 "hello"

(integer) 3

redis 127.0.0.1:6379> lrange mylist7 0 -1

1) "foo"

redis 127.0.0.1:6379>

ltrim

保留指定key 的值范围内的数据

redis 127.0.0.1:6379> rpush mylist8 "one"

(integer) 1

redis 127.0.0.1:6379> rpush mylist8 "two"

(integer) 2

redis 127.0.0.1:6379> rpush mylist8 "three"

(integer) 3

redis 127.0.0.1:6379> rpush mylist8 "four"

(integer) 4

redis 127.0.0.1:6379> ltrim mylist8 1 -1

OK

redis 127.0.0.1:6379> lrange mylist8 0 -1

1) "two"

2) "three"

3) "four"

redis 127.0.0.1:6379>

lpop

list的头部删除元素,并返回删除元素

redis 127.0.0.1:6379> lrange mylist 0 -1

1) "hello"

2) "world"

redis 127.0.0.1:6379> lpop mylist

"hello"

redis 127.0.0.1:6379> lrange mylist 0 -1

1) "world"

redis 127.0.0.1:6379>

rpop

list的尾部删除元素,并返回删除元素:

redis 127.0.0.1:6379> lrange mylist2 0 -1

1) "hello"

2) "world"

redis 127.0.0.1:6379> rpop mylist2

"world"

redis 127.0.0.1:6379> lrange mylist2 0 -1

1) "hello"

redis 127.0.0.1:6379>

rpoplpush

从第一个list的尾部移除元素并添加到第二个list的头部,最后返回被移除的元素值,整个操作是原子的.如果第一个list是空或者不存在返回nil:

redis 127.0.0.1:6379> lrange mylist5 0 -1

1) "three"

2) "foo"

3) "hello"

redis 127.0.0.1:6379> lrange mylist6 0 -1

1) "hello"

2) "foo"

redis 127.0.0.1:6379> rpoplpush mylist5 mylist6

"hello"

redis 127.0.0.1:6379> lrange mylist5 0 -1

1) "three"

2) "foo"

redis 127.0.0.1:6379> lrange mylist6 0 -1

1) "hello"

2) "hello"

3) "foo"

redis 127.0.0.1:6379>

lindex

返回名称为key的list中index位置的元素:

redis 127.0.0.1:6379> lrange mylist5 0 -1

1) "three"

2) "foo"

redis 127.0.0.1:6379> lindex mylist5 0

"three"

redis 127.0.0.1:6379> lindex mylist5 1

"foo"

redis 127.0.0.1:6379>

llen

返回key对应list的长度:

redis 127.0.0.1:6379> llen mylist5

(integer) 2

redis 127.0.0.1:6379>

 

 

 

数据的分布存储

2018117

10:44

要完成数据的分片存储,需要至少多个redis实例

 

启动多个redis实例

前面的单个redis节点实例的启动时默认配置

端口号6379

 

配置文件

/redis根目录/redis.conf

 

配置文件的修改内容

p61 bind 用#注释掉

 

p80 保护模式不启动

 

p84 6379是默认端口(要启动其他的redis实例需要修改端口)

 

p105 当客户端空闲时间一小时,就会自动断开连接,0秒表示

不启用超时配置

 

p128 daemonize 设置成yes让redis服务器启动有守护进程管理

(后台执行)

 

p150 对应不同的redis实例,pid的文件名称需要和端口同名

 

save 900(秒) 1(变动的数据条数)

当900以内,至少有1条数据变动,看是flush保存数据到文件

save 300 10

300秒以内至少10条数据变动,保存文件

save 60 10000

 

 

启动第二和第三个redis实例

redis-server redis.conf(指定启动文件)

需要第二个实例的配置文件

需要第三个实例的配置文件

拷贝redis.conf,用redis6380.conf,redis6381.conf

 

将拷贝的文件中只修改与端口有关内容

port

 

pid文件

 

6381的略

 

启动另外两个节点

#redis-server redis6380.conf

#redis-server redis6381.conf

#ps -ef|grep redis

 

 

指定端口登录客户端redis-cli -p [端口号]

#redis-cli -p 6380

 

#redis-cli -p 6381

 

 

6380和6381会共享6379dump.db文件

所以不同的节点实例在同一个机器上运行时,可以修改dump.db

指定端口文件;

 

三个节点,怎么分布式保存数据?

数据来源:代码的逻辑执行

如何使用代码来操作redis执行分布式的数据存储过程?

引出了Jedis客户端

 

 

 

Jedis

2018117

11:36

测试jedis控制redis的命令功能

需要导入jedis包

 

 

自定义分片

准备数据:

葵花宝典A,B,C三部分数据

将三部分数据分别存储到redis 6379 6380 6381

 

哈希取余

利用hash的散列特性,可以处理海量非结构化数据的散列分布的分片计算

代码

 

jedis分片

没有在分片时使用哈希取余,hash一致性

 

经过代码发现,一般的自定义分片逻辑计算无法做到散列

不散列无法均衡

 

jedis池

 

 

 

 

HASH一致性

2018117

15:27

作为散列算法

考虑哈西取余的问题

1 容易产生大规模的数据倾斜(散列必定倾斜)

hash一致性一定程度的解决了数据倾斜;

2 哈希取余算法,导致数据迁移量过大

 

redis集群数量进行增加减少的时候,哈希取余算法中的n变化了

由于n的变化,数据命中变化量非常大,需要迁移的数据量非常大,

 

jedis中引入另外一种hash散列算法--hash一致性

1997麻省理工学生发明;引入一个2^32-1(43亿)整数环,

把节点使用ip+端口做哈希散列计算,得到43亿中一个值,投射到环中

将所有的数据key进行哈希散列计算,得到43亿中的一个

 

node1,2,3个节点启动着redis

数据分别是key1,2,3,4

根据hash散列算法都投射到一个整数上

顺时针寻找最近节点的映射规则,将key值进行存放

key1,2存储在node1

key3存储在node2

key4存储在node3

 

当增加删除节点时,迁移量有何变化?

 

增加node4,根据散列得到43亿中一个整数,投射到环上

根据顺时针寻找最近节点存储的原则,只需要迁移key4

而且可以判断,原节点数量越多,迁移量越小

 

节点删除,将node2删除,迁移key3

 

 

解决数据平衡性

单独的使用节点的ip+端口做映射,毕竟节点数量是有限的

有可能在映射时的各自分布位置并不平均,导致数据偏移量非常大

 

解决数据的平衡性引入虚拟节点

node1的ip是192.168.40.156

node2的ip是192.168.40.157

各自引入2个虚拟节点(虚拟节点的数量是非常大的)

node1-1=hash(192.168.40.156#1)

node1-2=hash(192.168.40.156#2)

node2-1=hash(192.168.40.157#1)

node2-2=hash(192.168.40.157#2)

每一个虚拟节点在哈希环上也会接收顺时针寻找最近节点的key们

通过增加节点数量(虚拟的),完成数据的映射平衡

凡是投影到node1-1,node1-2的key,都会中真实存储在node1中

所以虚拟节点越多平衡性越好

 

 

 

京淘的缓存引入

2018117

16:24

根据在模拟缓存的逻辑,思考后台什么位置可以做缓存?

商品分类树(缓存版本1)

商品列表(不好做,有分页参数)

商品新增,修改,删除

商品详情新增,修改,删除

 

 

补充内容

2018117

10:19

HASH取余数据分片

 

 

原子级操作

一系列操作如果称之为原子级,不可分割,一旦分隔开

系列操作不成功

 

 

 

当天问题

2018117

16:51

 

版本1的缓存引入京淘时

商品分类树查询

Name [spring.liveBeansView.mbeanDomain] is not bound in this Context. Unable to find [spring.liveBeansView.mbeanDomain].. Returning null.

 

原因,从mysql查询的数据没有text,state

返回json需要text和state,ItemCat类中的两个get方法,导致MAPPER转化字符串和对象时的错误

在ItemCat中添加一个注解,让MAPPER转化时忽略这两个属性


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值