Jax's Blog

Happy Coding,Happy Life


  • Home

  • About

  • Tags

  • Archives

ubuntu 使用mysql 报错this is incompatible with sql_mode=only_full_group_by

Posted on 2021-06-13 | | Visitors:

错误信息

在执行sql:select * from tablename group by id;

错误信息

1
[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'information_schema.PROFILING.SEQ' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

原因

错误的原因是我mysql版本是8.0的,5.7版本后的设置sql_mode=only_full_group_by

网上搜索解决方案是直接修改mysql配置文件(我的系统是Ubuntu16.04的,在/etc/mysql/mysql.conf.d/mysqld.cnf 中并没有sql_mode这个配置,所以直接加上就好,如果是其他系统有得修改就不用添加了)

加上如下配置:

1
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

重启mysql服务失败。

sql_mode中去除NO_AUTO_CREATE_USER。

重启成功。

upsource docker 环境搭建

Posted on 2021-02-23 | | Visitors:

安装

Pull the image from the Docker Hub Repository docker pull jetbrains/upsource:{version}

从docker源拉取最新镜像。

启动镜像:

1
2
3
4
5
6
7
docker run -it --name upsource-server-instance  \
-v {path to data directory}:/opt/upsource/data \
-v {path to conf directory}:/opt/upsource/conf \
-v {path to logs directory}:/opt/upsource/logs \
-v {path to backups directory}:/opt/upsource/backups \
-p {port on host}:8080 \
jetbrains/upsource:{version}

{path to data directory}是Upsource存放Apache Cassandra数据库的主机目录。对于一个新实例,传递一个空目录。如果不映射此路径,则在移除容器时可能会丢失Upsource数据。{path to conf directory}是Upsource存放配置文件的主机目录,这些配置文件包括环境设置、JVM选项、Hub集成设置等。{path to logs directory}是Upsource写入日志文件的主机目录。{path to backups directory}是Upsource存储备份的主机目录。有关管理备份文件的更多信息,请参阅Upsource文档;

我的启动配置参考:

1
2
3
4
5
6
7
docker run -d --name upsource-server-instance  \
-v /data/upsource/data:/opt/upsource/data \
-v /data/upsource/conf:/opt/upsource/conf \
-v /data/upsource/logs:/opt/upsource/logs \
-v /data/upsource/backups:/opt/upsource/backups \
-p 8080:8080 \
jetbrains/upsource:2020.1.1970

在启动之前必须给路径创建权限

1
2
> mkdir -p -m 750 /data/upsource/data /data/upsource/logs /data/upsource/conf /data/upsource/backups 
> chown -R 13001:13001 /data/upsource/data /data/upsource/logs /data/upsource/conf /data/upsource/backups

启动成功:

配置

访问xxx:8080地址,按照流程配置就行。

nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 80;
listen [::]:80;
server_name upsource.yummall.cn;
#root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
# to proxy WebSockets in nginx
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://127.0.0.1:8080;
proxy_pass_header Sec-Websocket-Extensions;
}
}

macOS安装nginx出错

Posted on 2021-02-16 | | Visitors:

问题

错误内容:

1
2
3
4
5
6
7
8
9
10
brew install nginx
==> Downloading https://mirrors.ustc.edu.cn/homebrew-bottles/bottles/openssl%401.1-1.1.1j.big_sur.bottle.tar.gz
#=#=#
curl: (22) The requested URL returned error: 404
Trying a mirror...
==> Downloading https://homebrew.bintray.com/bottles/openssl%401.1-1.1.1j.big_sur.bottle.tar.gz
#=#=-# #
curl: (22) The requested URL returned error: 403 Forbidden
Error: Failed to download resource "openssl@1.1"
Download failed: https://homebrew.bintray.com/bottles/openssl%401.1-1.1.1j.big_sur.bottle.tar.gz

原因&解决

之前brew使用的教育源。教育源无法找到openssl资源导致无法安装nginx

更换至阿里云的源,问题解决。

1
2
3
4
5
6
7
8
9
10
# 替换brew.git
cd "$(brew --repo)"
git remote set-url origin https://mirrors.aliyun.com/homebrew/brew.git

# 替换homebrew-core.git
cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
git remote set-url origin https://mirrors.aliyun.com/homebrew/homebrew-core.git

# 刷新源
brew update

Nginx 常用指令

nginx -V 查看版本以及配置文件地址

