gitweixin
  • 首页
  • 小程序代码
    • 资讯读书
    • 工具类
    • O2O
    • 地图定位
    • 社交
    • 行业软件
    • 电商类
    • 互联网类
    • 企业类
    • UI控件
  • 大数据开发
    • Hadoop
    • Spark
    • Hbase
    • Elasticsearch
    • Kafka
    • Flink
    • 数据仓库
    • 数据挖掘
    • flume
    • Kafka
    • Hive
    • shardingsphere
    • solr
  • 开发博客
    • Android
    • php
    • python
    • 运维
    • 技术架构
    • 数据库
  • 程序员网赚
  • bug清单
  • 量化投资
  • 在线查询工具
    • 去行号
    • 在线时间戳转换工具
    • 免费图片批量修改尺寸在线工具
    • SVG转JPG在线工具

月度归档2月 2021

精品微信小程序开发门户,代码全部亲测可用

  • 首页   /  2021   /  
  • 2月
  • ( 页面4 )
flume 2月 20,2021

Flume处理Spooling Directory Source数据太慢优化

一个数据采集处理系统,架构如下:

日志数据 -> flume -> kafka -> Spark Streaming。

flume到kafka的数据处理时间是1秒多;而spark Streaming的数据处理时间是十几毫秒。

flume方面:

flume数量不够:增加日志服务器以增加并行度;

(1)自身:增加内存flume-env.sh 4-6g

-Xmx与-Xms最好设置一致,减少内存抖动带来的性能影响,如果设置不一致容易导致频繁fullgc。

(2)找朋友:多个目录,多个spooling directory source同时采集

(3)taildir source的batchsize修改为合适的值

( 4 ) flume要读取文件夹如果文件太多,要按最新或最早顺序读取时,会很影响速度。

# batchsize是每次处理的数据条数越高,处理的数据越多,延迟越高。

kafka数据积压的问题,主要的解决办法是:

(1)增加Kafka对应的分区数(比如:期望处理数据的总吞吐量是100M/s。但是实际最多每个分区的生产能力和消费能力的最小值是20M/s,那么我们就需要设置5个或者6个分区),2)要求下一级消费者配套增加CPU核数,动态增加Kafka服务器集群。

(2)kafka ack设成0(ack有0有1有-1。0的可靠性最差,但是速度最快)

注:ack有3个可选值,分别是1,0,-1。

ack=1,简单来说就是,producer只要收到一个分区副本成功写入的通知就认为推送消息成功了。这个副本必须是leader副本。只有leader副本成功写入了,producer才会认为消息发送成功。

ack=0,简单来说就是,producer发送一次就不再发送了,不管是否发送成功。

ack=-1,简单来说就是,producer只有收到分区内所有副本的成功写入的通知才认为推送消息成功了。

(3) a1.channels.c1.type = memory memory类型可能会丢失数据,但是速度最快。

作者 east
bug清单, flume 2月 20,2021

Flume Spooling Directory Source 采集NullPointerException

采用flume的Spooling Directory Source,突然遇到下面的错误

(org.apache.flume.source.SpoolDirectoryExtSource2$SpoolDirectoryRunnable.run:277)  - FATAL: Spool Directory source source1: { spoolDir: /home/work/local/log }: Uncaught exception in SpoolDirectorySource thread. Restart or reconfigure Flume to continue processing.
java.lang.NullPointerException
    at org.apache.avro.io.ResolvingDecoder.readLong(ResolvingDecoder.java:159)
    at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:157)
    at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:177)
    at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:148)
    at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:139)
    at org.apache.avro.file.DataFileStream.next(DataFileStream.java:233)
    at org.apache.flume.serialization.DurablePositionTracker.initReader(DurablePositionTracker.java:171)
    at org.apache.flume.serialization.DurablePositionTracker.<init>(DurablePositionTracker.java:158)
    at org.apache.flume.serialization.DurablePositionTracker.getInstance(DurablePositionTracker.java:76)
    at org.apache.flume.client.avro.ReliableSpoolingFileEventExtReader2.openFile(ReliableSpoolingFileEventExtReader2.java:561)
    at org.apache.flume.client.avro.ReliableSpoolingFileEventExtReader2.getNextFile(ReliableSpoolingFileEventExtReader2.java:511)
    at org.apache.flume.client.avro.ReliableSpoolingFileEventExtReader2.readEvents(ReliableSpoolingFileEventExtReader2.java:264)
    at org.apache.flume.source.SpoolDirectoryExtSource2$SpoolDirectoryRunnable.run(SpoolDirectoryExtSource2.java:252)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

重启flume 后发现问题依旧。试验把flume 采集的日志放到新目录,重启flume采集新目录发现没问题了。看来是旧目录/home/work/local/log 有文件变动造成的。

例如 有.flumespool隐藏目录,该目录下有文件.flumespool-main.meta隐藏文件,用来记录flume读取文件的位置,发现该记录停止在flume出问题的时间。再查看其它正常运行的机器的相同路径及文件,并没有发现该文件,于是将该文件移到其它目录下,重启flume,此时发现flume成功运行!

作者 east
运维 2月 19,2021

linode如何迁移服务器

linode是个性价比的服务器,广受广大站长喜欢。由于种种原因,可以很方便进行不同地区迁移。例如linode日本地区服务器,在中国用移动网络不太稳定,要迁移到加州。

方法/步骤

  1. 虽然迁移服务器理论上讲只是ip变了,不影响服务上网站运行。但为防止万一,最后进行备份。登录linode服务器,找到要迁移的服务器,选择”Migrate”
  2. 在下一步的界面中,勾选同意,选择要迁移的服务器地区。最后点击“Enter Migrate Queue”
  3. 完成上一步后,可以在服务器的status上看到迁移的进度。迁移完成后会自动重启。
  4. 迁移服务后,由于ip变了,所以要在域名解析中,把新ip替换旧的ip。