nginx -v 查看版本

nginx -c filename 指定配置文件

nginx -h 帮助

mybatis plus版本冲突导致的异常

Posted on 2021-02-16 | | Visitors:

错误信息

Caused by: java.lang.NoClassDefFoundError: org/mybatis/logging/LoggerFactory at com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean.(MybatisSqlSessionFactoryBean.java:98) at com.cy.ares.dao.conf.MybatisConfiguration.sqlSessionFactoryBean(MybatisConfiguration.java:151)

原因

mybatis JAR包冲突。去掉你的 mybatis-spring-boot-starter。

但是在某个项目的引入中并没有发现maven中有导入mybatis-spring-boot-starter。那么需要排查导入的包中是否有包含mybatis JAR包。方法:使用命令mvn dependency:tree 树状结构查看所有引入的jar包。然后搜索mybatis-spring-boot-starter包。找出该父级包,使用exclusion属性排除mybatis-spring-boot-starter包的导入。

为什么没人在乎你的会员权益?搭建会员体系这些坑,你都避开了吗?

Posted on 2021-02-16 | | Visitors:

会员,最初始的本质是享受特权,享受特有的优惠与福利,而所谓的“会员权益”正是“会员体系”能够长期存在的最大助力与基石。

从长期来看,平台的一切会员运营手段均是为了盈利而服务的,但短期来说,则目标各有不同。而这些目标,也恰好是搭建会员权益体系的原因:

  • 注重用户体验,提升用户粘性;
  • 培养用户对产品的忠诚度;
  • 便于构建用户画像,方便进行后期精细化管理;
  • 从会员群体中获取更多商业价值
  • 促进用户转化

……

不同的目的,决定着最终构建出的会员权益的侧重点如何,例如:

1、如果以提升用户粘性为主,那么会员权益中则需要侧重服务类型权益。通过会员体系的建立,筛选出较高等级的会员,给与其减免费用、优先应答、专人服务等权益。如此可在尽量少的成本下,得到更好的效果,用户也会为了更高级的服务而提升自己等级;

2、 如果以商业价值为主,那么会员权益中可以提供实物或虚拟商品为主,通过利益诱导,吸引其在平台下单转化,同时消耗积分,会员等级越高,花费则越少。

你能给会员提供的价值是什么?

你能给会员提供什么?24小时客服、98折、会员日福利?很多企业在设置会员权益之时,都陷入了一个怪圈——不管有没有用,权益显得越多越好。

实际上,这类拍脑袋定出来的会员权益存在着三大问题:

  1. 没有重点。会员权益宜精不宜多,列出太多反而没有重点;

  2. 权益过于普通。例如生日积分奖励、直邮杂志、购物折扣等等,用户在被各类优惠反复轰炸的今天,太过普通的权益无法对会员产生吸引力;

  3. 权益不明确。“生日贺礼”是什么?是高端生日礼品还是电子贺卡?“高端圈层活动”又是什么?都是些什么人参加?什么主题?此类权益会让会员觉得莫名其妙,反而产生反作用。

因此,在搭建会员权益体系之前,你需要确定好你能给用户提供的价值(不仅仅指权益内容)是什么。而确定这个,可以通过问自己以下几个问题来解决:

  • 你所在的平台可以提供或者置换到哪些资源或者服务?写张表格,把它们和对接人一起列出来;

  • 这些权益中,成本是多少?通过成本的关系,将它们排列出来,划定等级;

  • 摆在你面前的这张表格里,有没有哪些资源或服务是对用户真正有用的?把自己代入用户视角,并把这些没用的资源剔除;

  • 能否把这些权益包装一下,打包或者取一个比较吸引人的名字?或者使用其他方法,让这些权益的价值看起来更加大;

  • 最后一点,这些权益是否会对实现平台短期目标有帮助?是否会产生被刷单薅羊毛等反作用?

如何设计一套诱人的会员权益?

1、以最高层级诉求优先对标

既然会员体系本身就是为了满足高价值用户,设计权益,应该先从头部用户开始,和非头部用户相比,头部用户需求度、产品了解度、挑剔度都比较高,满足了头部用户的权益,也就验证了权益设计的成功。

2、围绕核心动作设计权益

所谓的核心动作,就是用户为获得产品价值所做出的的动作,也是企业最希望用户完成的动作。交易类产品核心动作是下单,在线内容的核心动作是观看内容。不论增值还是降低成本,设计权益需始终以促进核心动作的发生为目标。如,电商权益折扣、无理由退货,都为了让用户下单更爽,而电商企业可以获得更多收入。