作者 east
bug清单, python 2月 15,2021

python3解决解决Please use the NLTK Downloader to obtain the resource

运行环境是windows,python3,运行python程序出现下面的错误:

  Please use the NLTK Downloader to obtain the resource:

  [31m>>> import nltk
  >>> nltk.download(‘stopwords’)
  [0m
  Searched in:
    – ‘C:\\Users\\99386/nltk_data’
    – ‘C:\\nltk_data’
    – ‘D:\\nltk_data’
    – ‘E:\\nltk_data’
    – ‘F:\\Program Files\\Python\\Python36\\nltk_data’
    – ‘F:\\Program Files\\Python\\Python36\\lib\\nltk_data’
    – ‘C:\\Users\\99386\\AppData\\Roaming\\nltk_data’

>>>python

>>> import nltk
>>> nltk.download(‘punkt’)

按照上面的命令会安装失败。要采用下面变通的方式:

接下来我们去https://github.com/nltk/nltk_data下载我们需要的数据。

只需下载正数第二个“packages”文件夹即可。把packages文件夹下的所有子文件夹拷贝至上面报错一个路径,例如F:\\Program Files\\Python\\Python36\\nltk_data 。请注意,不要把packages拷过去,而是packages的子文件夹。还有注意包含子文件夹,要把有些压缩包解压,例如把tokenizers下的punkt.zip解压(注意不要多了一层嵌套)。这时运行python程序可以看到原来的问题解决了。

作者 east
bug清单, shardingsphere 2月 13,2021

解决DATE_FORMAT(data_create_time, ‘%Y-%m-%d’)>= DATE_FORMAT(?, ‘%Y-%m-%d’)报错

使用 shardingsphere 4.1.0版本,代码如下:

 PreparedStatement ps = conn.prepareStatement("select * from test where DATE_FORMAT(create_date, '%Y-%m-%d')>= DATE_FORMAT(?, '%Y-%m-%d') limit ?,?");
    ps.setString(1,"2020-02-01");
    ps.setInt(2,1);
    ps.setInt(3,10)

报以下的错:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at org.apache.shardingsphere.sql.parser.binder.segment.select.pagination.PaginationContext.getValue(PaginationContext.java:57) ~[shardingsphere-sql-parser-binder-4.1.0.jar:4.1.0]
at org.apache.shardingsphere.sql.parser.binder.segment.select.pagination.PaginationContext.(PaginationContext.java:50) ~[shardingsphere-sql-parser-binder-4.1.0.jar:4.1.0]
at org.apache.shardingsphere.sql.parser.binder.segment.select.pagination.engine.LimitPaginationContextEngine.createPaginationContext(LimitPaginationContextEngine.java:38) ~[shardingsphere-sql-parser-binder-4.1.0.jar:4.1.0]
at org.apache.shardingsphere.sql.parser.binder.segment.select.pagination.engine.PaginationContextEngine.createPaginationContext(PaginationContextEngine.java:48) ~[shardingsphere-sql-parser-binder-4.1.0.jar:4.1.0]
at org.apache.shardingsphere.sql.parser.binder.statement.dml.SelectStatementContext.(SelectStatementContext.java:100) ~[shardingsphere-sql-parser-binder-4.1.0.jar:4.1.0]
at org.apache.shardingsphere.sql.parser.binder.SQLStatementContextFactory.getDMLStatementContext(SQLStatementContextFactory.java:103) ~[shardingsphere-sql-parser-binder-4.1.0.jar:4.1.0]
at org.apache.shardingsphere.sql.parser.binder.SQLStatementContextFactory.newInstance(SQLStatementContextFactory.java:87) ~[shardingsphere-sql-parser-binder-4.1.0.jar:4.1.0]
at org.apache.shardingsphere.underlying.route.DataNodeRouter.createRouteContext(DataNodeRouter.java:99) ~[shardingsphere-route-4.1.0.jar:4.1.0]
at org.apache.shardingsphere.underlying.route.DataNodeRouter.executeRoute(DataNodeRouter.java:89) ~[shardingsphere-route-4.1.0.jar:4.1.0]
at org.apache.shardingsphere.underlying.route.DataNodeRouter.route(DataNodeRouter.java:76) ~[shardingsphere-route-4.1.0.jar:4.1.0]

经过测试,传递的参数如果为string类型就报下面的错误,如果把类型修正为Date类型则不会报如下错误。配置:

spring:
  shardingsphere:
    encrypt:
      encryptors:
        aesEncryptor:
          type: aes
          props:
            aes.key.value: 123456
      tables:
        linkman:
          columns:
            mobile:
              plainColumn: mobile
              cipherColumn: mobile_encrypted
              encryptor: aesEncryptor
    datasource:
      names: ds
      ds:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/shardingsphere_test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
        username: root
        password: root
        connection-timeout: 30000
        maximum-pool-size: 20
        minimum-idle: 5
        auto-commit: true
        idle-timeout: 600000
        pool-name: crm-hikari
        max-lifetime: 1800000
        connection-test-query: SELECT 1
    props:
      query.with.cipher.column: false
<select id="selectByTime" resultMap="BaseResultMap"  parameterType="string">
        SELECT  <include refid="Base_Column_List"/>
         FROM linkman
         WHERE DATE_FORMAT(create_time, '%Y-%m-%d') =  DATE_FORMAT(#{createTime},'%Y-%m-%d')
    </select>

    List<Linkman> selectByTime(@Param("createTime") String createTime);
//如果把createTime的类型修改为Date类型则不会报错.
作者 east
python 2月 13,2021

最新亲测可用的免费google翻译api

google翻译的水平越来越高,用处还不少,每次通过访问translate.google.cn来复制粘贴觉得效率太慢。

官方的google翻译好像要收费,找了一圈google翻译的免费api,特别是github上面的,发现好些开源项目已经过时,因为google更新了ttk的token。

找了好些java语言发现不可用,最后发现这个python开源项目更新日期挺近的,亲测是可用,免费而且速度很快。

https://github.com/Saravananslb/py-googletranslation

这个开源项目要求依赖是  Python 3.6+ 。如果没安装的可以到 这里下载: https://www.python.org/downloads/release/python-391/

。为了使用方便,安装了带pip管理工具的。

下载py-googletranslation,

$ pip install pygoogletranslation

为了科学上网,原来开源项目默认的google.com是访问不了的,要做下面修改,或直接找到下载代码,把google.com修改为google.cn
>>> from googletrans import Translator
>>> translator = Translator(service_urls=[
      'translate.google.cn',   
    ])

基础用法:

如果没有指定源语言,会自动侦测源语言

>>> from pygoogletranslation import Translator
>>> translator = Translator()
>>> translator.translate('Good Morning', dest='ta')
# <Translated src=ko dest=ta text=காலை வணக்கம். pronunciation=Good evening.>
>>> translator.translate('안녕하세요.', dest='ja')
# <Translated src=ko dest=ja text=こんにちは。 pronunciation=Kon'nichiwa.>
>>> translator.translate('veritas lux mea', src='la')
# <Translated src=la dest=en text=The truth is my light pronunciation=The truth is my light>

高级用法(批量):

可以使用数组批量翻译,只是简单调用一个http session

>>> from pygoogletranslation import Translator
>>> translator = Translator()
>>> t = (translator.translate(["Good ' Morning", "India"], dest="ta"))
>>> for _t in t:
>>>     print(_t.text)
# காலை வணக்கம்
# இந்தியா

语言检测:

>>> from pygoogletranslation import Translator
>>> translator = Translator()
>>> translator.detect('காலை வணக்கம்,')
# <Detected lang=ta confidence=0.72041003>
>>> translator.detect('この文章は日本語で書かれました。')
# <Detected lang=ja confidence=0.64889508>
>>> translator.detect('This sentence is written in English.')
# <Detected lang=en confidence=0.22348526>
>>> translator.detect('Tiu frazo estas skribita en Esperanto.')
# <Detected lang=eo confidence=0.10538048>

翻译文档类型的(.doc, .docx, .pdf, .txt):

>>> from pygoogletranslation import Translator
>>> translator = Translator()
>>> translator.bulktranslate('test.txt', dest="ta")
# <bulk translated text>
# for bulk translation, sometimes you might get an error with response
# code "429" - Too Many attempts.
# To overcome this error, add below parameter.
>>> translator = Translator(retry=NO_OF_ATTEMPTS, sleep=WAIT_SECONDS, retry_message=TRUE)
>>> translator.bulktranslate('test.txt', dest="ta")
# retry - no of attemps (default- 3 times)
# sleep - no of attempts after seconds (default- 5 seconds)
# retry_message - True - display retrying message (default- False)
pygoogletranslation定义的语言列表
>>> from pygoogletranslation import Translator
>>> translator = Translator()
>>> translator.glanguage()
>>> {
   "sl": {
   "auto": "Detect language",
   "af": "Afrikaans",
   "sq": "Albanian",
   "am": "Amharic",
   "ar": "Arabic",
   "hy": "Armenian",
   "az": "Azerbaijani",
   "eu": "Basque",
   "be": "Belarusian",
   "bn": "Bengali",
   "bs": "Bosnian",
   "bg": "Bulgarian",
   "ca": "Catalan",
   "ceb": "Cebuano",
   "ny": "Chichewa",
   "zh-CN": "Chinese",
   "co": "Corsican",
   "hr": "Croatian",
   "cs": "Czech",
   "da": "Danish",
   "nl": "Dutch",
   "en": "English",
   "eo": "Esperanto",
   "et": "Estonian",
   "tl": "Filipino",
   "fi": "Finnish",
   "fr": "French",
   "fy": "Frisian",
   "gl": "Galician",
   "ka": "Georgian",
   "de": "German",
   "el": "Greek",
   "gu": "Gujarati",
   "ht": "Haitian Creole",
   "ha": "Hausa",
   "haw": "Hawaiian",
   "iw": "Hebrew",
   "hi": "Hindi",
   "hmn": "Hmong",
   "hu": "Hungarian",
   "is": "Icelandic",
   "ig": "Igbo",
   "id": "Indonesian",
   "ga": "Irish",
   "it": "Italian",
   "ja": "Japanese",
   "jw": "Javanese",
   "kn": "Kannada",
   "kk": "Kazakh",
   "km": "Khmer",
   "rw": "Kinyarwanda",
   "ko": "Korean",
   "ku": "Kurdish (Kurmanji)",
   "ky": "Kyrgyz",
   "lo": "Lao",
   "la": "Latin",
   "lv": "Latvian",
   "lt": "Lithuanian",
   "lb": "Luxembourgish",
   "mk": "Macedonian",
   "mg": "Malagasy",
   "ms": "Malay",
   "ml": "Malayalam",
   "mt": "Maltese",
   "mi": "Maori",
   "mr": "Marathi",
   "mn": "Mongolian",
   "my": "Myanmar (Burmese)",
   "ne": "Nepali",
   "no": "Norwegian",
   "or": "Odia (Oriya)",
   "ps": "Pashto",
   "fa": "Persian",
   "pl": "Polish",
   "pt": "Portuguese",
   "pa": "Punjabi",
   "ro": "Romanian",
   "ru": "Russian",
   "sm": "Samoan",
   "gd": "Scots Gaelic",
   "sr": "Serbian",
   "st": "Sesotho",
   "sn": "Shona",
   "sd": "Sindhi",
   "si": "Sinhala",
   "sk": "Slovak",
   "sl": "Slovenian",
   "so": "Somali",
   "es": "Spanish",
   "su": "Sundanese",
   "sw": "Swahili",
   "sv": "Swedish",
   "tg": "Tajik",
   "ta": "Tamil",
   "tt": "Tatar",
   "te": "Telugu",
   "th": "Thai",
   "tr": "Turkish",
   "tk": "Turkmen",
   "uk": "Ukrainian",
   "ur": "Urdu",
   "ug": "Uyghur",
   "uz": "Uzbek",
   "vi": "Vietnamese",
   "cy": "Welsh",
   "xh": "Xhosa",
   "yi": "Yiddish",
   "yo": "Yoruba",
   "zu": "Zulu"
   },
   "tl": {
   "af": "Afrikaans",
   "sq": "Albanian",
   "am": "Amharic",
   "ar": "Arabic",
   "hy": "Armenian",
   "az": "Azerbaijani",
   "eu": "Basque",
   "be": "Belarusian",
   "bn": "Bengali",
   "bs": "Bosnian",
   "bg": "Bulgarian",
   "ca": "Catalan",
   "ceb": "Cebuano",
   "ny": "Chichewa",
   "zh-CN": "Chinese (Simplified)",
   "zh-TW": "Chinese (Traditional)",
   "co": "Corsican",
   "hr": "Croatian",
   "cs": "Czech",
   "da": "Danish",
   "nl": "Dutch",
   "en": "English",
   "eo": "Esperanto",
   "et": "Estonian",
   "tl": "Filipino",
   "fi": "Finnish",
   "fr": "French",
   "fy": "Frisian",
   "gl": "Galician",
   "ka": "Georgian",
   "de": "German",
   "el": "Greek",
   "gu": "Gujarati",
   "ht": "Haitian Creole",
   "ha": "Hausa",
   "haw": "Hawaiian",
   "iw": "Hebrew",
   "hi": "Hindi",
   "hmn": "Hmong",
   "hu": "Hungarian",
   "is": "Icelandic",
   "ig": "Igbo",
   "id": "Indonesian",
   "ga": "Irish",
   "it": "Italian",
   "ja": "Japanese",
   "jw": "Javanese",
   "kn": "Kannada",
   "kk": "Kazakh",
   "km": "Khmer",
   "rw": "Kinyarwanda",
   "ko": "Korean",
   "ku": "Kurdish (Kurmanji)",
   "ky": "Kyrgyz",
   "lo": "Lao",
   "la": "Latin",
   "lv": "Latvian",
   "lt": "Lithuanian",
   "lb": "Luxembourgish",
   "mk": "Macedonian",
   "mg": "Malagasy",
   "ms": "Malay",
   "ml": "Malayalam",
   "mt": "Maltese",
   "mi": "Maori",
   "mr": "Marathi",
   "mn": "Mongolian",
   "my": "Myanmar (Burmese)",
   "ne": "Nepali",
   "no": "Norwegian",
   "or": "Odia (Oriya)",
   "ps": "Pashto",
   "fa": "Persian",
   "pl": "Polish",
   "pt": "Portuguese",
   "pa": "Punjabi",
   "ro": "Romanian",
   "ru": "Russian",
   "sm": "Samoan",
   "gd": "Scots Gaelic",
   "sr": "Serbian",
   "st": "Sesotho",
   "sn": "Shona",
   "sd": "Sindhi",
   "si": "Sinhala",
   "sk": "Slovak",
   "sl": "Slovenian",
   "so": "Somali",
   "es": "Spanish",
   "su": "Sundanese",
   "sw": "Swahili",
   "sv": "Swedish",
   "tg": "Tajik",
   "ta": "Tamil",
   "tt": "Tatar",
   "te": "Telugu",
   "th": "Thai",
   "tr": "Turkish",
   "tk": "Turkmen",
   "uk": "Ukrainian",
   "ur": "Urdu",
   "ug": "Uyghur",
   "uz": "Uzbek",
   "vi": "Vietnamese",
   "cy": "Welsh",
   "xh": "Xhosa",
   "yi": "Yiddish",
   "yo": "Yoruba",
   "zu": "Zulu"
   },
   "al": {}
   }
#!/usr/bin/python
import sys
import time
import os
def main():               
	from pygoogletranslation import Translator
	translator = Translator()
	count = 0
	with open('result.txt', 'w', encoding='gb18030') as df:
	    result = translator.bulktranslate('test.txt', dest="en")
	    df.write(result.text)

if __name__ == "__main__":
	main()

作者 east
bug清单, Elasticsearch 2月 12,2021

ES无法重启问题分析

ES无法重启问题分析

题背景:

对ES集群进行了重启,集群重启几分钟后,部分实例开始逐渐下线,导致集群不可恢复。

集群规模:

普通模式,3EsMaster,40EsNode,每实例均为31GB内存。

数据量:

1000多index,38365个shard,其中主分片28695个,数据量100T。

日志分析:

ES集群重启,恢复几分钟后,出现大量ping Master节点超时的错误,然后ES节点实例开始逐渐下线,导致集群恢复不了。

原因分析:

集群分片数过多,并发恢复过程中,同时业务没有停止,导致EsMaster处理压力过大,number_of_pending_tasks(挂起的任务)逐渐增加,到达4W多,大量的任务阻塞。

此时_cluster/health命令已无法正常返回结果,导致大量ES实例处于恢复中状态,连续3次检查超时后,Manger将会重启实例。就会导致挂起的任务越来越多,集群不可恢复。

处理步骤:

  1. 重启的过程中,发现大量ES实例执行_cluster/health命令超时错误,但其实数据仍在缓慢恢复中。于是注释_cluser/health检查脚本,防止实例多次失败后,被manger重启。
  2. 再次重启后,发现大量分片处于未分配状态,执行_cluster/allocation/explain查看分片未被分配的原因,发现shard恢复时的cluster.routing.allocation.node_current_incoming达到了最大值。鉴于集群主分片数太多,于是调大恢复参数至:cluster.routing.allocation.node_initial_primaries_recoveries 200 cluster.routing.allocation.node_concurrent_recoveries 100 cluster.routing.allocation.cluster_concurrent_rebalance 100 同时因为有业务数据写入,将分片分配设置为none:cluster.routing.allocation.enable none
  3. 再次重启后,集群开始恢复,查看_cat/thred_pool/,generic 线程池(分片恢复会用到该线程池)已经到达128,查看界面CPU使用率也在70-80,查看日志,分片正在恢复中。
  4. 10分钟左右,集群恢复到80%左右,开始恢复缓慢,初始化分片(initializing_shards)有2000多个,这些分片初始化的过程耗时接近2小时 原因分析:因为在多次重启的过程中,业务侧并没有停止,由于有些primary新写入了数据,在数据的recovery过程中,需要从主副本之间拷贝数据,或者利用translog恢复数据。直达primary-replica完全in-sync后,才会完成初始化。 这个过程取决于shard的大小和新写入量的大小(初始化的分片普遍数据量较大)。
    1. 最后有一个分片无法分配,查看原因,该分片无法从translog in-sync(同步),查看该索引settings,sync_interval设置为360s,设置同步刷新时间过多,会有一定几率发生数据丢失(客户有原数据备份)。
    2. 集群恢复后,还原集群参数配置和健康检查脚本。

问题根因:

  1. 集群的分片数过多,按一个实例管理600shard为标准,该集群分片数过度超标的。合 理设置索引分片,定期对历史索引进行处理(关闭或删除不需要的索引)。
  2. 目前的健康检查机制需要优化,使用_cluster/health去判断各实例的健康是否合理,包 括检查周期等。在EsMaster压力过大的情况下,_cluster/health可能会造成误判。
作者 east
bug清单, Elasticsearch 2月 12,2021

ES实例磁盘空间不足,导致索引read-only

ES实例磁盘空间不足,导致索引read-only

题现象:

数据导入失败错误日志:

retrying failed action with response code: 403 ({“type”=>”cluster_block_exception”, “reason”=>”blocked by: [FORBIDDEN/12/index read-only / allow delete (api)]

问题原因:

磁盘空间不足,磁盘使用率大于95%,索引被强制设置为只读,导致数据无写入。

解决办法:

1. 下线磁盘空间不足的ES实例。

curl -XPUT --negotiate -k -u : "https://127.0.0.1:24100/_cluster/settings" -H 'Content-Type: application/json'  -d '{
"transient" : {
"cluster.routing.allocation.exclude._name" : "EsNode1@192.168.198.6, EsNode2@192.168.198.6 "
}
}'

2. 等待数据迁移完成。执行_cluster/healht命令查询relocating_shards参数的值,直到变为0,说明迁移完毕。

curl -XGET --negotiate -k -u : "https://127.0.0.1:24100/_cluster/health?pretty"

3. 修改索引只读字段属性为null,放开写入。

curl -XPUT --negotiate -k -u : "https://127.0.0.1:24100/*/_settings" -H 'Content-Type: application/json' -d '{"index.blocks.read_only_allow_delete": null}'

4. 继续写入数据。

作者 east
bug清单, Elasticsearch 2月 12,2021

es bulk入库数据丢失 分析思路

bulk入库数据丢失

【问题现象】

用户反馈数据,会生成报文,每天丢20%的报文,ES中存储的是2种日志,通过抽了2个业务日志做比对,反馈说有一些流水的号没有打出来,怀疑有丢失数据的情况

【分析过程】

建议业务单独入库疑似丢掉的数据,但是数据已经丢失,没法复现。

后续了解到业务是通过bulk批量方式入库的,但是bulk方式入库会有个现象:批量入库后会返回整体的成功信息,如果此批次里面有错误数据的话是不会报错的,同时也不会入库错误数据,带来的现象就是数据丢失。

随即本地模拟了bulk方式入库,如下入库3条数据,在其中构造出一条错误数据,可以看到整体是反馈成功的。

bulk入库数据丢失

后续通过查询索引只能查询出2条数据,如下:

bulk入库数据丢失

【处理建议】

1. 从入库数据源头提前了解到数据信息,防止错误数据入库。

2. 可以对代码二次开发进行每条入库数据解析,能及时观察到错误数据。

3. 单独入库每条数据,会对性能有较大影响。

作者 east
技术架构 2月 12,2021

直播间机器人设计方案

设计目标

1:模拟一定人数在房间,保证房间的人气

2:不同时段房间内房间机器人的人数要有波动,防止人数不真实

3:支持房间内做活动,需要临时增加大批量的用户

4:机器人不能出现大批量进入房间,大批量退出房间的情形

设计流程

1:增加robot进程进行通知机器人进入房间退出房间的处理

2:设计给机器人分配特定的号段区间 (例如:850000000-860000000)

2:robot进程读取配置文件,获取房间信息,以及房间的机器人配置信息流程

4:如有讲师在麦上,robot服务定时判断真实人数和在线人数的比例公式,判断是否需要增加或减少机器人,如果需要,则发起信令请求,消息流为:

robot->usermgrsvr->gateway->roomsvr

5:房间服务器获取到加入房间请求后,判断当前的最大机器人ID,然后从最大的机器人ID

往上累加,获取最新的机器人ID。(如果达到最高的配置860000000,则从最低850000000开始循环)。然后根据新增加机器人ID,做加入房间的处理.

6:房间服务器获取到退出房间的请求后,判断当前的最小机器人ID,然后删除指定的机器人数量

7: 如果没有讲师在麦上,robot服务逐步删除房间内的机器人,发起信令请求, 消息流为:

   robot->usermgrsvr->gateway->roomsvr,房间服务器处理为第6部。

配置文件

robot配置文件robot.conf如下信息:

[roomlist]        #房间列表配置

Roomid=60001,60002,60003

[onlineparam]

onlinenum=20   #机器人基础在线人数

onlinerate=1-200:30;201-500:20;501-2000:10;2001-1000000000:5 #机器人数比率

假设M为真实的在线总人数

当1<=M<=200时

Totalonline =  onlinenum + M * 30

当200<M<=500时

Totalonline = onlinenum + 200 * 30 + (M-200) * 20

当500<M<=2000时

Totalonline = onlinenum + 200 * 30 + 300 * 20 + (M-500) * 10

当2000<M<=1000000000时

Totalonline = onlinenum + 200 * 30 + 300 * 20 + 500 * 10 + (M-500) *5

作者 east
技术架构 2月 12,2021

Redis数据同步服务器(syncsvr)文档

架构图

流程图

初始化同步流程:

动态数据同步线程:

服务器部署

  1. 每个机房部署一个syncsvr服务器
  2. Syncsvr与其他机房的syncsvr相互连接
作者 east
技术架构 2月 11,2021

C++编码规范

一、    文件名命名规范

  1. 文件的名字需和承载的类之间有一定的关联性,而且常用的公共头文件需要定义得比较简短
  • 文件名采用全部小写的方式,不允许大小写混合的方式

二、    源程序文件

  1. 源文件段落依下列顺序:
  2. 序言
  3. 系统头文件引用(include)
  4. 用户头文件引用(include)
  5. 全局常量宏定义(define)
  6. 全局函数宏定义(define)
  7. 全局类型定义(typedef)
  8. 全局枚举类型定义(enums)
  9. 全局变量说明(extern)
  10. 全局变量说明(non-static)
  11. 全局变量说明(static)
  12. 函数(通常从最高层开始,按层次横向排列。如果定义较多的独立的公用函数,可以考虑按字母顺序排列。
  13. 序言内容应包括版权声明、内容描述、格式如下:

/*********************************************************************

 *  Copyright 2016  by 99letou.

 *  All right reserved.

 *

 *  功能:*****文件

 *

 *  Edit History:

 *

 *    2016/04/04 – Created by David.

 *    2006/04/06 – Modified by John to print output in the new form.

 */

  • 段落之间用空行分隔。
  • 文件长度尽可能在1000行之内。
  • 每行长度尽可能不要超过79列。

三、    头文件

  1. 头文件开头注释:

/**
 * Description: This is a test program
 */ 

  • 每个头文件采用下面的形式避免被重复引用:

#ifndef EXAMPLE_H

#define EXAMPLE_H

… /* body of example.h file */

#endif /* EXAMPLE_H */

  • 多个源文件引用的说明放入头文件中。
  • 说明函数或外部变量的头文件应在定义该函数或变量的文件中引用。
  • 引用头文件不要使用绝对路径。使用<filename.h>引用系统头文件;使用“filename.h””引用用户头文件。

四、    数据变量说明

  1. 常量的命名规范:

    常量名由全大写字母组成,单词间通过下划线来界定

  • 成员变量的命名规范:

    m+_+[变量类型]+变量名

    m后带上明确表达变量意义的英文名词而不要用难以表达意义的缩写。且m后的变量名首字母必须大写。如:

    class CMyGame

    {

        private :

           CPoint m_Point;<―――普通类型

           CGame* m_pGame;<―――指针类型

           Int m_nGameID;<―――整数类型

    }

  • 函数参数的命名规范:

采用波浪法来定义函数参数变量。同样的,也必须使用可以明确表达变量意义的英文名词,而不仅仅是缩写。

[变量类型]+变量名

如定义一个读取文件的函数,并且用参数传入一个文件名

public boolean readFile(String strFileName)

{

…

       m_sFileName = strFileName;

}

  • 局部变量的命名规范:

采用全部小写的方式定义局部变量名。而且尽量用有意义的名词作为变量名。

局部变量不需要在前面增加变量类型标识。

public boolean readFile()

{

              String filename = “e.ext”;

}

  • 局部循环变量的命名规范:

用小写的i、j、k依次作为循环变量

       如:

       for (int i = 0 ; i < 10 ; i ++ )

{

       for (int j = 0 ; j <10 ; j ++ )

       {

}

}

  • 临时变量的命名规范:

一般情况下尽量使用有意义的变量名,如果是某变量的临时变量,可采用前面增加tmp前缀的方式。如果实在没办法,可采用tmp、temp等作为临时变量名,但不可以过多定义诸如tmp1、tmp2等变量,如果出现此情况,则必定可以采用有意义的名词代替。

       int tmpserialno = mSerialNo++;

       tmpserialno %= 10;

       mSerialNo = tmpserialno;

  • 枚举常量

采用波浪法加E前缀来定义枚举常量。同样的,也必须使用可以明确表达变量意义的英文名词,而不仅仅是缩写。且E后首字母必须大写

正确写法:

enum ECHARTYPE
{
    CHARTYPE_SPACE = _ISspace,
    CHARTYPE_PRINT = _ISprint,
    CHARTYPE_CNTRL = _IScntrl,
};

错误写法:

enum ECHARTYPE{ SPACE = _ISspace, PRINT = _ISprint, CNTRL = _IScntrl };

  • 变量定义范围建议:

尽量在变量的有效范围内定义之,如果一个变量仅仅在某个函数内使用到,则把其定义为一个成员变量就是不适合的。在如某些变量只在循环内用到,则应该在循环体内定义之,而不要随意括大其定义范围。

  • 变量类型:

基本类型(保留类型)

char c cMyChar;
bool b bMyBool;
int/short/long n nMyInt;
float/double f fMyFloat;
Long64 l lMyLong;
String/char*(当明确知道是用作字符串的情况下) str strMyString
map map mapPlayers
vector vec vecPlayers
list lst lstPlayers
multimap mmap mmapState

特殊类型

Handle h hFile;
  1. 指针类型:

在变量类前增加p标识,作为标识此变量为指针类型,如:

       int *pKey = NULL;

       CDateTime* pDateTime = new CDateTime(0);

  1. 数组变量命名规范:

对于数组类型的变量,需要采用复数s以标识此为数组变量。如:

int m_nKeys[100];

double dValues[200];

CMyClass Strings[200];

特例:对于char buf[200]这种定义,由于其使用习惯原因,不需要采用数组前缀。

       对于数组指针变量,同样在类型前增加p标识。在删除的时候,必须用delete[]的方式删除动态数组,以保证数组内的实例被调用析构函数。

       CDateTime* pBirthdays = new CDateTime[20];

    ….

       delete[] pBirthdays;

       int* m_pnKeys = new int[20];

五、    类说明

  1. 类名命名规范

       根据各种类的类型和用途,采用不同前缀+名词的命名方式。名词采用波浪法,必须使用可以明确表达变量意义的英文名词。

  • 前缀
  • 普通类(C)

       一般类,采用C+名词的方式命名

例如:

Class CPerson

{

Protected :

String m_strName;

String m_strNickName;
};

  • 接口类(I)

    对于无任何实现的纯虚类,称为接口类,这些类的特点都是无任何成员变量,存在需要其他实现类实现的纯虚函数。

       接口类必须采用I+名词的方式命名。

例如:

class IDataInput

{

       Public :

              virtual ~IDataInput() {};

              virtual void read() = 0;

}

  • 结构体(T)

       Struct,结构体,必须以T+名词的方式命名。

例如:

       typedef struct _t_mystruct

       {

              Unsigned int number;

              Unsigned int value;

              Char name[255];

       }TMyStruct,* TMyStructPtr;

  • 模板类

       模板类,必须以全小写命名。

例如:

template<class T,allocator A>

class screen : public map<T,A>

{
}

  • 类成员的初始化(Member initialization lists)

成员的初始化必须在构造函数名的下一行开始

正确写法:

gribble::gribble()
:m_private_data(0), m_more_stuff(0), m_helper(0)
{
}

错误写法:

gribble::gribble():m_private_data(0),m_more_stuff(0), m_helper(0)
{
}

  • 类成员变量必须采用private的定义,不允许使用public定义,并置于类定义的最后,另外用getter和setter的函数访问和修改之(在需要考虑程序大小的时候可以忽略此规则)

    class CTest

    {

           public : 

    int getTopicID()      //获取话题ID

    { 

    return m_nTopicID;
    }

    void setTopicID(int nTopicID) //设置话题id

           {

                  m_nTopicID = nTopicID;

           }

           private:

      TInt m_nTopicID;

      }

  • 一个方法只完成一个任务,不要把多个任务放在一个方法中,即使那些任务非常小
  • 功能类的方法的大小尽可能不要超过100行

六、    函数说明

  1. 每个函数前加入注释块,描述函数功能、输入参数和返回值,必要时应说明其功能、用法、重要设计决策与副作用。

/**

    * @description : PrintOneMsg

    * @input param : nUserID     — 用户ID

    * @output param:  nMoney– 玩家体力

    * @return: 0  — success

               other — false

   * @exception CException reason

 */

int PrintOneMsg((int nUserID,int & nMoney)

{

function body;

return 0;

}

  • 函数名称原则上采用动词名词的组合形式,函数名称采用波浪法,第一个单词首字母采用小写,后面的单词的首字母采用大写

如:int getTopicID()

  • 函数的参数个数尽可能不要超过5个。
  • 函数体的开、闭花括号写在第一列,分别占一行。函数体的局部变量说明和代码缩进4格。
  • 业务逻辑函数的大小尽可能不要超过200行

七、    代码注释规范

为了能更好的体现代码即详细设计文档这个意图,在对代码注释的时候,需遵守下列的规范。

  1. 用“注释块”描述数据结构、算法等,放在被注释的程序段前:

/*

 *  Here is a block comment.

 *  The opening slash-star and closing star-slash are alone on a line.

 *  …

     */

  • “单行注释”放在被注释的程序段前,并与该程序段对齐:

if (argc > 1)

{

    // Get input file frmm command line

if (freopen(argv[1], “r”, stdin) == NULL)

{

        perror(argv[1]);

    }

}

  • 放在代码行尾的“短注释”与被注释的代码分开至少一个空格:

if (a == EXCEPTION)

{

b = TRUE;           // special case

    BODY

}

else

{

b = isprime(a);     //works only for odd a

BODY

}

  • 函数抛出异常注释规范

对于可能抛出异常的类方法、函数,在注释中说明所抛出异常的类名和产生异常的原因;

注释中采用如下语法

/**

* @exception fully-qualified-class-name description

*/

fully-qualified-class-name:方法声明的异常名

description:产生异常的原因

例如:

  /**

   * 连接数据库

   * @ exception CSQLException 数据库连接失败,具体原因请根据sqlcode查阅数据库错误代码说明

   */

virtual bool connect()=0;

八、    构造与析构

  1. 类构造函数,做非资源变量的初始化动作,原则上不进行任何可能出现错误的操作,如分配内存,调用资源等。
  2. delete 与new ,free与malloc,delete[] 与new[]必须成对使用,否则不保证会不会出现问题。

九、    异常处理

  1. 所有的异常抛出都必须以对象形式,而不是能以new 的指针形式。而捕获的时候就可以统一用引用的方式进行捕获。这样在性能和开销方面不会加大的同时,也无需关心指针的删除问题。

       try

       {

              throw CDateTimeException(“datetime format error”);

       }

       catch (CDateTimeException& e)

       {

              cout<<e.what()<<end;

       }

十、    其他良好的编程习惯

  1. 缩进采用tab而不是用space;tab的缩进显示距离建议为4个空格
  2. 用一个空行来分开代码和逻辑的分组;
  3. 花括号“{”、“}”需独立一行,而不像if for等可以和括号同一行,而且必须与if等缩进相同的空间

如:if ( test == 1 )

              {

       }

  • 在每个运算符和括号的前后都空一格。
  • 无warning编译
  • 在switch语句中出现的fall-through应加以注释:

switch (expr)

{

case ABC:  //注释

{

statement

break;

}

case DEF: //注释

{

statement

break;

}

     default: XYZ:

     {

       statement;

break;

}

}

作者 east

上一 1 … 3 4 5 下一个

关注公众号“大模型全栈程序员”回复“小程序”获取1000个小程序打包源码。回复”chatgpt”获取免注册可用chatgpt。回复“大数据”获取多本大数据电子书

标签

AIGC AI创作 bert chatgpt github GPT-3 gpt3 GTP-3 hive mysql O2O tensorflow UI控件 不含后台 交流 共享经济 出行 图像 地图定位 外卖 多媒体 娱乐 小程序 布局 带后台完整项目 开源项目 搜索 支付 效率 教育 日历 机器学习 深度学习 物流 用户系统 电商 画图 画布(canvas) 社交 签到 联网 读书 资讯 阅读 预订

官方QQ群

小程序开发群:74052405

大数据开发群: 952493060

近期文章

  • 详解Python当中的pip常用命令
  • AUTOSAR如何在多个供应商交付的配置中避免ARXML不兼容?
  • C++thread pool(线程池)设计应关注哪些扩展性问题?
  • 各类MCAL(Microcontroller Abstraction Layer)如何与AUTOSAR工具链解耦?
  • 如何设计AUTOSAR中的“域控制器”以支持未来扩展?
  • C++ 中避免悬挂引用的企业策略有哪些?
  • 嵌入式电机:如何在低速和高负载状态下保持FOC(Field-Oriented Control)算法的电流控制稳定?
  • C++如何在插件式架构中使用反射实现模块隔离?
  • C++如何追踪内存泄漏(valgrind/ASan等)并定位到业务代码?
  • C++大型系统中如何组织头文件和依赖树?

文章归档

  • 2025年6月
  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年1月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年7月
  • 2018年6月

分类目录

  • Android (73)
  • bug清单 (79)
  • C++ (34)
  • Fuchsia (15)
  • php (4)
  • python (43)
  • sklearn (1)
  • 云计算 (20)
  • 人工智能 (61)
    • chatgpt (21)
      • 提示词 (6)
    • Keras (1)
    • Tensorflow (3)
    • 大模型 (1)
    • 智能体 (4)
    • 深度学习 (14)
  • 储能 (44)
  • 前端 (4)
  • 大数据开发 (488)
    • CDH (6)
    • datax (4)
    • doris (30)
    • Elasticsearch (15)
    • Flink (78)
    • flume (7)
    • Hadoop (19)
    • Hbase (23)
    • Hive (40)
    • Impala (2)
    • Java (71)
    • Kafka (10)
    • neo4j (5)
    • shardingsphere (6)
    • solr (5)
    • Spark (99)
    • spring (11)
    • 数据仓库 (9)
    • 数据挖掘 (7)
    • 海豚调度器 (10)
    • 运维 (34)
      • Docker (3)
  • 小游戏代码 (1)
  • 小程序代码 (139)
    • O2O (16)
    • UI控件 (5)
    • 互联网类 (23)
    • 企业类 (6)
    • 地图定位 (9)
    • 多媒体 (6)
    • 工具类 (25)
    • 电商类 (22)
    • 社交 (7)
    • 行业软件 (7)
    • 资讯读书 (11)
  • 嵌入式 (70)
    • autosar (63)
    • RTOS (1)
    • 总线 (1)
  • 开发博客 (16)
    • Harmony (9)
  • 技术架构 (6)
  • 数据库 (32)
    • mongodb (1)
    • mysql (13)
    • pgsql (2)
    • redis (1)
    • tdengine (4)
  • 未分类 (6)
  • 程序员网赚 (20)
    • 广告联盟 (3)
    • 私域流量 (5)
    • 自媒体 (5)
  • 量化投资 (4)
  • 面试 (14)

功能

  • 登录
  • 文章RSS
  • 评论RSS
  • WordPress.org

All Rights Reserved by Gitweixin.本站收集网友上传代码, 如有侵犯版权,请发邮件联系yiyuyos@gmail.com删除.