3、合理控制权益成本

权益成本越高,权益价值吸引力一般也越大,一般的硬权益,需要花费较高的成本。但如果权益过高,会员的利润就会降低。所以,通常在做权益预算时,需要考虑这两个问题:

  1. 现有的预算能否满足会员增长
  2. 权益的ROI如何

4、简单直接,不过分花哨

一般一个会员体系有1个硬权益就会有效果,为了便于用户理解及记忆,一般来说,权益不宜过多,主打1-2个硬权益即可,适度增加一些额外权益,后续在做会员的心智教育时,让用户更聚焦地感知会员价值,为拉新和会员忠诚服务。

5、权益要设置一定的区隔

没有比较就没有伤害,比较会加剧价值感,会员对不同层级的权益比较,也会影响价值感。付费会员体系中,如付费和免费差异不大,用户就不会购买。在设计权益时,让差异感尽可能拉大,在高层级中提供专属层级权益,凸显会员、尤其是高等级会员的价值感。

我们来举个例子:

趣悠悠是一家趣味民宿在线预订平台,通过卖定价788元的会员卡,3个月覆盖全国20多个目的地,我们来看看是怎么设计的:

以足够吸引力的价格,让利给客户,降低住宿门槛。客户只需付 788 元,即可获得市价为 300-2000 元/间夜的轻奢型民宿 6 晚的权益。客户在「住一晚即可回本」的刺激下,很容易做出购买决定。

这里面既围绕了核心动作设计权益,吸引用户快速下单。又解决了淡季民宿无人问津的问题,也很好的控制了ROI。

1366

再看一家,正善牛肉是如何设置会员卡等级的:

正善牛肉做过多次不同方案后,最终确定将付费会员卡设为3个等级,价格越高,可享受的权益越多、越实惠。

等级一:28元超级会员双日卡,购买享会员价;

等级二:178元超级会员月卡,购买享会员价和包邮;

等级三:999元超级会员年卡,购买享社群内专享商品享折上折、包邮、随时退服务。

付费会员卡的定价是如何考虑的?

① 根据会员价设置入门最低门槛。会员价相当于原价的5.5-7折,而正善的商品最低价格都在200元左右,所以意味着会员至少可享受减60元的优惠,最低门槛的双日卡价格定为28元,优惠的价格远超双日卡的费用,用户自然就会选择购买付费会员卡。

② 区分包邮权益。正善牛肉是顺丰全冷链运输,平均运费在50元左右,但双日卡不包邮,客户需要自己承担运费。这时168元的月卡成为最好的选择,因为会员价享受的优惠加上邮费,最低也有110元了,购买两次,享受的优惠就可以抵消月卡的费用。

③ 利用“物尽其用”消费心理。想在一次购物当中将168元的卡费省回,至少要买6斤牛肉,一个3口之家短期内较难消耗这些牛肉。但大部分人都有“既然买了卡,那就要物尽其用”的心理,这促使客户进店复购或发动好友一起买,让用户自发的引流与复购。

正是这样的定价为正善每月带来超过80%的复购和持续不断的粉丝增长,客单价也从17年的300元提高到现在的1035元。

应用在docker环境下使用new font()黑体、宋体字体显示方框乱码

Posted on 2021-01-16 | | Visitors:

问题

应用在docker环境下使用new font()黑体、宋体字体显示方框乱码。

图片上的汉字是用new font画出来的,使用的黑体字体。

解决

可以在Windows系统目录 C:\Windows\Fonts 复制需要的字体到项目里, 然后在Dockerfile 引入.

找到所需要的字体文件,如黑体为:simhei.ttf。复制到dockerfile所在目录下。

image-20210531164326907

dockerfile加入:

1
COPY fonts/simhei.ttf /usr/share/fonts/

重新构建镜像。问题解决

用nacos下使用dubbo会连接旧的服务ip情况

Posted on 2020-12-16 | | Visitors:

问题

nacos服务器所在IP进行了更换,dubbo consumers启动依然请求旧的providers服务地址。

  • 首先排除dubbo缓存,找到文件夹:$用户名$/.dubbo 删除文件夹下文件。问题依然重现。

  • 删除nacos注册缓存,找到文件夹: $用户名$/nacos 删除文件夹下所有文件,问题解决。

思考

dubbo缓存

  • 根据官方图,dubbo调用者需要通过注册中心(例如:ZK、nacos)注册信息,获取提供者,但是如果频繁往ZK获取信息,肯定会存在单点故障问题,所以dubbo提供了将提供者信息缓存在本地的方法。
  • Dubbo在订阅注册中心的回调处理逻辑当中会保存服务提供者信息到本地缓存文件当中(同步/异步两种方式),以url纬度进行全量保存。
  • Dubbo在服务引用过程中会创建registry对象并加载本地缓存文件,会优先订阅注册中心,订阅注册中心失败后会访问本地缓存文件内容获取服务提供信息。

nacos缓存

查看源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public void init() {
executorService.scheduleWithFixedDelay(new SwitchRefresher(), 0L, 5000L, TimeUnit.MILLISECONDS);
executorService.scheduleWithFixedDelay(new DiskFileWriter(), 30, DAY_PERIOD_MINUTES, TimeUnit.MINUTES);
// backup file on startup if failover directory is empty.
executorService.schedule(new Runnable() {
@Override
public void run() {
try {
File cacheDir = new File(failoverDir);

if (!cacheDir.exists() && !cacheDir.mkdirs()) {
throw new IllegalStateException("failed to create cache dir: " + failoverDir);
}

File[] files = cacheDir.listFiles();
if (files == null || files.length <= 0) {
new DiskFileWriter().run();
}
} catch (Throwable e) {
LogUtils.LOG.error("NA", "failed to backup file on startup.", e);
}

}
}, 10000L, TimeUnit.MILLISECONDS);}

创建定时器,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class SwitchRefresher implements Runnable {
long lastModifiedMillis = 0L;
@Override
public void run() {
try {
File switchFile = new File(failoverDir + UtilAndComs.FAILOVER_SWITCH);
if (!switchFile.exists()) {
switchParams.put("failover-mode", "false");
LogUtils.LOG.debug("failover switch is not found, " + switchFile.getName());
return;
}
long modified = switchFile.lastModified();
if (lastModifiedMillis < modified) {
lastModifiedMillis = modified;
String failover = ConcurrentDiskUtil.getFileContent(failoverDir + UtilAndComs.FAILOVER_SWITCH, Charset.defaultCharset().toString());
if (!StringUtils.isEmpty(failover)) {
List<String> lines = Arrays.asList(failover.split(DiskCache.getLineSeperator()));
for (String line : lines) {
String line1 = line.trim();
if ("1".equals(line1)) {
switchParams.put("failover-mode", "true");
LogUtils.LOG.info("failover-mode is on");
new FailoverFileReader().run();
} else if ("0".equals(line1)) {
switchParams.put("failover-mode", "false");
LogUtils.LOG.info("failover-mode is off");
}
}
} else {
switchParams.put("failover-mode", "false");
}
}
} catch (Throwable e) {
LogUtils.LOG.error("NA", "failed to read failover switch.", e);
}
}}

首先判定下容灾开关是否有,容灾开关是一个磁盘文件的形式存在,通过容灾开关文件名字,判定容灾开关是否打开,1表示打开,0为关闭,读取到容灾开关后,将值更新到内存中,后续解析地址列表时,首先会判定一下容灾开关是否打开,如果打开了,就读缓存的数据,否则从服务端获取最新数据。

猜测是容灾开关打开状态,所以一直取的缓存的数据。

Docker安装redis使用自定义配置

Posted on 2020-10-17 | | Visitors:

获取 redis 镜像 docker pull redis

gSU9Em

查看本地镜像 docker images

wO8HzQ

从官网获取 redis.conf 配置文件

  1. 修改默认配置文件
  • bind 127.0.0.1 #注释掉这部分,这是限制redis只能本地访问
  • protected-mode no #默认yes,开启保护模式,限制为本地访问
  • daemonize no#默认no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程(可选),改为yes会使配置文件方式启动redis失败
  • dir ./ #输入本地redis数据库存放文件夹(可选)
  • appendonly yes #redis持久化(可选)
  1. docker 启动 redis 命令

    docker run -p 6379:6379 --name redis -v /usr/local/docker/redis.conf:/etc/redis/redis.conf -v /usr/local/docker/data:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes

  2. 不挂载配置文件:

    docker run --name redis -p 6379:6379 -d --restart=always redis redis-server --appendonly yes --requirepass "这是密码"

  3. 命令解释说明:

  • -p 6379:6379 端口映射:前表示主机部分,:后表示容器部分。
  • –name myredis 指定该容器名称,查看和进行操作都比较方便。
  • -v 挂载目录,规则与端口映射相同。
  • -d redis 表示后台启动redis
  • redis-server /etc/redis/redis.conf 以配置文件启动redis,加载容器内的conf文件,最终找到的是挂载的目录/usr/local/docker/redis.conf
  • appendonly yes 开启redis 持久化

运行成功

  1. 使用docker ps 查看redis已经运行了

    O4XLe7

  2. 使用 docker exec -it redis /bin/bash进入redis

  3. 使用 redis-cli 可以测试连接。

  4. 这样是默认不设置密码的,spring连接方式配置为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# REDIS配置

# Redis数据库索引(默认为0)
spring.redis.database=0

# Redis服务器IP地址
spring.redis.host=127.0.0.1

# Redis服务器连接端口
spring.redis.port=6379

# Redis服务器连接密码(默认为空,可不配置此项)
# spring.redis.password=xxx

# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=500

# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.lettuce.pool.max-wait=-1

# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=8

# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0

# 连接超时时间(毫秒)
spring.redis.timeout=0

微信小程序页面滚动事件导致的点击事件延迟

Posted on 2020-10-14 | | Visitors:

起因

小程序上线之后发现一个奇怪的现象,页面向下滑动,点击事件会延迟几秒。滑动的越多,延迟就越久,点击会出现几秒才会能打开新的页面。前端同学没有排查出原因,更换了几种跳转方式问题依旧。

排查

review了一下代码,发现如下代码。能看出问题吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
onPageScroll(e) {
if (this.data.offsetTop >= e.scrollTop && this.data.isFixed) {
this.getHeaderHeight();
this.setData({
isFixed: false
})
} else {
this.getHeaderHeight();
this.setData({
isFixed: true
})
}
}

页面滚动事件中会不断的执行 setData事件,导致事件阻塞。

更改成如下代码解决:

1
2
3
4
5
6
7
8
9
10
11
12
13
onPageScroll(e) {
if (this.data.offsetTop >= e.scrollTop && this.data.isFixed) {
this.getHeaderHeight();
this.setData({
isFixed: false
})
} else if(e.scrollTop > this.data.offsetTop && !this.data.isFixed){
this.getHeaderHeight();
this.setData({
isFixed: true
})
}
}

阿里云ECS服务器跨地域跨账号内网互通

Posted on 2020-10-14 | | Visitors:

根源

阿里云所有的特惠活动都是针对新用户,一台1W+的服务器,新用户可以拿到3千多3年,老用户则只有一点点优惠。无奈为了省钱只能拿新手机,新身份证,新公司资质申请账号进行购买,所以导致现在手上的阿里云账号有十来个了。所以务必要解决这十几个账号里的ECS资源能够内网互通。

同地域内网互通方案

云企业网(Cloud Enterprise Network)是承载在阿里云提供的高性能、低延迟的私有全球网络上的一张高可用网络。

云企业网可帮助您在不同地域VPC间,VPC与本地数据中心间搭建私网通信通道,通过自动路由分发及学习,提高网络的快速收敛和跨网络通信的质量和安全性,实现全网资源的互通,帮助您打造一张具有企业级规模和通信能力的互联网络。

  1. 首先拿一个主账号创建云企网实例

    https://cen.console.aliyun.com/cen/list

  2. 其他需要加入云企网的账号,进入专有网络VPC控制台,云企网跨账号授权给刚刚创建的主账号。

    d0wj4O

  3. 再回到主账号上的云企网,进入详情,点击加载网络实例,填写其他账号的信息。

    ![image-20201105203241525](/Users/jax/Library/Application Support/typora-user-images/image-20201105203241525.png)

  4. 这样就完成了同地域跨账号的内网互通。如碰到内网还是不通,可能是内网IP段冲突,更改VPC交换机IP段。不知道怎么操作提交宫工单给阿里云。

跨地域互通方案

这个就要花钱了。购买跨地域宽带包,然后按照上述步骤加载网络实例。

4pWNbK

12…6>
Jax

Jax

52 posts
1 categories
23 tags
GitHub E-Mail 摄影/图虫
© 2022 Jax
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4
湘ICP备12012411号-3